from datetime import datetime, timedelta
from typing import Dict, List, Optional


DEFAULT_LARGE_TRANSACTION_THRESHOLDS = {
    "SINGLE_TRANSACTION_AMOUNT": 1111,
    "CUMULATIVE_TRANSACTION_AMOUNT": 50000001,
    "ANNUAL_TURNOVER": 50000001,
    "LARGE_CASH_DEPOSIT": 2000001,
    "FREQUENT_CASH_DEPOSIT": 5,
    "FREQUENT_TRANSFER": 100001,
}

IDENTITY_POOL = {
    "staff_primary": {
        "name": "模型测试员工",
        "id_card": "330101198801010011",
        "account": "6222024000000001",
    },
    "family_primary": {
        "name": "模型测试家属",
        "id_card": "330101199001010022",
        "account": "6222024000000002",
    },
    "staff_secondary": {
        "name": "模型二测试员工",
        "id_card": "330101198802020033",
        "account": "6222024000000003",
    },
    "family_secondary": {
        "name": "模型二测试家属",
        "id_card": "330101199202020044",
        "account": "6222024000000004",
    },
}

IDENTITY_SCOPES = {
    "primary": {
        "staff": IDENTITY_POOL["staff_primary"],
        "family": IDENTITY_POOL["family_primary"],
    },
    "secondary": {
        "staff": IDENTITY_POOL["staff_secondary"],
        "family": IDENTITY_POOL["family_secondary"],
    },
}

IDENTITY_CARD_POOL = tuple(identity["id_card"] for identity in IDENTITY_POOL.values())

REFERENCE_NOW = datetime(2026, 3, 18, 9, 0, 0)


def resolve_identity_scope(log_id: int) -> Dict[str, Dict[str, str]]:
    """按 logId 稳定选择单个员工域。"""
    return IDENTITY_SCOPES["primary"] if log_id % 2 == 1 else IDENTITY_SCOPES["secondary"]


def resolve_identity_cards(log_id: int) -> tuple:
    """返回指定 logId 允许出现的证件号集合（员工本人及家属）。"""
    identity_scope = resolve_identity_scope(log_id)
    return tuple(identity["id_card"] for identity in identity_scope.values())


def _format_datetime(value: datetime) -> str:
    return value.strftime("%Y-%m-%d %H:%M:%S")


def _format_date(value: datetime) -> str:
    return value.strftime("%Y-%m-%d")


def _build_statement(
    group_id: int,
    log_id: int,
    *,
    trx_datetime: datetime,
    cret_no: str,
    customer_name: str,
    user_memo: str,
    cash_type: str,
    dr_amount: float = 0.0,
    cr_amount: float = 0.0,
    le_name: str = "模型测试主体",
    account_mask_no: str = "6222024999999999",
    customer_account_mask_no: str = "9558800000000001",
    bank_comments: str = "",
    customer_bank: str = "",
    customer_cert_no: str = "",
    customer_social_credit_code: str = "",
) -> Dict:
    trans_amount = round(dr_amount if dr_amount > 0 else cr_amount, 2)
    balance_amount = round(80000000 + cr_amount - dr_amount, 2)

    return {
        "accountId": 0,
        "accountMaskNo": account_mask_no,
        "accountingDate": _format_date(trx_datetime),
        "accountingDateId": int(trx_datetime.strftime("%Y%m%d")),
        "archivingFlag": 0,
        "attachments": 0,
        "balanceAmount": balance_amount,
        "bank": "ZJRCU",
        "bankComments": bank_comments,
        "bankStatementId": 0,
        "bankTrxNumber": "",
        "batchId": log_id,
        "cashType": cash_type,
        "commentsNum": 0,
        "crAmount": round(cr_amount, 2),
        "createDate": _format_datetime(REFERENCE_NOW),
        "createdBy": "902001",
        "cretNo": cret_no,
        "currency": "CNY",
        "customerAccountMaskNo": customer_account_mask_no,
        "customerBank": customer_bank,
        "customerId": -1,
        "customerName": customer_name,
        "customerReference": "",
        "customerCertNo": customer_cert_no,
        "customerSocialCreditCode": customer_social_credit_code,
        "downPaymentFlag": 0,
        "drAmount": round(dr_amount, 2),
        "exceptionType": "",
        "groupId": group_id,
        "internalFlag": 0,
        "leId": 16308,
        "leName": le_name,
        "overrideBsId": 0,
        "paymentMethod": "",
        "sourceCatalogId": 0,
        "split": 0,
        "subBankstatementId": 0,
        "toDoFlag": 0,
        "transAmount": trans_amount,
        "transFlag": "P" if dr_amount > 0 else "R",
        "transTypeId": 0,
        "transformAmount": 0,
        "transformCrAmount": 0,
        "transformDrAmount": 0,
        "transfromBalanceAmount": 0,
        "trxBalance": 0,
        "trxDate": _format_datetime(trx_datetime),
        "uploadSequnceNumber": 0,
        "userMemo": user_memo,
    }


