package com.ruoyi.ccdi.project.sql;

import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertTrue;

class CcdiBankTagRuleSqlMetadataTest {

    @Test
    void phase1MetadataSql_shouldAlignInitAndMigrationScripts() throws IOException {
        String initSql = readProjectFile("sql", "2026-03-16-bank-tagging.sql");
        String migrationSql = readProjectFile("sql", "migration", "2026-03-20-sync-bank-tag-phase1-rule-metadata.sql");

        assertPhase1Metadata(initSql);
        assertPhase1Metadata(migrationSql);
    }

    @Test
    void phase2MetadataSql_shouldAlignInitAndMigrationScripts() throws IOException {
        String initSql = readProjectFile("sql", "2026-03-16-bank-tagging.sql");
        String migrationSql = readProjectFile("sql", "migration", "2026-03-20-sync-bank-tag-phase2-rule-metadata.sql");

        assertPhase2Metadata(initSql);
        assertPhase2Metadata(migrationSql);
    }

    @Test
    void abnormalAccountMetadataSql_shouldContainBusinessCaliberAndRuleRemark() throws IOException {
        String migrationSql = readProjectFile("sql", "migration",
            "2026-03-31-create-ccdi-account-info-and-abnormal-account-rules.sql");

        assertAll(
            () -> assertTrue(migrationSql.contains("员工本人账户已销户，且销户日前30天内存在大额资金流动。"),
                "SUDDEN_ACCOUNT_CLOSURE 应使用设计文档中的业务口径"),
            () -> assertTrue(migrationSql.contains("员工本人账户开户后长期未使用，首次启用后出现大额资金流动。"),
                "DORMANT_ACCOUNT_LARGE_ACTIVATION 应使用设计文档中的业务口径"),
            () -> assertTrue(migrationSql.contains("真实规则：识别员工本人账户销户前30天内存在大额资金流动的员工对象"),
                "SUDDEN_ACCOUNT_CLOSURE 应同步真实规则说明"),
            () -> assertTrue(migrationSql.contains("真实规则：识别长期休眠后首次启用即出现大额资金流动的员工对象"),
                "DORMANT_ACCOUNT_LARGE_ACTIVATION 应同步真实规则说明")
        );
    }

    private void assertPhase1Metadata(String sqlContent) {
        assertAll(
            () -> assertTrue(sqlContent.contains("'FOREX_BUY_AMT'")
                    && sqlContent.contains("'SINGLE_PURCHASE_AMOUNT'"),
                "FOREX_BUY_AMT 应使用 SINGLE_PURCHASE_AMOUNT"),
            () -> assertTrue(sqlContent.contains("'FOREX_SELL_AMT'")
                    && sqlContent.contains("'SINGLE_SETTLEMENT_AMOUNT'"),
                "FOREX_SELL_AMT 应使用 SINGLE_SETTLEMENT_AMOUNT"),
            () -> assertTrue(sqlContent.contains("'LARGE_STOCK_TRADING'")
                    && sqlContent.contains("'STOCK_TFR_LARGE'"),
                "LARGE_STOCK_TRADING 应使用 STOCK_TFR_LARGE"),
            () -> assertTrue(sqlContent.contains("真实规则：识别单笔购汇金额超过阈值的流水"),
                "应同步 FOREX_BUY_AMT 的真实规则说明"),
            () -> assertTrue(sqlContent.contains("真实规则：识别单笔结汇金额超过阈值的流水"),
                "应同步 FOREX_SELL_AMT 的真实规则说明"),
            () -> assertTrue(sqlContent.contains("真实规则：识别单笔三方资管交易金额超过阈值的流水"),
                "应同步 LARGE_STOCK_TRADING 的真实规则说明")
        );
    }

    private void assertPhase2Metadata(String sqlContent) {
        assertAll(
            () -> assertTrue(sqlContent.contains("真实规则：识别低收入关系人累计交易超10万元的员工对象"),
                "应同步 LOW_INCOME_RELATIVE_LARGE_TRANSACTION 的真实规则说明"),
            () -> assertTrue(sqlContent.contains("真实规则：识别同日多对手方且金额落在可疑区间的疑似赌博对象"),
                "应同步 MULTI_PARTY_GAMBLING_TRANSFER 的真实规则说明"),
            () -> assertTrue(sqlContent.contains("'MONTHLY_FIXED_INCOME'")
                    && sqlContent.contains("真实规则：识别近12个月持续出现稳定月度非工资收入的员工对象"),
                "应同步 MONTHLY_FIXED_INCOME 的指标编码和真实规则说明"),
            () -> assertTrue(sqlContent.contains("'FIXED_COUNTERPARTY_TRANSFER', '疑似兼职', NULL, 'OBJECT'")
                    && sqlContent.contains("真实规则：识别固定交易对手季度转入金额落在设定区间的员工对象"),
                "FIXED_COUNTERPARTY_TRANSFER 应清空旧 indicator_code 并同步真实规则说明"),
            () -> assertTrue(sqlContent.contains("真实规则：识别购房支出但当前房产登记口径缺失的流水"),
                "应同步 HOUSE_REGISTRATION_MISMATCH 的真实规则说明"),
            () -> assertTrue(sqlContent.contains("真实规则：识别物业缴费但当前房产登记口径缺失的流水"),
                "应同步 PROPERTY_FEE_REGISTRATION_MISMATCH 的真实规则说明"),
            () -> assertTrue(sqlContent.contains("员工及关系人有5000元以上的纳税记录，但当前资产登记口径下无房产登记。"),
                "TAX_ASSET_REGISTRATION_MISMATCH 应使用当前资产登记口径表述"),
            () -> assertTrue(sqlContent.contains("真实规则：识别大额纳税但当前房产登记口径缺失的流水"),
                "应同步 TAX_ASSET_REGISTRATION_MISMATCH 的真实规则说明"),
            () -> assertTrue(sqlContent.contains("真实规则：识别单个供应商采购额占比超过70%的员工对象"),
                "应同步 SUPPLIER_CONCENTRATION 的真实规则说明"),
            () -> assertTrue(sqlContent.contains("工资发放后24小时内转出超过80%的资金。")
                    && sqlContent.contains("真实规则：识别工资入账24小时内快速转出的员工对象"),
                "应同步 SALARY_QUICK_TRANSFER 的业务口径和真实规则说明"),
            () -> assertTrue(sqlContent.contains("工资发放后除代扣项目外，连续30天无消费或转账支出记录。")
                    && sqlContent.contains("真实规则：识别工资入账后30天内无消费或转账支出的员工对象"),
                "应同步 SALARY_UNUSED 的业务口径修复和真实规则说明")
        );
    }

    private String readProjectFile(String... parts) throws IOException {
        Path path = Path.of("..", parts);
        return Files.readString(path, StandardCharsets.UTF_8);
    }
}
