-- =============================================================================
-- INVY — Production Migration Script
-- =============================================================================
-- SAFE: Additive-only.  Nothing is dropped.  All blocks are idempotent.
-- Run once to bring a production DB (old schema) in sync with the new schema.
--
-- Order of execution:
--   1. Enable extensions
--   2. Create new tables (IF NOT EXISTS)
--   3. Patch existing tables (ADD COLUMN IF NOT EXISTS / ALTER/ADD CONSTRAINT)
--   4. Migrate old `guests` rows → `guests_v2`  (only when guests_v2 is empty)
--   5. Add indexes and triggers (IF NOT EXISTS)
-- =============================================================================

-- =============================================================================
-- STEP 1 — Enable UUID extension
-- =============================================================================
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";


-- =============================================================================
-- STEP 2a — Create `users` table
-- =============================================================================
CREATE TABLE IF NOT EXISTS users (
    id         UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    email      TEXT NOT NULL UNIQUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);


-- =============================================================================
-- STEP 2b — Create `events` table
-- =============================================================================
CREATE TABLE IF NOT EXISTS events (
    id         UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    name       TEXT NOT NULL,
    date       TIMESTAMP WITH TIME ZONE,
    location   TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_events_created_at ON events(created_at);


-- =============================================================================
-- STEP 2c — Create `event_members` table
-- =============================================================================
CREATE TABLE IF NOT EXISTS event_members (
    id           UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    event_id     UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
    user_id      UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    role         TEXT NOT NULL DEFAULT 'admin'
                     CHECK (role IN ('admin', 'editor', 'viewer')),
    display_name TEXT,
    created_at   TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(event_id, user_id)
);
CREATE INDEX IF NOT EXISTS idx_event_members_event_id   ON event_members(event_id);
CREATE INDEX IF NOT EXISTS idx_event_members_user_id    ON event_members(user_id);
CREATE INDEX IF NOT EXISTS idx_event_members_event_user ON event_members(event_id, user_id);


-- =============================================================================
-- STEP 2d — Create `guests_v2` table
-- =============================================================================
CREATE TABLE IF NOT EXISTS guests_v2 (
    id               UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    event_id         UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
    added_by_user_id UUID NOT NULL REFERENCES users(id),

    -- identity
    first_name  TEXT NOT NULL,
    last_name   TEXT NOT NULL DEFAULT '',
    email       TEXT,
    phone       TEXT,          -- legacy alias
    phone_number TEXT,

    -- RSVP
    rsvp_status    TEXT NOT NULL DEFAULT 'invited'
                       CHECK (rsvp_status IN ('invited', 'confirmed', 'declined')),
    meal_preference TEXT,

    -- plus-one
    has_plus_one BOOLEAN DEFAULT FALSE,
    plus_one_name TEXT,

    -- seating
    table_number TEXT,
    side         TEXT,   -- e.g. "groom", "bride"

    -- provenance
    owner_email TEXT,
    source      TEXT NOT NULL DEFAULT 'manual'
                    CHECK (source IN ('google', 'manual', 'self-service')),

    notes      TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_guests_v2_event_id         ON guests_v2(event_id);
CREATE INDEX IF NOT EXISTS idx_guests_v2_added_by         ON guests_v2(added_by_user_id);
CREATE INDEX IF NOT EXISTS idx_guests_v2_event_user       ON guests_v2(event_id, added_by_user_id);
CREATE INDEX IF NOT EXISTS idx_guests_v2_phone_number     ON guests_v2(phone_number);
CREATE INDEX IF NOT EXISTS idx_guests_v2_event_phone      ON guests_v2(event_id, phone_number);
CREATE INDEX IF NOT EXISTS idx_guests_v2_event_status     ON guests_v2(event_id, rsvp_status);
CREATE INDEX IF NOT EXISTS idx_guests_v2_owner_email      ON guests_v2(event_id, owner_email);
CREATE INDEX IF NOT EXISTS idx_guests_v2_source           ON guests_v2(event_id, source);


-- =============================================================================
-- STEP 2e — Create `rsvp_tokens` table
-- =============================================================================
CREATE TABLE IF NOT EXISTS rsvp_tokens (
    token      TEXT PRIMARY KEY,
    event_id   UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
    guest_id   UUID REFERENCES guests_v2(id) ON DELETE SET NULL,
    phone      TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    expires_at TIMESTAMP WITH TIME ZONE,
    used_at    TIMESTAMP WITH TIME ZONE
);
CREATE INDEX IF NOT EXISTS idx_rsvp_tokens_event_id ON rsvp_tokens(event_id);
CREATE INDEX IF NOT EXISTS idx_rsvp_tokens_guest_id ON rsvp_tokens(guest_id);


-- =============================================================================
-- STEP 3a — Patch `events` table: add WhatsApp / RSVP columns (IF NOT EXISTS)
-- =============================================================================
DO $$
BEGIN
    ALTER TABLE events ADD COLUMN partner1_name TEXT; EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE events ADD COLUMN partner2_name TEXT; EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE events ADD COLUMN venue TEXT; EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE events ADD COLUMN event_time TEXT; EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE events ADD COLUMN guest_link TEXT; EXCEPTION WHEN duplicate_column THEN NULL;
END $$;

CREATE INDEX IF NOT EXISTS idx_events_guest_link ON events(guest_link);


-- =============================================================================
-- STEP 3b — Patch `guests_v2`: add any missing columns (forward-compat)
-- =============================================================================
DO $$
BEGIN
    ALTER TABLE guests_v2 ADD COLUMN phone TEXT;
    EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE guests_v2 ADD COLUMN phone_number TEXT;
    EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE guests_v2 ADD COLUMN last_name TEXT NOT NULL DEFAULT '';
    EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE guests_v2 ADD COLUMN notes TEXT;
    EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE guests_v2 ADD COLUMN side TEXT;
    EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE guests_v2 ADD COLUMN source TEXT NOT NULL DEFAULT 'manual';
    EXCEPTION WHEN duplicate_column THEN NULL;
END $$;
DO $$
BEGIN
    ALTER TABLE guests_v2 ADD COLUMN owner_email TEXT;
    EXCEPTION WHEN duplicate_column THEN NULL;
END $$;


-- Fix rsvp_status constraint: old versions used 'status' column name or enum
DO $$
BEGIN
    -- rename `status` → `rsvp_status` if that old column exists
    IF EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_name = 'guests_v2' AND column_name = 'status'
    ) AND NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_name = 'guests_v2' AND column_name = 'rsvp_status'
    ) THEN
        ALTER TABLE guests_v2 RENAME COLUMN status TO rsvp_status;
    END IF;