def _build_sample_context(
    log_id: int,
    primary_enterprise_name: Optional[str] = None,
    primary_account_no: Optional[str] = None,
    staff_id_card: Optional[str] = None,
    family_id_cards: Optional[List[str]] = None,
) -> Dict[str, str]:
    identity_scope = resolve_identity_scope(log_id)
    staff_identity = identity_scope["staff"]
    family_identity = identity_scope["family"]
    selected_staff_id_card = staff_id_card or staff_identity["id_card"]
    selected_family_id_cards = list(family_id_cards or [family_identity["id_card"]])

    return {
        "le_name": primary_enterprise_name or "模型测试主体",
        "account_no": primary_account_no or "6222024999999999",
        "staff_id_card": selected_staff_id_card,
        "family_id_card": (
            selected_family_id_cards[0] if selected_family_id_cards else selected_staff_id_card
        ),
    }


def _build_phase2_subjects(
    log_id: int,
    staff_id_card: Optional[str] = None,
    family_id_cards: Optional[List[str]] = None,
) -> Dict[str, str]:
    identity_scope = resolve_identity_scope(log_id)
    fallback_staff = identity_scope["staff"]["id_card"]
    fallback_family = identity_scope["family"]["id_card"]

    primary_subject = staff_id_card or fallback_staff
    family_pool = [
        card
        for card in (family_id_cards or [])
        if card and card != primary_subject
    ]
    secondary_subject = (
        family_pool[0]
        if family_pool
        else (fallback_family if fallback_family != primary_subject else primary_subject)
    )
    tertiary_subject = family_pool[1] if len(family_pool) > 1 else secondary_subject

    return {
        "primary": primary_subject,
        "secondary": secondary_subject,
        "tertiary": tertiary_subject,
    }


def build_house_or_car_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=9, hours=1),
            cret_no=context["staff_id_card"],
            customer_name="杭州贝壳房地产经纪有限公司",
            user_memo="购买房产首付款",
            cash_type="对公转账",
            dr_amount=680000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024555500001",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=8, hours=2),
            cret_no=context["family_id_card"],
            customer_name="兰溪星耀汽车销售服务有限公司",
            user_memo="购车首付款",
            cash_type="对公转账",
            dr_amount=380000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024555500002",
        ),
    ]


def build_tax_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=7, hours=1),
            cret_no=context["staff_id_card"],
            customer_name="国家金库兰溪市中心支库",
            user_memo="个人所得税税款",
            cash_type="税务缴款",
            dr_amount=126000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024555500003",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=6, hours=3),
            cret_no=context["family_id_card"],
            customer_name="兰溪市税务局",
            user_memo="房产税务缴税",
            cash_type="税务缴款",
            dr_amount=88000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024555500004",
        ),
    ]


def build_single_large_income_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=5, hours=2),
            cret_no=context["staff_id_card"],
            customer_name="浙江远望贸易有限公司",
            user_memo="经营往来收入",
            cash_type="对公转账",
            cr_amount=18800000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600001",
        )
    ]


