-- DuckDB SQL Schema Definition for Eurovision 25 Homereview Backend
-- Generated from schema documentation.
-- Target Database: DuckDB
-- Incorporates Sequences for Auto-Incrementing Primary Keys.
-- Note: Timestamps default to creation time; application logic should handle 'updated_at' updates.

-- Drop objects in reverse order of dependency and existence check
DROP TABLE IF EXISTS Review;
DROP TABLE IF EXISTS Song;
DROP TABLE IF EXISTS "User"; -- Quoted because USER is a reserved keyword
DROP TABLE IF EXISTS Team;
DROP TABLE IF EXISTS Contest;
DROP TABLE IF EXISTS CountryCodes;
DROP VIEW IF EXISTS ReviewSummary;
DROP VIEW IF EXISTS ReviewSummaryByTeam;

DROP SEQUENCE IF EXISTS group_id_seq;
DROP SEQUENCE IF EXISTS user_id_seq;
DROP SEQUENCE IF EXISTS song_id_seq;
DROP SEQUENCE IF EXISTS review_id_seq;
DROP SEQUENCE IF EXISTS contest_id_seq;

-- =============================================================================
-- Sequences for Primary Keys
-- =============================================================================
CREATE SEQUENCE group_id_seq START 1;
CREATE SEQUENCE user_id_seq START 1;
CREATE SEQUENCE song_id_seq START 1;
CREATE SEQUENCE review_id_seq START 1;
CREATE SEQUENCE contest_id_seq START 1;

-- =============================================================================
-- Table: Contest
-- Stores information about Eurovision contests by year.
-- =============================================================================
CREATE TABLE Contest (
    id INTEGER PRIMARY KEY DEFAULT nextval('contest_id_seq'), -- Use sequence for auto-increment
    year INTEGER DEFAULT EXTRACT(YEAR FROM CURRENT_DATE) NOT NULL, -- The year of the Eurovision contest
    is_active BOOLEAN DEFAULT TRUE NOT NULL,                -- Flag indicating if this is the active contest
    finals_date DATE NOT NULL,                                       -- Date of the finals
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,           -- Timestamp when the contest was created
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP            -- Timestamp when the contest was last updated
);

-- Add index for faster lookups by year
CREATE INDEX idx_contest_year ON Contest (year);

-- =============================================================================
-- Table: Group
-- Stores information about the different households or groups participating.
-- =============================================================================
CREATE TABLE "Team" (
    id INTEGER PRIMARY KEY DEFAULT nextval('group_id_seq'), -- Use sequence for auto-increment
    name VARCHAR UNIQUE NOT NULL,                           -- The name of the household/group
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,           -- Timestamp when the group was created
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP            -- Timestamp when the group was last updated
);

-- =============================================================================
-- Table: User
-- Stores information about individual users (players and admins).
-- =============================================================================
CREATE TABLE "User" (
    id INTEGER PRIMARY KEY DEFAULT nextval('user_id_seq'), -- Use sequence for auto-increment
    username VARCHAR UNIQUE NOT NULL,                       -- The user's login name
    first_name VARCHAR DEFAULT '',
    last_name VARCHAR DEFAULT '',
    hashed_password VARCHAR NOT NULL,                       -- The securely hashed password
    email VARCHAR UNIQUE,                                   -- User's email address (nullable)
    team_id INTEGER NOT NULL,                              -- Foreign Key -> Group.id
    avatar_id INTEGER DEFAULT 0 NOT NULL,                   -- Identifier for the user's avatar
    is_active BOOLEAN DEFAULT TRUE NOT NULL,                -- Flag indicating if the user account is active
    is_admin BOOLEAN DEFAULT FALSE NOT NULL,                -- Flag indicating if the user has admin privileges
    last_login TIMESTAMP DEFAULT '1970-01-01 00:00:00',           -- Timestamp when the user was last logged in. Epoch (1970-01-01) means "never logged in"
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,           -- Timestamp when the user was created
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,           -- Timestamp when the user was last updated

    FOREIGN KEY (team_id) REFERENCES "Team"(id)           -- Link to the Team table
);