END $$;

-- Ensure CHECK constraint is present (safe drop+add)
DO $$
BEGIN
    ALTER TABLE guests_v2 DROP CONSTRAINT IF EXISTS guests_v2_rsvp_status_check;
    ALTER TABLE guests_v2 ADD  CONSTRAINT guests_v2_rsvp_status_check
        CHECK (rsvp_status IN ('invited', 'confirmed', 'declined'));
EXCEPTION WHEN OTHERS THEN NULL;
END $$;

DO $$
BEGIN
    ALTER TABLE guests_v2 DROP CONSTRAINT IF EXISTS guests_v2_source_check;
    ALTER TABLE guests_v2 ADD  CONSTRAINT guests_v2_source_check
        CHECK (source IN ('google', 'manual', 'self-service'));
EXCEPTION WHEN OTHERS THEN NULL;
END $$;


-- =============================================================================
-- STEP 3c — updated_at triggers
-- =============================================================================
CREATE OR REPLACE FUNCTION _update_updated_at()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$;

DO $$
BEGIN
    CREATE TRIGGER trg_guests_v2_updated_at
        BEFORE UPDATE ON guests_v2
        FOR EACH ROW EXECUTE FUNCTION _update_updated_at();
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$
BEGIN
    CREATE TRIGGER trg_events_updated_at
        BEFORE UPDATE ON events
        FOR EACH ROW EXECUTE FUNCTION _update_updated_at();
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;