def build_cumulative_income_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=5, hours=2),
            cret_no=context["staff_id_card"],
            customer_name="浙江远望贸易有限公司",
            user_memo="经营往来收入",
            cash_type="对公转账",
            cr_amount=18800000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600001",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=5, hours=1),
            cret_no=context["staff_id_card"],
            customer_name="浙江远望贸易有限公司",
            user_memo="项目回款收入",
            cash_type="对公转账",
            cr_amount=20800000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600001",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=4, hours=4),
            cret_no=context["staff_id_card"],
            customer_name="浙江远望贸易有限公司",
            user_memo="业务合作收入",
            cash_type="对公转账",
            cr_amount=20700000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600001",
        ),
    ]


def build_annual_turnover_supporting_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=15, hours=2),
            cret_no=context["staff_id_card"],
            customer_name="浙江金穗供应链有限公司",
            user_memo="年度经营回款",
            cash_type="对公转账",
            cr_amount=17200000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600002",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=11, hours=3),
            cret_no=context["staff_id_card"],
            customer_name="浙江金穗供应链有限公司",
            user_memo="年度项目回款",
            cash_type="对公转账",
            cr_amount=17600000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600002",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=9, hours=4),
            cret_no=context["staff_id_card"],
            customer_name="浙江金穗供应链有限公司",
            user_memo="年度合作收入",
            cash_type="对公转账",
            cr_amount=17800000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600002",
        ),
    ]


def build_large_cash_deposit_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=datetime(2026, 3, 10, 9, 0, 0),
            cret_no=context["staff_id_card"],
            customer_name="",
            user_memo="现金存款",
            cash_type="现金存款",
            cr_amount=3000000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
        )
    ]


def build_frequent_cash_deposit_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    deposit_specs = [
        (datetime(2026, 3, 10, 9, 0, 0), "现金存款", 3000000.0),
        (datetime(2026, 3, 10, 9, 30, 0), "ATM现金存款", 3100000.0),
        (datetime(2026, 3, 10, 10, 0, 0), "自助存款现金存入", 3200000.0),
        (datetime(2026, 3, 10, 10, 30, 0), "CRS存款", 3300000.0),
        (datetime(2026, 3, 10, 11, 0, 0), "本行ATM存款", 3400000.0),
        (datetime(2026, 3, 10, 11, 30, 0), "柜面现金存款", 3500000.0),
    ]
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=trx_datetime,
            cret_no=context["staff_id_card"],
            customer_name="",
            user_memo=user_memo,
            cash_type="现金存款",
            cr_amount=cr_amount,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
        )
        for trx_datetime, user_memo, cr_amount in deposit_specs
    ]


def build_large_transfer_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=3, hours=1),
            cret_no=context["staff_id_card"],
            customer_name="异地转账平台",
            user_memo="手机银行转账",
            cash_type="转账支出",
            dr_amount=12000000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024777700001",
        )
    ]


def build_gambling_sensitive_keyword_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=4, hours=2),
            cret_no=context["staff_id_card"],
            customer_name="欢乐游戏科技有限公司",
            user_memo="游戏充值",
            cash_type="快捷支付",
            dr_amount=6888.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024888800001",
        )
    ]


def build_special_amount_transaction_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=4, hours=1),
            cret_no=context["staff_id_card"],
            customer_name="兰溪特别金额结算中心",
            user_memo="特殊金额转账",
            cash_type="转账支出",
            dr_amount=1314.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024888800002",
        )
    ]


def build_suspicious_income_keyword_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=3, hours=5),
            cret_no=context["staff_id_card"],
            customer_name="灰度信息咨询有限公司",
            user_memo="劳务费发放",
            cash_type="劳务费入账",
            cr_amount=166666.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024888800003",
        )
    ]


