-- Virtual Art Gallery — canonical PostgreSQL schema
-- Applied by: npm run dev:migrate (server/migrate.js)
-- Incremental ALTER migrations in db/migrate-*.sql run after this on existing databases.

CREATE TABLE IF NOT EXISTS historical_eras (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    start_year INTEGER NOT NULL,
    end_year INTEGER NOT NULL,
    start_definite BOOLEAN DEFAULT true,
    end_definite BOOLEAN DEFAULT true,
    description TEXT,
    sort_order INTEGER DEFAULT 0
);

CREATE TABLE IF NOT EXISTS art_movements (
    id SERIAL PRIMARY KEY,
    name VARCHAR(150) NOT NULL,
    start_year INTEGER NOT NULL,
    end_year INTEGER NOT NULL,
    start_definite BOOLEAN DEFAULT true,
    end_definite BOOLEAN DEFAULT true,
    era_id INTEGER REFERENCES historical_eras(id),
    description TEXT,
    color VARCHAR(20) DEFAULT '#8B7355'
);

CREATE TABLE IF NOT EXISTS artists (
    id SERIAL PRIMARY KEY,
    name VARCHAR(200) NOT NULL,
    birth_year INTEGER,
    death_year INTEGER,
    movement_id INTEGER REFERENCES art_movements(id),
    portrait_path VARCHAR(500),
    portrait_thumb_path VARCHAR(500),
    bio_short TEXT,
    bio_full TEXT,
    wikipedia_title VARCHAR(300),
    century INTEGER,
    checkup_checked BOOLEAN NOT NULL DEFAULT false,
    checkup_fixed BOOLEAN NOT NULL DEFAULT false,
    palette_metadata JSONB
);

CREATE TABLE IF NOT EXISTS artist_periods (
    id SERIAL PRIMARY KEY,
    artist_id INTEGER NOT NULL REFERENCES artists(id) ON DELETE CASCADE,
    name VARCHAR(200) NOT NULL,
    start_year INTEGER,
    end_year INTEGER,
    description TEXT,
    sort_order INTEGER DEFAULT 0
);

CREATE TABLE IF NOT EXISTS paintings (
    id SERIAL PRIMARY KEY,
    artist_id INTEGER NOT NULL REFERENCES artists(id) ON DELETE CASCADE,
    period_id INTEGER REFERENCES artist_periods(id),
    title VARCHAR(300) NOT NULL,
    year INTEGER,
    year_end INTEGER,
    description TEXT,
    curator_notes TEXT NOT NULL DEFAULT '',
    image_path VARCHAR(500),
    thumbnail_path VARCHAR(500),
    wikipedia_title VARCHAR(300),
    sort_order INTEGER DEFAULT 0,
    checkup_checked BOOLEAN NOT NULL DEFAULT false,
    checkup_fixed BOOLEAN NOT NULL DEFAULT false
);

CREATE TABLE IF NOT EXISTS painting_influences (
    id SERIAL PRIMARY KEY,
    painting_id INTEGER NOT NULL REFERENCES paintings(id) ON DELETE CASCADE,
    influenced_by_painting_id INTEGER NOT NULL REFERENCES paintings(id) ON DELETE CASCADE,
    notes TEXT,
    source VARCHAR(500),
    aspects TEXT,
    quote TEXT,
    source_author VARCHAR(200),
    source_url VARCHAR(500),
    UNIQUE(painting_id, influenced_by_painting_id)
);