-- =============================================================================
-- Table: Song
-- Stores information about each participating song in the contest.
-- =============================================================================
CREATE TABLE Song (
    id INTEGER PRIMARY KEY DEFAULT nextval('song_id_seq'), -- Use sequence for auto-increment
    year INTEGER NOT NULL,                                  -- The year of the Eurovision contest
    country VARCHAR NOT NULL,                               -- The participating country name
    artist VARCHAR NOT NULL,                                -- The name of the performing artist(s)
    title VARCHAR NOT NULL,                                 -- The title of the song
    running_order INTEGER NOT NULL,                         -- Official order in the show (nullable)
    lyrics_url VARCHAR,                                     -- URL to the original lyrics (nullable)
    artist_url VARCHAR,                                     -- URL to the artist's page (nullable)
    flag_url VARCHAR,                                       -- URL to the country flag (nullable)
    lyrics_original VARCHAR,                                -- Original lyrics (nullable)
    lyrics_translation_fi VARCHAR,                          -- Finnish translation (nullable)
    tags VARCHAR[],                                         -- Comma-separated tags (nullable)
    confidence FLOAT NOT NULL DEFAULT 0.0,                  -- Confidence level of the translation (nullable)
    language VARCHAR NOT NULL,                              -- Language of the song (nullable)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,           -- Timestamp when the song entry was created
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP            -- Timestamp when the song entry was last updated
);

-- Add index for faster lookups by year as specified in documentation
CREATE INDEX idx_song_year ON Song (year);

-- =============================================================================
-- Table: Review
-- Stores the scores and comments submitted by a user for a specific song.
-- =============================================================================
CREATE TABLE Review (
    id INTEGER PRIMARY KEY DEFAULT nextval('review_id_seq'), -- Use sequence for auto-increment
    user_id INTEGER NOT NULL,                               -- Foreign Key -> User.id
    song_id INTEGER NOT NULL,                               -- Foreign Key -> Song.id
    score_song INTEGER NOT NULL,                            -- Score (1-100) for song quality
    score_show INTEGER NOT NULL,                            -- Score (1-100) for the stage show
    score_costume INTEGER NOT NULL,                        -- Score (1-100) for wardrobe/costumes
    text_review VARCHAR,                                    -- Optional textual comments (nullable)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,           -- Timestamp when the review was created
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,           -- Timestamp when the review was last modified

    FOREIGN KEY (user_id) REFERENCES "User"(id),            -- Link to the User table
    FOREIGN KEY (song_id) REFERENCES Song(id),              -- Link to the Song table

    -- Ensure scores are within the valid range (1-100)
    CHECK (score_song >= 1 AND score_song <= 100),
    CHECK (score_show >= 1 AND score_show <= 100),
    CHECK (score_costume >= 1 AND score_costume <= 100),

    -- Ensure each user can only submit one review per song
    UNIQUE (user_id, song_id)
);

CREATE TABLE CountryCodes (
    code VARCHAR PRIMARY KEY,
    name_en VARCHAR NOT NULL,
    name_fi VARCHAR NOT NULL,
    name_sv VARCHAR NOT NULL
);

CREATE VIEW ReviewSummaryGlobal AS
SELECT 
    song_id,
    cc.name_fi AS country_fi,
    cc.name_sv AS country_sv,
    s.artist,
    s.title,
    COUNT(*) AS total_reviews,
    AVG(score_song) AS avg_score_song,
    AVG(score_show) AS avg_score_show,
    AVG(score_costume) AS avg_score_costume,
    AVG((score_song + score_show + score_costume)/3) AS avg_total_score
FROM Review r
JOIN Song s ON r.song_id = s.id
JOIN CountryCodes cc ON s.country = cc.code
GROUP BY song_id, cc.name_fi, cc.name_sv, s.artist, s.title
ORDER BY avg_total_score DESC;

