"""Phase 11: Knowledge Management — Playbooks + Lessons Learned

Revision ID: b037know
Revises: b036atk
Create Date: 2026-05-20

Uses raw SQL to bypass SQLAlchemy DDL hooks (no enum types — string columns
with Pydantic-layer validation instead, so no PostgreSQL enums needed).
"""

from typing import Union
from alembic import op
import sqlalchemy as sa

revision: str = "b037know"
down_revision: Union[str, None] = "b036atk"
branch_labels = None
depends_on = None


def upgrade() -> None:
    conn = op.get_bind()

    # ── playbooks ──────────────────────────────────────────────────────────────
    conn.execute(sa.text("""
        CREATE TABLE IF NOT EXISTS playbooks (
            id             UUID PRIMARY KEY DEFAULT gen_random_uuid(),
            technique_id   UUID NOT NULL REFERENCES techniques(id) ON DELETE CASCADE,
            playbook_type  VARCHAR(32) NOT NULL,
            title          VARCHAR(255) NOT NULL,
            content        TEXT NOT NULL DEFAULT '',
            version        INTEGER NOT NULL DEFAULT 1,
            tools          JSONB,
            prerequisites  JSONB,
            created_by     UUID REFERENCES users(id) ON DELETE SET NULL,
            updated_by     UUID REFERENCES users(id) ON DELETE SET NULL,
            created_at     TIMESTAMP DEFAULT now(),
            updated_at     TIMESTAMP DEFAULT now(),
            is_active      BOOLEAN DEFAULT TRUE,
            CONSTRAINT uq_playbook_technique_type UNIQUE (technique_id, playbook_type)
        )
    """))
    conn.execute(sa.text(
        "CREATE INDEX IF NOT EXISTS ix_playbooks_technique_id ON playbooks (technique_id)"
    ))
    conn.execute(sa.text(
        "CREATE INDEX IF NOT EXISTS ix_playbooks_type ON playbooks (playbook_type)"
    ))

    # ── playbook_versions ──────────────────────────────────────────────────────
    conn.execute(sa.text("""
        CREATE TABLE IF NOT EXISTS playbook_versions (
            id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
            playbook_id   UUID NOT NULL REFERENCES playbooks(id) ON DELETE CASCADE,
            version       INTEGER NOT NULL,
            title         VARCHAR(255) NOT NULL,
            content       TEXT NOT NULL DEFAULT '',
            tools         JSONB,
            prerequisites JSONB,
            changed_by    UUID REFERENCES users(id) ON DELETE SET NULL,
            change_note   VARCHAR(500),
            created_at    TIMESTAMP DEFAULT now()
        )
    """))
    conn.execute(sa.text(
        "CREATE INDEX IF NOT EXISTS ix_pb_versions_playbook_id ON playbook_versions (playbook_id)"
    ))
    conn.execute(sa.text(
        "CREATE INDEX IF NOT EXISTS ix_pb_versions_version ON playbook_versions (playbook_id, version)"
    ))

    # ── lessons_learned ────────────────────────────────────────────────────────
    conn.execute(sa.text("""
        CREATE TABLE IF NOT EXISTS lessons_learned (
            id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
            title         VARCHAR(255) NOT NULL,
            what_happened TEXT NOT NULL DEFAULT '',
            root_cause    TEXT NOT NULL DEFAULT '',
            fix_applied   TEXT,
            severity      VARCHAR(16) NOT NULL DEFAULT 'medium',
            entity_type   VARCHAR(32) NOT NULL DEFAULT 'manual',
            entity_id     UUID,
            technique_ids JSONB,
            tags          JSONB,
            created_by    UUID REFERENCES users(id) ON DELETE SET NULL,
            created_at    TIMESTAMP DEFAULT now(),
            updated_at    TIMESTAMP DEFAULT now(),
            is_active     BOOLEAN DEFAULT TRUE
        )
    """))
    conn.execute(sa.text(
        "CREATE INDEX IF NOT EXISTS ix_ll_entity ON lessons_learned (entity_type, entity_id)"
    ))
    conn.execute(sa.text(
        "CREATE INDEX IF NOT EXISTS ix_ll_severity ON lessons_learned (severity)"
    ))
    conn.execute(sa.text(
        "CREATE INDEX IF NOT EXISTS ix_ll_created_by ON lessons_learned (created_by)"
    ))


def downgrade() -> None:
    conn = op.get_bind()
    conn.execute(sa.text("DROP TABLE IF EXISTS lessons_learned"))
    conn.execute(sa.text("DROP TABLE IF EXISTS playbook_versions"))
    conn.execute(sa.text("DROP TABLE IF EXISTS playbooks"))
