-- Entry-Secret N:N migration (manual SQL)
-- Safe to re-run: uses IF EXISTS/IF NOT EXISTS guards.

BEGIN;

-- 1) secrets: add new columns
ALTER TABLE secrets
    ADD COLUMN IF NOT EXISTS user_id UUID REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE secrets
    ADD COLUMN IF NOT EXISTS type VARCHAR(64) NOT NULL DEFAULT 'text';

-- 2) rename field_name -> name (idempotent)
DO $$ BEGIN
    IF EXISTS (
        SELECT 1
        FROM information_schema.columns
        WHERE table_name = 'secrets' AND column_name = 'field_name'
    ) THEN
        ALTER TABLE secrets RENAME COLUMN field_name TO name;
    END IF;
END $$;

-- 3) create join table
CREATE TABLE IF NOT EXISTS entry_secrets (
    entry_id UUID NOT NULL REFERENCES entries(id) ON DELETE CASCADE,
    secret_id UUID NOT NULL REFERENCES secrets(id) ON DELETE CASCADE,
    sort_order INT NOT NULL DEFAULT 0,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    PRIMARY KEY (entry_id, secret_id)
);
CREATE INDEX IF NOT EXISTS idx_entry_secrets_secret_id ON entry_secrets(secret_id);

-- 4) backfill user_id and relationship from old secrets.entry_id
DO $$ BEGIN
    IF EXISTS (
        SELECT 1
        FROM information_schema.columns
        WHERE table_name = 'secrets' AND column_name = 'entry_id'
    ) THEN
        UPDATE secrets s
        SET user_id = e.user_id
        FROM entries e
        WHERE s.entry_id = e.id AND s.user_id IS NULL;

        INSERT INTO entry_secrets(entry_id, secret_id, sort_order)
        SELECT entry_id, id, 0
        FROM secrets
        WHERE entry_id IS NOT NULL
        ON CONFLICT DO NOTHING;
    END IF;
END $$;

-- 5) backfill secret types
UPDATE secrets SET type = 'pem' WHERE name IN ('ssh_key');
UPDATE secrets SET type = 'password' WHERE name IN ('password');
UPDATE secrets SET type = 'phone' WHERE name LIKE 'phone%';
UPDATE secrets SET type = 'url' WHERE name IN ('webhook_url', 'address');
UPDATE secrets
SET type = 'token'
WHERE name IN (
    'access_key_id',
    'access_key_secret',
    'global_api_key',
    'api_key',
    'secret_key',
    'personal_access_token',
    'runner_token',
    'GOOGLE_CLIENT_ID',
    'GOOGLE_CLIENT_SECRET'
);

-- 6) drop old entry_id path
ALTER TABLE secrets DROP CONSTRAINT IF EXISTS secrets_entry_id_fkey;
DROP INDEX IF EXISTS idx_secrets_entry_id;
ALTER TABLE secrets DROP CONSTRAINT IF EXISTS secrets_entry_id_field_name_key;
ALTER TABLE secrets DROP CONSTRAINT IF EXISTS secrets_entry_id_name_key;
ALTER TABLE secrets DROP COLUMN IF EXISTS entry_id;

-- 7) add indexes for new access paths
CREATE INDEX IF NOT EXISTS idx_secrets_user_id
    ON secrets(user_id) WHERE user_id IS NOT NULL;
DO $$
DECLARE
    duplicate_samples TEXT;
BEGIN
    SELECT string_agg(
               format('user_id=%s, name=%s, count=%s', t.user_id, t.name, t.cnt),
               E'\n'
           )
    INTO duplicate_samples
    FROM (
        SELECT user_id::TEXT AS user_id, name, COUNT(*) AS cnt
        FROM secrets
        WHERE user_id IS NOT NULL
        GROUP BY user_id, name
        HAVING COUNT(*) > 1
        ORDER BY cnt DESC, user_id, name
        LIMIT 20
    ) t;

    IF duplicate_samples IS NOT NULL THEN
        RAISE EXCEPTION
            'Cannot enforce unique constraint on secrets(user_id, name). Duplicates found:%',
            E'\n' || duplicate_samples
            USING HINT = 'Please deduplicate conflicting rows, then rerun migration.';
    END IF;
END $$;
CREATE UNIQUE INDEX IF NOT EXISTS idx_secrets_unique_user_name
    ON secrets(user_id, name) WHERE user_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_secrets_name ON secrets(name);
CREATE INDEX IF NOT EXISTS idx_secrets_type ON secrets(type);

-- 8) secrets_history: rename and remove entry-scoped columns
DO $$ BEGIN
    IF EXISTS (
        SELECT 1
        FROM information_schema.columns
        WHERE table_name = 'secrets_history' AND column_name = 'field_name'
    ) THEN
        ALTER TABLE secrets_history RENAME COLUMN field_name TO name;
    END IF;
END $$;
ALTER TABLE secrets_history DROP COLUMN IF EXISTS entry_id;
ALTER TABLE secrets_history DROP COLUMN IF EXISTS entry_version;

COMMIT;
