BEGIN;

LOCK TABLE tb_agent_wallet IN ACCESS EXCLUSIVE MODE;

ALTER TABLE tb_agent_wallet
    ADD COLUMN IF NOT EXISTS credit_enabled boolean NOT NULL DEFAULT false,
    ADD COLUMN IF NOT EXISTS credit_limit bigint NOT NULL DEFAULT 0;

COMMENT ON COLUMN tb_agent_wallet.credit_enabled IS '是否启用代理主钱包信用额度；分佣钱包固定关闭';
COMMENT ON COLUMN tb_agent_wallet.credit_limit IS '代理主钱包信用额度，单位为分；关闭信用时固定为0';

-- 迁移在目标库读取真实约束定义，不依赖归档迁移中的约束名称。
DO $$
DECLARE
    balance_attnum smallint;
    constraint_row record;
    normalized_definition text;
BEGIN
    SELECT attnum
      INTO balance_attnum
      FROM pg_attribute
     WHERE attrelid = 'tb_agent_wallet'::regclass
       AND attname = 'balance'
       AND NOT attisdropped;

    FOR constraint_row IN
        SELECT conname, conkey, pg_get_constraintdef(oid) AS definition
          FROM pg_constraint
         WHERE conrelid = 'tb_agent_wallet'::regclass
           AND contype = 'c'
    LOOP
        normalized_definition := regexp_replace(lower(constraint_row.definition), '[[:space:]()]', '', 'g');
        IF (array_length(constraint_row.conkey, 1) = 1
                AND constraint_row.conkey[1] = balance_attnum
                AND normalized_definition LIKE 'check%balance%>=%0%')
           OR normalized_definition LIKE '%frozen_balance%<=%balance%' THEN
            RAISE NOTICE '移除代理钱包历史约束 %：%', constraint_row.conname, constraint_row.definition;
            EXECUTE format('ALTER TABLE tb_agent_wallet DROP CONSTRAINT %I', constraint_row.conname);
        END IF;
    END LOOP;
END
$$;

ALTER TABLE tb_agent_wallet
    DROP CONSTRAINT IF EXISTS chk_agent_wallet_credit_config,
    DROP CONSTRAINT IF EXISTS chk_agent_wallet_credit_scope,
    DROP CONSTRAINT IF EXISTS chk_agent_wallet_frozen_nonnegative,
    DROP CONSTRAINT IF EXISTS chk_agent_wallet_arithmetic_range,
    DROP CONSTRAINT IF EXISTS chk_agent_wallet_available_balance,
    DROP CONSTRAINT IF EXISTS chk_agent_wallet_version_nonnegative;

-- 历史钱包默认关闭信用；任何既有异常都必须先形成清单并修复，禁止迁移静默改账。
DO $$
DECLARE
    abnormal_count bigint;
BEGIN
    SELECT COUNT(*)
      INTO abnormal_count
      FROM tb_agent_wallet
     WHERE wallet_type NOT IN ('main', 'commission')
        OR frozen_balance < 0
        OR version < 0
        OR credit_enabled
        OR credit_limit <> 0
        OR (wallet_type = 'main' AND balance::numeric - frozen_balance::numeric < 0)
        OR (wallet_type = 'commission' AND (balance < 0 OR frozen_balance > balance));

    IF abnormal_count > 0 THEN
        RAISE EXCEPTION '代理钱包信用迁移发现 % 条异常数据，请先导出钱包ID、约束定义并修复后重试', abnormal_count;
    END IF;
END
$$;

ALTER TABLE tb_agent_wallet
    ADD CONSTRAINT chk_agent_wallet_credit_config CHECK (
        (credit_enabled = false AND credit_limit = 0) OR
        (credit_enabled = true AND credit_limit > 0)
    ),
    ADD CONSTRAINT chk_agent_wallet_credit_scope CHECK (
        wallet_type = 'main' OR (credit_enabled = false AND credit_limit = 0)
    ),
    ADD CONSTRAINT chk_agent_wallet_frozen_nonnegative CHECK (frozen_balance >= 0),
    ADD CONSTRAINT chk_agent_wallet_arithmetic_range CHECK (
        wallet_type <> 'main' OR (
            balance > -9223372036854775808::numeric AND
            balance::numeric - frozen_balance::numeric BETWEEN -9223372036854775808::numeric AND 9223372036854775807::numeric AND
            balance::numeric - frozen_balance::numeric +
                CASE WHEN credit_enabled THEN credit_limit::numeric ELSE 0::numeric END
                BETWEEN -9223372036854775808::numeric AND 9223372036854775807::numeric
        )
    ),
    ADD CONSTRAINT chk_agent_wallet_available_balance CHECK (
        (wallet_type = 'main' AND
            balance::numeric - frozen_balance::numeric +
            CASE WHEN credit_enabled THEN credit_limit::numeric ELSE 0::numeric END >= 0) OR
        (wallet_type = 'commission' AND balance >= 0 AND frozen_balance <= balance)
    ),
    ADD CONSTRAINT chk_agent_wallet_version_nonnegative CHECK (version >= 0);

CREATE INDEX IF NOT EXISTS idx_agent_wallet_main_credit_enabled
    ON tb_agent_wallet (shop_id)
    WHERE wallet_type = 'main' AND credit_enabled = true AND deleted_at IS NULL;

COMMENT ON CONSTRAINT chk_agent_wallet_credit_config ON tb_agent_wallet IS '保证信用开关与额度组合一致';
COMMENT ON CONSTRAINT chk_agent_wallet_credit_scope ON tb_agent_wallet IS '保证只有代理主钱包可以启用信用额度';
COMMENT ON CONSTRAINT chk_agent_wallet_frozen_nonnegative ON tb_agent_wallet IS '保证冻结金额不为负数';
COMMENT ON CONSTRAINT chk_agent_wallet_arithmetic_range ON tb_agent_wallet IS '保证现金可用、总可用和欠款金额均可在int64范围内安全计算';
COMMENT ON CONSTRAINT chk_agent_wallet_available_balance ON tb_agent_wallet IS '保证主钱包总可用金额和分佣钱包现金可用金额不为负数';
COMMENT ON CONSTRAINT chk_agent_wallet_version_nonnegative ON tb_agent_wallet IS '保证钱包乐观锁版本不为负数';
COMMENT ON INDEX idx_agent_wallet_main_credit_enabled IS '启用信用额度的有效代理主钱包索引';

COMMIT;