CREATE TABLE IF NOT EXISTS painting_influence_sources (
    id SERIAL PRIMARY KEY,
    painting_id INTEGER NOT NULL REFERENCES paintings(id) ON DELETE CASCADE,
    source_type VARCHAR(20) NOT NULL CHECK (source_type IN ('painting', 'artist', 'movement')),
    source_painting_id INTEGER REFERENCES paintings(id) ON DELETE CASCADE,
    source_artist_id INTEGER REFERENCES artists(id) ON DELETE CASCADE,
    source_movement_id INTEGER REFERENCES art_movements(id) ON DELETE CASCADE,
    period_note VARCHAR(240),
    period_start_year INTEGER,
    period_end_year INTEGER,
    notes TEXT,
    source VARCHAR(500),
    aspects TEXT,
    quote TEXT,
    source_author VARCHAR(200),
    source_url VARCHAR(500),
    discovered_via VARCHAR(120),
    confidence VARCHAR(20) NOT NULL DEFAULT 'curated',
    CONSTRAINT painting_influence_sources_source_shape CHECK (
        (source_type = 'painting' AND source_painting_id IS NOT NULL AND source_artist_id IS NULL AND source_movement_id IS NULL)
        OR (source_type = 'artist' AND source_artist_id IS NOT NULL AND source_painting_id IS NULL AND source_movement_id IS NULL)
        OR (source_type = 'movement' AND source_movement_id IS NOT NULL AND source_painting_id IS NULL AND source_artist_id IS NULL)
    )
);

CREATE TABLE IF NOT EXISTS painting_annotations (
    id SERIAL PRIMARY KEY,
    painting_id INTEGER NOT NULL REFERENCES paintings(id) ON DELETE CASCADE,
    label VARCHAR(80),
    body TEXT NOT NULL,
    category VARCHAR(30) NOT NULL DEFAULT 'subject',
    pos_x NUMERIC(5, 2),
    pos_y NUMERIC(5, 2),
    source_author VARCHAR(200),
    source VARCHAR(500),
    source_url VARCHAR(500),
    sort_order INTEGER NOT NULL DEFAULT 0,
    confidence VARCHAR(20) NOT NULL DEFAULT 'curated'
);

CREATE INDEX IF NOT EXISTS idx_artists_movement ON artists(movement_id);
CREATE INDEX IF NOT EXISTS idx_artists_birth_year ON artists(birth_year);
CREATE INDEX IF NOT EXISTS idx_artists_death_year ON artists(death_year);
CREATE INDEX IF NOT EXISTS idx_artists_century ON artists(century);
CREATE INDEX IF NOT EXISTS artists_checkup_checked_idx ON artists (checkup_checked);
CREATE INDEX IF NOT EXISTS artists_checkup_fixed_idx ON artists (checkup_fixed);
CREATE INDEX IF NOT EXISTS artists_palette_metadata_idx ON artists USING gin (palette_metadata);

CREATE INDEX IF NOT EXISTS idx_paintings_artist ON paintings(artist_id);
CREATE INDEX IF NOT EXISTS idx_paintings_period ON paintings(period_id);
CREATE INDEX IF NOT EXISTS paintings_checkup_checked_idx ON paintings (checkup_checked);
CREATE INDEX IF NOT EXISTS paintings_checkup_fixed_idx ON paintings (checkup_fixed);

CREATE INDEX IF NOT EXISTS idx_movements_era ON art_movements(era_id);
CREATE INDEX IF NOT EXISTS idx_movements_years ON art_movements(start_year, end_year);

CREATE INDEX IF NOT EXISTS idx_influences_painting ON painting_influences(painting_id);
CREATE INDEX IF NOT EXISTS idx_influences_by ON painting_influences(influenced_by_painting_id);

CREATE UNIQUE INDEX IF NOT EXISTS painting_influence_sources_unique
    ON painting_influence_sources (
        painting_id,
        source_type,
        COALESCE(source_painting_id, 0),
        COALESCE(source_artist_id, 0),
        COALESCE(source_movement_id, 0)
    );

CREATE INDEX IF NOT EXISTS painting_influence_sources_painting_idx
    ON painting_influence_sources (painting_id);

CREATE INDEX IF NOT EXISTS idx_influence_sources_source_painting
    ON painting_influence_sources (source_painting_id);

CREATE INDEX IF NOT EXISTS painting_influence_sources_artist_idx
    ON painting_influence_sources (source_artist_id);

CREATE INDEX IF NOT EXISTS painting_influence_sources_movement_idx
    ON painting_influence_sources (source_movement_id);

CREATE INDEX IF NOT EXISTS painting_annotations_painting_idx
    ON painting_annotations (painting_id);
