-- Initial database schema for crossword puzzle application
-- This migration creates the basic tables for topics, words, and clues

CREATE TABLE IF NOT EXISTS topics (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL UNIQUE,
    description TEXT,
    difficulty VARCHAR(20) DEFAULT 'medium' CHECK (difficulty IN ('easy', 'medium', 'hard')),
    word_count INTEGER DEFAULT 0,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS words (
    id SERIAL PRIMARY KEY,
    word VARCHAR(50) NOT NULL,
    length INTEGER NOT NULL,
    topic_id INTEGER REFERENCES topics(id) ON DELETE CASCADE,
    difficulty VARCHAR(20) DEFAULT 'medium' CHECK (difficulty IN ('easy', 'medium', 'hard')),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT unique_word_topic UNIQUE (word, topic_id)
);

CREATE TABLE IF NOT EXISTS clues (
    id SERIAL PRIMARY KEY,
    word_id INTEGER REFERENCES words(id) ON DELETE CASCADE,
    clue_text TEXT NOT NULL,
    difficulty VARCHAR(20) DEFAULT 'medium' CHECK (difficulty IN ('easy', 'medium', 'hard')),
    is_primary BOOLEAN DEFAULT true,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS generated_puzzles (
    id SERIAL PRIMARY KEY,
    grid_data JSONB NOT NULL,
    clues_data JSONB NOT NULL,
    metadata JSONB,
    topics TEXT[] NOT NULL,
    difficulty VARCHAR(20) DEFAULT 'medium',
    word_count INTEGER,
    grid_size INTEGER,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    expires_at TIMESTAMP WITH TIME ZONE DEFAULT (CURRENT_TIMESTAMP + INTERVAL '24 hours')
);

-- Indexes for better query performance
CREATE INDEX IF NOT EXISTS idx_words_topic_id ON words(topic_id);
CREATE INDEX IF NOT EXISTS idx_words_length ON words(length);
CREATE INDEX IF NOT EXISTS idx_words_difficulty ON words(difficulty);
CREATE INDEX IF NOT EXISTS idx_clues_word_id ON clues(word_id);
CREATE INDEX IF NOT EXISTS idx_clues_primary ON clues(is_primary);
CREATE INDEX IF NOT EXISTS idx_puzzles_topics ON generated_puzzles USING GIN(topics);
CREATE INDEX IF NOT EXISTS idx_puzzles_difficulty ON generated_puzzles(difficulty);
CREATE INDEX IF NOT EXISTS idx_puzzles_expires ON generated_puzzles(expires_at);

-- Function to update word count in topics table
CREATE OR REPLACE FUNCTION update_topic_word_count()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' THEN
        UPDATE topics 
        SET word_count = word_count + 1, updated_at = CURRENT_TIMESTAMP
        WHERE id = NEW.topic_id;
        RETURN NEW;
    ELSIF TG_OP = 'DELETE' THEN
        UPDATE topics 
        SET word_count = word_count - 1, updated_at = CURRENT_TIMESTAMP
        WHERE id = OLD.topic_id;
        RETURN OLD;
    END IF;
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- Trigger to automatically update word count
CREATE TRIGGER trigger_update_word_count
    AFTER INSERT OR DELETE ON words
    FOR EACH ROW
    EXECUTE FUNCTION update_topic_word_count();

-- Function to clean up expired puzzles
CREATE OR REPLACE FUNCTION cleanup_expired_puzzles()
RETURNS INTEGER AS $$
DECLARE
    deleted_count INTEGER;
BEGIN
    DELETE FROM generated_puzzles WHERE expires_at < CURRENT_TIMESTAMP;
    GET DIAGNOSTICS deleted_count = ROW_COUNT;
    RETURN deleted_count;
END;
$$ LANGUAGE plpgsql;