def build_forex_buy_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=2, hours=6),
            cret_no=context["staff_id_card"],
            customer_name="中国银行外汇业务中心",
            user_memo="个人购汇",
            cash_type="购汇支出",
            dr_amount=126000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024999900001",
        )
    ]


def build_forex_sell_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=2, hours=4),
            cret_no=context["staff_id_card"],
            customer_name="中国银行外汇业务中心",
            user_memo="个人结汇",
            cash_type="结汇收入",
            cr_amount=132000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024999900002",
        )
    ]


def build_stock_transfer_large_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=2, hours=2),
            cret_no=context["staff_id_card"],
            customer_name="国信证券资金账户",
            user_memo="证券大额转托管转出",
            cash_type="转账支出",
            dr_amount=560000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024999900003",
        )
    ]


def build_large_stock_trading_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=1, hours=3),
            cret_no=context["staff_id_card"],
            customer_name="华泰证券资金账户",
            user_memo="证券大额交易买入",
            cash_type="证券交易",
            dr_amount=880000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024999900004",
        )
    ]


def build_withdraw_cnt_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    withdraw_specs = [
        (datetime(2026, 3, 12, 9, 0, 0), "微信提现", 8000.0),
        (datetime(2026, 3, 12, 10, 0, 0), "支付宝提现", 9000.0),
        (datetime(2026, 3, 12, 11, 0, 0), "微信提现", 8500.0),
        (datetime(2026, 3, 12, 12, 0, 0), "支付宝提现", 9200.0),
    ]
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=trx_datetime,
            cret_no=context["staff_id_card"],
            customer_name="财付通结算账户" if "微信" in user_memo else "支付宝结算账户",
            user_memo=user_memo,
            cash_type="提现支出",
            dr_amount=dr_amount,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
        )
        for trx_datetime, user_memo, dr_amount in withdraw_specs
    ]


def build_low_income_relative_large_transaction_samples(
    group_id: int,
    log_id: int,
    **kwargs,
) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    subjects = _build_phase2_subjects(
        log_id,
        staff_id_card=kwargs.get("staff_id_card"),
        family_id_cards=kwargs.get("family_id_cards"),
    )
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=18),
            cret_no=subjects["secondary"],
            customer_name="兰溪惠民互助协会",
            user_memo="亲属大额转入",
            cash_type="对私转账",
            cr_amount=68000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024888800001",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=REFERENCE_NOW - timedelta(days=9),
            cret_no=subjects["secondary"],
            customer_name="兰溪惠民互助协会",
            user_memo="亲属经营补贴",
            cash_type="对私转账",
            cr_amount=52000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024888800001",
        ),
    ]


def build_multi_party_gambling_transfer_samples(
    group_id: int,
    log_id: int,
    **kwargs,
) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    subjects = _build_phase2_subjects(
        log_id,
        staff_id_card=kwargs.get("staff_id_card"),
        family_id_cards=kwargs.get("family_id_cards"),
    )
    transfer_specs = [
        ("欢乐游戏科技有限公司", 3888.0),
        ("星彩娱乐网络科技有限公司", 4288.0),
        ("极速竞技服务有限公司", 4688.0),
    ]
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=datetime(2026, 3, 11, 10 + index, 0, 0),
            cret_no=subjects["primary"],
            customer_name=customer_name,
            user_memo="手机银行转账",
            cash_type="对私转账",
            dr_amount=dr_amount,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no=f"62220247777000{index + 1}",
        )
        for index, (customer_name, dr_amount) in enumerate(transfer_specs)
    ]


def build_monthly_fixed_income_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    subjects = _build_phase2_subjects(
        log_id,
        staff_id_card=kwargs.get("staff_id_card"),
        family_id_cards=kwargs.get("family_id_cards"),
    )
    income_months = [
        datetime(2025, 10, 5, 9, 0, 0),
        datetime(2025, 11, 5, 9, 0, 0),
        datetime(2025, 12, 5, 9, 0, 0),
        datetime(2026, 1, 5, 9, 0, 0),
        datetime(2026, 2, 5, 9, 0, 0),
        datetime(2026, 3, 5, 9, 0, 0),
    ]
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=trx_datetime,
            cret_no=subjects["primary"],
            customer_name="兰溪远航信息服务有限公司",
            user_memo="月度稳定兼职收入",
            cash_type="对私转账",
            cr_amount=7200.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600101",
        )
        for trx_datetime in income_months
    ]