-- =============================================================================
-- STEP 4 — Migrate old `guests` rows → `guests_v2`
--
-- Conditions:
--   • The old `guests` table must exist.
--   • guests_v2 must be EMPTY (idempotent guard — never runs twice).
--
-- Strategy:
--   • For each distinct `owner` in the old table create a row in `users`.
--   • Create one migration event ("Migrated Wedding") owned by the first user.
--   • Insert event_members for every owner → that event (role = admin).
--   • Insert guests mapping:
--       rsvp_status: 'pending' → 'invited', 'accepted' → 'confirmed', else as-is
--       phone_number field → phone_number + phone columns
--       owner          → owner_email
--       source         = 'google' (they came from Google import originally)
-- =============================================================================
DO $$
DECLARE
    old_table_exists BOOLEAN;
    new_table_empty  BOOLEAN;
    migration_event_id UUID;
    default_user_id    UUID;
    owner_row          RECORD;
    owner_user_id      UUID;
BEGIN
    -- Check preconditions
    SELECT EXISTS (
        SELECT 1 FROM information_schema.tables
        WHERE table_name = 'guests' AND table_schema = 'public'
    ) INTO old_table_exists;

    SELECT (COUNT(*) = 0) FROM guests_v2 INTO new_table_empty;

    IF NOT old_table_exists OR NOT new_table_empty THEN
        RAISE NOTICE 'Migration skipped: old_table_exists=%, new_table_empty=%',
                     old_table_exists, new_table_empty;
        RETURN;
    END IF;

    RAISE NOTICE 'Starting data migration from guests → guests_v2 …';

    -- ── Create one user per distinct owner ──────────────────────────────────
    FOR owner_row IN
        SELECT DISTINCT COALESCE(NULLIF(TRIM(owner), ''), 'imported@invy.app') AS email
        FROM guests
    LOOP
        INSERT INTO users (email)
        VALUES (owner_row.email)
        ON CONFLICT (email) DO NOTHING;
    END LOOP;

    -- ── Pick (or create) the migration event ────────────────────────────────
    SELECT id INTO migration_event_id FROM events LIMIT 1;

    IF migration_event_id IS NULL THEN
        INSERT INTO events (name, date, location)
        VALUES ('Migrated Wedding', CURRENT_TIMESTAMP, 'Imported from previous system')
        RETURNING id INTO migration_event_id;
    END IF;

    -- ── Get a fallback user (the first one alphabetically) ──────────────────
    SELECT id INTO default_user_id FROM users ORDER BY email LIMIT 1;

    -- ── Create event_members entries for each owner ──────────────────────────
    FOR owner_row IN
        SELECT DISTINCT COALESCE(NULLIF(TRIM(owner), ''), 'imported@invy.app') AS email
        FROM guests
    LOOP
        SELECT id INTO owner_user_id FROM users WHERE email = owner_row.email;

        INSERT INTO event_members (event_id, user_id, role)
        VALUES (migration_event_id, owner_user_id, 'admin')
        ON CONFLICT (event_id, user_id) DO NOTHING;
    END LOOP;

    -- ── Copy guests ──────────────────────────────────────────────────────────
    INSERT INTO guests_v2 (
        event_id,
        added_by_user_id,
        first_name,
        last_name,
        email,
        phone_number,
        phone,
        rsvp_status,
        meal_preference,
        has_plus_one,
        plus_one_name,
        table_number,
        owner_email,
        source,
        notes,
        created_at
    )
    SELECT
        migration_event_id,
        COALESCE(
            (SELECT id FROM users WHERE email = NULLIF(TRIM(g.owner), '')),
            default_user_id
        ),
        g.first_name,
        COALESCE(g.last_name, ''),
        g.email,
        g.phone_number,
        g.phone_number,
        CASE g.rsvp_status
            WHEN 'accepted' THEN 'confirmed'
            WHEN 'pending'  THEN 'invited'
            WHEN 'declined' THEN 'declined'
            ELSE 'invited'
        END,
        g.meal_preference,
        COALESCE(g.has_plus_one, FALSE),
        g.plus_one_name,
        g.table_number::TEXT,
        NULLIF(TRIM(COALESCE(g.owner, '')), ''),
        'google',
        g.notes,
        COALESCE(g.created_at, CURRENT_TIMESTAMP)
    FROM guests g;

    RAISE NOTICE 'Migration complete. Rows inserted: %', (SELECT COUNT(*) FROM guests_v2);
END $$;


-- =============================================================================
-- DONE
-- =============================================================================
SELECT
    (SELECT COUNT(*) FROM users)      AS users_total,
    (SELECT COUNT(*) FROM events)     AS events_total,
    (SELECT COUNT(*) FROM guests_v2)  AS guests_v2_total;