CREATE VIEW ReviewSummaryByTeam AS
SELECT 
    r.song_id,
    cc.name_fi AS country_fi,
    cc.name_sv AS country_sv,
    s.artist,
    s.title,
    u.team_id,
    COUNT(*) AS total_reviews,
    AVG(r.score_song) AS avg_score_song,
    AVG(r.score_show) AS avg_score_show,
    AVG(r.score_costume) AS avg_score_costume,
    AVG((r.score_song + r.score_show + r.score_costume)/3) AS avg_total_score
FROM Review r
JOIN "User" u ON r.user_id = u.id
JOIN Song s ON r.song_id = s.id
JOIN CountryCodes cc ON s.country = cc.code
GROUP BY r.song_id, u.team_id, cc.name_fi, cc.name_sv, s.artist, s.title
ORDER BY avg_total_score DESC;

-- Insert country codes data
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('ALB', 'Albania', 'Albania', 'Albanien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('ARM', 'Armenia', 'Armenia', 'Armenien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('AUS', 'Australia', 'Australia', 'Australien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('AUT', 'Austria', 'Itävalta', 'Österrike');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('AZE', 'Azerbaijan', 'Azerbaidžan', 'Azerbajdzjan');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('BEL', 'Belgium', 'Belgia', 'Belgien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('HRV', 'Croatia', 'Kroatia', 'Kroatien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('CYP', 'Cyprus', 'Kypros', 'Cypern');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('CZE', 'Czechia', 'Tšekki', 'Tjeckien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('DNK', 'Denmark', 'Tanska', 'Danmark');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('EST', 'Estonia', 'Viro', 'Estland');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('FIN', 'Finland', 'Suomi', 'Finland');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('FRA', 'France', 'Ranska', 'Frankrike');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('GEO', 'Georgia', 'Georgia', 'Georgien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('DEU', 'Germany', 'Saksa', 'Tyskland');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('GRC', 'Greece', 'Kreikka', 'Grekland');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('ISL', 'Iceland', 'Islanti', 'Island');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('IRL', 'Ireland', 'Irlanti', 'Irland');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('ISR', 'Israel', 'Israel', 'Israel');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('ITA', 'Italy', 'Italia', 'Italien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('LVA', 'Latvia', 'Latvia', 'Lettland');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('LTU', 'Lithuania', 'Liettua', 'Litauen');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('LUX', 'Luxembourg', 'Luxemburg', 'Luxemburg');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('MLT', 'Malta', 'Malta', 'Malta');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('MNE', 'Montenegro', 'Montenegro', 'Montenegro');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('NLD', 'Netherlands', 'Alankomaat', 'Nederländerna');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('NOR', 'Norway', 'Norja', 'Norge');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('POL', 'Poland', 'Puola', 'Polen');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('PRT', 'Portugal', 'Portugali', 'Portugal');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('SMR', 'San Marino', 'San Marino', 'San Marino');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('SRB', 'Serbia', 'Serbia', 'Serbien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('SVN', 'Slovenia', 'Slovenia', 'Slovenien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('ESP', 'Spain', 'Espanja', 'Spanien');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('SWE', 'Sweden', 'Ruotsi', 'Sverige');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('CHE', 'Switzerland', 'Sveitsi', 'Schweiz');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('UKR', 'Ukraine', 'Ukraina', 'Ukraina');
INSERT INTO CountryCodes (code, name_en, name_fi, name_sv) VALUES ('GBR', 'United Kingdom', 'Englanti', 'Storbritannien');


-- TODO: Clean this next year. Its now here just to get the show running
INSERT INTO Contest (year, finals_date) VALUES (2025, '2025-05-16');
-- =============================================================================
-- Views (Optional - Not Created Here Based on Documentation Decision)
-- =============================================================================
-- The documentation suggests performing result aggregations in the application
-- layer. No CREATE VIEW statements are included.
-- =============================================================================

-- End of Schema Definition