def build_fixed_counterparty_transfer_samples(
    group_id: int,
    log_id: int,
    **kwargs,
) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    subjects = _build_phase2_subjects(
        log_id,
        staff_id_card=kwargs.get("staff_id_card"),
        family_id_cards=kwargs.get("family_id_cards"),
    )
    quarter_dates = [
        datetime(2025, 4, 8, 9, 0, 0),
        datetime(2025, 7, 8, 9, 0, 0),
        datetime(2025, 10, 8, 9, 0, 0),
        datetime(2026, 1, 8, 9, 0, 0),
    ]
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=trx_datetime,
            cret_no=subjects["primary"],
            customer_name="兰溪零工服务有限公司",
            user_memo="季度稳定兼职收入",
            cash_type="对私转账",
            cr_amount=4200.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600201",
        )
        for trx_datetime in quarter_dates
    ]


def build_salary_quick_transfer_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    subjects = _build_phase2_subjects(
        log_id,
        staff_id_card=kwargs.get("staff_id_card"),
        family_id_cards=kwargs.get("family_id_cards"),
    )
    salary_time = datetime(2026, 3, 14, 9, 0, 0)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=salary_time,
            cret_no=subjects["primary"],
            customer_name="浙江兰溪农村商业银行股份有限公司",
            user_memo="工资入账",
            cash_type="工资代发",
            cr_amount=12000.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600301",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=salary_time + timedelta(hours=6),
            cret_no=subjects["primary"],
            customer_name="张某某",
            user_memo="工资到账后快速转出",
            cash_type="对私转账",
            dr_amount=10800.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600302",
        ),
    ]


def build_salary_unused_samples(group_id: int, log_id: int, **kwargs) -> List[Dict]:
    context = _build_sample_context(log_id, **kwargs)
    subjects = _build_phase2_subjects(
        log_id,
        staff_id_card=kwargs.get("staff_id_card"),
        family_id_cards=kwargs.get("family_id_cards"),
    )
    salary_time = datetime(2026, 2, 10, 9, 0, 0)
    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=salary_time,
            cret_no=subjects["secondary"],
            customer_name="浙江兰溪农村商业银行股份有限公司",
            user_memo="工资入账",
            cash_type="工资代发",
            cr_amount=9800.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600401",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=salary_time + timedelta(days=5),
            cret_no=subjects["secondary"],
            customer_name="兰溪住房公积金中心",
            user_memo="代扣公积金",
            cash_type="代扣支出",
            dr_amount=500.0,
            le_name=context["le_name"],
            account_mask_no=context["account_no"],
            customer_account_mask_no="6222024666600402",
        ),
    ]


def build_sudden_account_closure_samples(
    group_id: int,
    log_id: int,
    *,
    account_fact: Dict,
    le_name: str = "模型测试主体",
) -> List[Dict]:
    invalid_date = datetime.strptime(account_fact["invalid_date"], "%Y-%m-%d")
    owner_id_card = account_fact["owner_id_card"]
    account_no = account_fact["account_no"]
    account_name = account_fact["account_name"]

    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=invalid_date - timedelta(days=30, hours=-1),
            cret_no=owner_id_card,
            customer_name="杭州临时往来款账户",
            user_memo=f"{account_name}销户前资金回笼",
            cash_type="对私转账",
            cr_amount=88000.0,
            le_name=le_name,
            account_mask_no=account_no,
            customer_account_mask_no="6222024666610001",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=invalid_date - timedelta(days=12, hours=2),
            cret_no=owner_id_card,
            customer_name="杭州消费支付商户",
            user_memo=f"{account_name}销户前集中支出",
            cash_type="快捷支付",
            dr_amount=62000.0,
            le_name=le_name,
            account_mask_no=account_no,
            customer_account_mask_no="6222024666610002",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=invalid_date - timedelta(days=1, hours=3),
            cret_no=owner_id_card,
            customer_name="浙江异常账户清理专户",
            user_memo=f"{account_name}异常账户销户前转出",
            cash_type="对私转账",
            dr_amount=126000.0,
            le_name=le_name,
            account_mask_no=account_no,
            customer_account_mask_no="6222024666610003",
        ),
    ]


