"""Add normalized identities and fixed platform roles without copying legacy passwords."""

from alembic import op


revision = "20260716_10"
down_revision = "20260716_03"
branch_labels = None
depends_on = None


def upgrade() -> None:
    op.execute(
        """
        DO $$
        BEGIN
            IF EXISTS (
                SELECT 1 FROM information_schema.columns
                WHERE table_schema = 'public' AND table_name = 'users'
                  AND column_name = 'password'
            ) AND NOT EXISTS (
                SELECT 1 FROM information_schema.tables
                WHERE table_schema = 'public' AND table_name = 'users_legacy'
            ) THEN
                ALTER TABLE public.users RENAME TO users_legacy;
                ALTER INDEX IF EXISTS public.idx_users_username
                    RENAME TO idx_users_legacy_username;
            END IF;
        END $$;

        CREATE TABLE IF NOT EXISTS public.roles (
            id UUID PRIMARY KEY,
            name VARCHAR(32) NOT NULL UNIQUE,
            description VARCHAR(200) NOT NULL,
            created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
        );

        CREATE TABLE IF NOT EXISTS public.users (
            id UUID PRIMARY KEY,
            username VARCHAR(64) NOT NULL UNIQUE,
            display_name VARCHAR(100),
            password_hash TEXT NOT NULL,
            status VARCHAR(20) NOT NULL DEFAULT 'active'
                CHECK (status IN ('active', 'disabled')),
            created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
            last_login_at TIMESTAMPTZ
        );

        CREATE TABLE IF NOT EXISTS public.user_roles (
            user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
            role_id UUID NOT NULL REFERENCES public.roles(id) ON DELETE CASCADE,
            assigned_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
            assigned_by UUID REFERENCES public.users(id) ON DELETE SET NULL,
            PRIMARY KEY (user_id, role_id)
        );

        CREATE TABLE IF NOT EXISTS public.auth_audit_events (
            id BIGSERIAL PRIMARY KEY,
            user_id UUID REFERENCES public.users(id) ON DELETE SET NULL,
            username VARCHAR(64),
            event_type VARCHAR(40) NOT NULL,
            success BOOLEAN NOT NULL,
            ip_address VARCHAR(64),
            user_agent VARCHAR(300),
            detail VARCHAR(500),
            created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
        );
        CREATE INDEX IF NOT EXISTS idx_auth_audit_created_at
            ON public.auth_audit_events(created_at DESC);
        CREATE INDEX IF NOT EXISTS idx_auth_audit_username
            ON public.auth_audit_events(username);

        INSERT INTO public.roles (id, name, description) VALUES
            ('01900000-0000-7000-8000-000000000001', 'admin', '平台管理员'),
            ('01900000-0000-7000-8000-000000000002', 'editor', '治理编辑者'),
            ('01900000-0000-7000-8000-000000000003', 'viewer', '只读查看者')
        ON CONFLICT (name) DO NOTHING;
        """
    )


def downgrade() -> None:
    # Identity rollback is intentionally data-preserving.
    pass
