use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        let db = manager.get_connection();

        // 1. 创建触发器函数：适用于 `version` 列（erp-health / erp-auth / erp-config 等所有模块）
        db.execute_unprepared(
            r#"
CREATE OR REPLACE FUNCTION enforce_version() RETURNS trigger AS $$
BEGIN
    IF NEW.version IS DISTINCT FROM OLD.version + 1 THEN
        RAISE EXCEPTION 'Optimistic lock conflict on %: expected version %, got %',
            TG_TABLE_NAME, OLD.version + 1, NEW.version;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;
"#,
        )
        .await?;

        // 2. 创建触发器函数：适用于 `version_lock` 列（erp-ai 模块）
        db.execute_unprepared(
            r#"
CREATE OR REPLACE FUNCTION enforce_version_lock() RETURNS trigger AS $$
BEGIN
    IF NEW.version_lock IS DISTINCT FROM OLD.version_lock + 1 THEN
        RAISE EXCEPTION 'Optimistic lock conflict on %: expected version_lock %, got %',
            TG_TABLE_NAME, OLD.version_lock + 1, NEW.version_lock;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;
"#,
        )
        .await?;

        // 3. 自动发现所有含 version / version_lock 的表并绑定触发器
        //    排除 market_entry（version 是 String，非乐观锁）
        db.execute_unprepared(
            r#"
DO $$
DECLARE
    rec RECORD;
    trig_name text;
BEGIN
    FOR rec IN
        SELECT table_name, column_name
        FROM information_schema.columns
        WHERE column_name IN ('version', 'version_lock')
          AND table_schema = 'public'
          AND table_name NOT IN ('market_entry', 'process_definitions', 'ai_prompt')
    LOOP
        IF rec.column_name = 'version' THEN
            trig_name := 'trg_enforce_version';
            EXECUTE format(
                'CREATE TRIGGER %I BEFORE UPDATE ON %I
                 FOR EACH ROW EXECUTE FUNCTION enforce_version()',
                trig_name, rec.table_name
            );
        ELSE
            trig_name := 'trg_enforce_version_lock';
            EXECUTE format(
                'CREATE TRIGGER %I BEFORE UPDATE ON %I
                 FOR EACH ROW EXECUTE FUNCTION enforce_version_lock()',
                trig_name, rec.table_name
            );
        END IF;
    END LOOP;
END;
$$;
"#,
        )
        .await?;

        Ok(())
    }

    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        let db = manager.get_connection();

        // 1. 删除所有乐观锁触发器
        db.execute_unprepared(
            r#"
DO $$
DECLARE
    rec RECORD;
BEGIN
    FOR rec IN
        SELECT event_object_table AS table_name, trigger_name
        FROM information_schema.triggers
        WHERE trigger_name IN ('trg_enforce_version', 'trg_enforce_version_lock')
    LOOP
        EXECUTE format('DROP TRIGGER IF EXISTS %I ON %I', rec.trigger_name, rec.table_name);
    END LOOP;
END;
$$;
"#,
        )
        .await?;

        // 2. 删除触发器函数
        db.execute_unprepared("DROP FUNCTION IF EXISTS enforce_version() CASCADE")
            .await?;
        db.execute_unprepared("DROP FUNCTION IF EXISTS enforce_version_lock() CASCADE")
            .await?;

        Ok(())
    }
}