def build_dormant_account_large_activation_samples(
    group_id: int,
    log_id: int,
    *,
    account_fact: Dict,
    le_name: str = "模型测试主体",
) -> List[Dict]:
    effective_date = datetime.strptime(account_fact["effective_date"], "%Y-%m-%d")
    activation_start = datetime(effective_date.year, effective_date.month, effective_date.day) + timedelta(days=181)
    owner_id_card = account_fact["owner_id_card"]
    account_no = account_fact["account_no"]
    account_name = account_fact["account_name"]

    return [
        _build_statement(
            group_id,
            log_id,
            trx_datetime=activation_start,
            cret_no=owner_id_card,
            customer_name="浙江存量资产回收账户",
            user_memo=f"{account_name}休眠后异常账户激活入账",
            cash_type="对公转账",
            cr_amount=180000.0,
            le_name=le_name,
            account_mask_no=account_no,
            customer_account_mask_no="6222024666620001",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=activation_start + timedelta(days=9, hours=2),
            cret_no=owner_id_card,
            customer_name="浙江大额往来备付金专户",
            user_memo=f"{account_name}休眠激活后大额转入",
            cash_type="对公转账",
            cr_amount=260000.0,
            le_name=le_name,
            account_mask_no=account_no,
            customer_account_mask_no="6222024666620002",
        ),
        _build_statement(
            group_id,
            log_id,
            trx_datetime=activation_start + timedelta(days=18, hours=1),
            cret_no=owner_id_card,
            customer_name="杭州临时资金调拨账户",
            user_memo=f"{account_name}休眠账户异常账户激活转出",
            cash_type="对私转账",
            dr_amount=120000.0,
            le_name=le_name,
            account_mask_no=account_no,
            customer_account_mask_no="6222024666620003",
        ),
    ]


LARGE_TRANSACTION_BUILDERS = {
    "HOUSE_OR_CAR_EXPENSE": build_house_or_car_samples,
    "TAX_EXPENSE": build_tax_samples,
    "SINGLE_LARGE_INCOME": build_single_large_income_samples,
    "CUMULATIVE_INCOME": build_cumulative_income_samples,
    "ANNUAL_TURNOVER": build_annual_turnover_supporting_samples,
    "LARGE_CASH_DEPOSIT": build_large_cash_deposit_samples,
    "FREQUENT_CASH_DEPOSIT": build_frequent_cash_deposit_samples,
    "LARGE_TRANSFER": build_large_transfer_samples,
}

PHASE1_RULE_BUILDERS = {
    "GAMBLING_SENSITIVE_KEYWORD": build_gambling_sensitive_keyword_samples,
    "SPECIAL_AMOUNT_TRANSACTION": build_special_amount_transaction_samples,
    "SUSPICIOUS_INCOME_KEYWORD": build_suspicious_income_keyword_samples,
    "FOREX_BUY_AMT": build_forex_buy_samples,
    "FOREX_SELL_AMT": build_forex_sell_samples,
    "STOCK_TFR_LARGE": build_stock_transfer_large_samples,
    "LARGE_STOCK_TRADING": build_large_stock_trading_samples,
    "WITHDRAW_CNT": build_withdraw_cnt_samples,
}

PHASE2_STATEMENT_RULE_BUILDERS = {
    "LOW_INCOME_RELATIVE_LARGE_TRANSACTION": build_low_income_relative_large_transaction_samples,
    "MULTI_PARTY_GAMBLING_TRANSFER": build_multi_party_gambling_transfer_samples,
    "MONTHLY_FIXED_INCOME": build_monthly_fixed_income_samples,
    "FIXED_COUNTERPARTY_TRANSFER": build_fixed_counterparty_transfer_samples,
    "SALARY_QUICK_TRANSFER": build_salary_quick_transfer_samples,
    "SALARY_UNUSED": build_salary_unused_samples,
}

ABNORMAL_ACCOUNT_RULE_BUILDERS = {
    "SUDDEN_ACCOUNT_CLOSURE": build_sudden_account_closure_samples,
    "DORMANT_ACCOUNT_LARGE_ACTIVATION": build_dormant_account_large_activation_samples,
}


def _resolve_abnormal_account_fact(rule_code: str, abnormal_accounts: List[Dict]) -> Optional[Dict]:
    for account_fact in abnormal_accounts:
        if account_fact.get("rule_code") == rule_code:
            return account_fact

    if rule_code == "SUDDEN_ACCOUNT_CLOSURE":
        return next(
            (
                account_fact
                for account_fact in abnormal_accounts
                if account_fact.get("status") == 2 and account_fact.get("invalid_date")
            ),
            None,
        )

    if rule_code == "DORMANT_ACCOUNT_LARGE_ACTIVATION":
        return next(
            (
                account_fact
                for account_fact in abnormal_accounts
                if account_fact.get("status") == 1 and account_fact.get("effective_date")
            ),
            None,
        )

    return None


def build_seed_statements_for_rule_plan(
    group_id: int,
    log_id: int,
    rule_plan: Dict,
    **kwargs,
) -> List[Dict]:
    statements: List[Dict] = []
    abnormal_accounts = list(kwargs.get("abnormal_accounts") or [])
    common_kwargs = {key: value for key, value in kwargs.items() if key != "abnormal_accounts"}

    for rule_code in rule_plan.get("large_transaction_hit_rules", []):
        builder = LARGE_TRANSACTION_BUILDERS.get(rule_code)
        if builder is not None:
            statements.extend(builder(group_id, log_id, **common_kwargs))

    for rule_code in rule_plan.get("phase1_hit_rules", []):
        builder = PHASE1_RULE_BUILDERS.get(rule_code)
        if builder is not None:
            statements.extend(builder(group_id, log_id, **common_kwargs))

    for rule_code in rule_plan.get("phase2_statement_hit_rules", []):
        builder = PHASE2_STATEMENT_RULE_BUILDERS.get(rule_code)
        if builder is not None:
            statements.extend(builder(group_id, log_id, **common_kwargs))

    for rule_code in rule_plan.get("abnormal_account_hit_rules", []):
        builder = ABNORMAL_ACCOUNT_RULE_BUILDERS.get(rule_code)
        account_fact = _resolve_abnormal_account_fact(rule_code, abnormal_accounts)
        if builder is not None and account_fact is not None:
            statements.extend(
                builder(
                    group_id,
                    log_id,
                    account_fact=account_fact,
                    le_name=common_kwargs.get("primary_enterprise_name", "模型测试主体"),
                )
            )

    return statements


def build_large_transaction_seed_statements(
    group_id: int,
    log_id: int,
    primary_enterprise_name: Optional[str] = None,
    primary_account_no: Optional[str] = None,
    staff_id_card: Optional[str] = None,
    family_id_cards: Optional[List[str]] = None,
) -> List[Dict]:
    return build_seed_statements_for_rule_plan(
        group_id=group_id,
        log_id=log_id,
        rule_plan={
            "large_transaction_hit_rules": list(LARGE_TRANSACTION_BUILDERS.keys()),
            "phase1_hit_rules": [],
        },
        primary_enterprise_name=primary_enterprise_name,
        primary_account_no=primary_account_no,
        staff_id_card=staff_id_card,
        family_id_cards=family_id_cards,
    )
