# -*- coding: utf-8 -*-
"""
财务日度汇总任务

功能说明：
    以"日期"为粒度，汇总当日财务数据
    
数据来源：
    - dwd_settlement_head: 结账单头表
    - dwd_groupbuy_redemption: 团购核销
    - dwd_recharge_order: 充值订单
    - dws_finance_expense_summary: 支出汇总（Excel导入）
    - dws_platform_settlement: 平台回款/服务费（Excel导入）

目标表：
    dws.dws_finance_daily_summary

更新策略：
    - 更新频率：每小时更新当日数据
    - 幂等方式：delete-before-insert（按日期）
    
业务规则：
    - 发生额：table_charge_money + goods_money + assistant_pd_money + assistant_cx_money
    - 团购优惠：coupon_amount - 团购支付金额
    - 团购支付：pl_coupon_sale_amount 或关联 groupbuy_redemption.ledger_unit_price
    - 首充/续充：通过 is_first 字段区分

作者：ETL团队
创建日期：2026-02-01
"""

from __future__ import annotations

from datetime import date
from decimal import Decimal
from typing import Any, Dict, List

from .base_dws_task import TaskContext
from .finance_base_task import FinanceBaseTask


# CHANGE 2025-07-16 | task 2.3: 继承 FinanceBaseTask，共享提取方法
class FinanceDailyTask(FinanceBaseTask):
    """
    财务日度汇总任务
    
    汇总每日的：
    - 发生额（正价）
    - 优惠拆分
    - 确认收入
    - 现金流（流入/流出）
    - 充值统计（首充/续充）
    - 订单统计
    """

    # CHANGE 2025-07-15 | task 1.3: 声明日期列，供基类默认 load() 使用
    DATE_COL = "stat_date"

    # CHANGE 2026-03-22 | P14: 财务日度任务完成后触发 AI App2 预生成
    AI_TRIGGER_EVENT = "dws_completed"
    
    def get_task_code(self) -> str:
        return "DWS_FINANCE_DAILY"
    
    def get_target_table(self) -> str:
        return "dws_finance_daily_summary"
    
    def get_primary_keys(self) -> List[str]:
        return ["site_id", "stat_date"]
    
    # ==========================================================================
    # ETL主流程
    # ==========================================================================
    
    def extract(self, context: TaskContext) -> Dict[str, Any]:
        """
        提取数据
        """
        start_date = context.window_start.date() if hasattr(context.window_start, 'date') else context.window_start
        end_date = context.window_end.date() if hasattr(context.window_end, 'date') else context.window_end
        site_id = context.store_id
        
        self.logger.info(
            "%s: 提取数据，日期范围 %s ~ %s",
            self.get_task_code(), start_date, end_date
        )
        
        # 1. 获取结账单汇总
        settlement_summary = self._extract_settlement_summary(site_id, start_date, end_date)
        
        # 2. 获取团购核销汇总
        groupbuy_summary = self._extract_groupbuy_summary(site_id, start_date, end_date)
        
        # 3. 获取充值汇总
        recharge_summary = self._extract_recharge_summary(site_id, start_date, end_date)

        # 3.1 获取赠送卡消费汇总（余额变动）
        gift_card_summary = self._extract_gift_card_consume_summary(site_id, start_date, end_date)

        # 3.2 获取支付方式拆分
        # CHANGE 2026-03-27 | board-finance-integration T1.1 | 新增支付方式拆分
        payment_split = self._extract_payment_split(site_id, start_date, end_date)
        
        # 4. 获取支出汇总（来自导入表）
        expense_summary = self._extract_expense_summary(site_id, start_date, end_date)
        
        # 5. 获取平台回款汇总（来自导入表）
        platform_summary = self._extract_platform_summary(site_id, start_date, end_date)
        
        # 6. 获取大客户优惠明细（用于拆分手动优惠）
        big_customer_summary = self._extract_big_customer_discounts(site_id, start_date, end_date)
        
        return {
            'settlement_summary': settlement_summary,
            'groupbuy_summary': groupbuy_summary,
            'recharge_summary': recharge_summary,
            'gift_card_summary': gift_card_summary,
            'payment_split': payment_split,
            'expense_summary': expense_summary,
            'platform_summary': platform_summary,
            'big_customer_summary': big_customer_summary,
            'start_date': start_date,
            'end_date': end_date,
            'site_id': site_id
        }
    
    def transform(self, extracted: Dict[str, Any], context: TaskContext) -> List[Dict[str, Any]]:
        """
        转换数据：按日期聚合
        """
        settlement_summary = extracted['settlement_summary']
        groupbuy_summary = extracted['groupbuy_summary']
        recharge_summary = extracted['recharge_summary']
        gift_card_summary = extracted['gift_card_summary']
        expense_summary = extracted['expense_summary']
        platform_summary = extracted['platform_summary']
        big_customer_summary = extracted['big_customer_summary']
        payment_split = extracted['payment_split']
        site_id = extracted['site_id']
        
        self.logger.info(
            "%s: 转换数据，%d 天结账数据，%d 天充值数据",
            self.get_task_code(), len(settlement_summary), len(recharge_summary)
        )
        
        # 按日期合并数据
        dates = set()
        for item in settlement_summary + recharge_summary + gift_card_summary + expense_summary + platform_summary:
            stat_date = item.get('stat_date')
            if stat_date:
                dates.add(stat_date)
        
        # 构建索引
        settle_index = {s['stat_date']: s for s in settlement_summary}
        groupbuy_index = {g['stat_date']: g for g in groupbuy_summary}
        recharge_index = {r['stat_date']: r for r in recharge_summary}
        gift_card_index = {g['stat_date']: g for g in gift_card_summary}
        expense_index = {e['stat_date']: e for e in expense_summary}
        platform_index = {p['stat_date']: p for p in platform_summary}
        big_customer_index = {b['stat_date']: b for b in big_customer_summary}
        payment_split_index = {ps['stat_date']: ps for ps in payment_split}
        
        results = []
        for stat_date in sorted(dates):
            settle = settle_index.get(stat_date, {})
            groupbuy = groupbuy_index.get(stat_date, {})
            recharge = recharge_index.get(stat_date, {})
            gift_card = gift_card_index.get(stat_date, {})
            expense = expense_index.get(stat_date, {})
            platform = platform_index.get(stat_date, {})
            big_customer = big_customer_index.get(stat_date, {})
            ps = payment_split_index.get(stat_date, {})
            
            record = self._build_daily_record(
                stat_date, settle, groupbuy, recharge, gift_card, expense, platform, big_customer, site_id, ps
            )
            results.append(record)
        
        return results
    
    # load() 已移除——使用 BaseDwsTask 默认实现（DATE_COL="stat_date"）

    # 提取方法已迁移至 FinanceBaseTask（task 2.3）
    
    # ==========================================================================
    # 数据转换方法
    # ==========================================================================
    
    def _build_daily_record(
        self,
        stat_date: date,
        settle: Dict[str, Any],
        groupbuy: Dict[str, Any],
        recharge: Dict[str, Any],
        gift_card: Dict[str, Any],
        expense: Dict[str, Any],
        platform: Dict[str, Any],
        big_customer: Dict[str, Any],
        site_id: int,
        payment_split: Dict[str, Any],
    ) -> Dict[str, Any]:
        """
        构建日度财务记录
        """
        # 发生额
        gross_amount = self.safe_decimal(settle.get('gross_amount', 0))
        table_fee_amount = self.safe_decimal(settle.get('table_fee_amount', 0))
        goods_amount = self.safe_decimal(settle.get('goods_amount', 0))
        assistant_pd_amount = self.safe_decimal(settle.get('assistant_pd_amount', 0))
        assistant_cx_amount = self.safe_decimal(settle.get('assistant_cx_amount', 0))
        
        # 支付
        cash_pay_amount = self.safe_decimal(settle.get('cash_pay_amount', 0))
        card_pay_amount = self.safe_decimal(settle.get('card_pay_amount', 0))
        balance_pay_amount = self.safe_decimal(settle.get('balance_pay_amount', 0))
        
        # 优惠
        coupon_amount = self.safe_decimal(settle.get('coupon_amount', 0))
        pl_coupon_sale = self.safe_decimal(settle.get('pl_coupon_sale_amount', 0))
        groupbuy_pay = self.safe_decimal(groupbuy.get('groupbuy_pay_total', 0))
        
        # 团购支付金额：优先使用pl_coupon_sale_amount，否则使用groupbuy核销金额
        if pl_coupon_sale > 0:
            groupbuy_pay_amount = pl_coupon_sale
        else:
            groupbuy_pay_amount = groupbuy_pay
        
        # 团购优惠 = 团购抵消台费 - 团购支付金额
        discount_groupbuy = coupon_amount - groupbuy_pay_amount
        if discount_groupbuy < 0:
            discount_groupbuy = Decimal('0')
        
        adjust_amount = self.safe_decimal(settle.get('adjust_amount', 0))
        member_discount = self.safe_decimal(settle.get('member_discount_amount', 0))
        rounding_amount = self.safe_decimal(settle.get('rounding_amount', 0))
        big_customer_amount = self.safe_decimal(big_customer.get('big_customer_amount', 0))
        # 大客户优惠不超过手动调整总额（大客户是 adjust 的子集）
        big_customer_amount = min(big_customer_amount, adjust_amount) if adjust_amount > 0 else Decimal('0')
        other_discount = adjust_amount - big_customer_amount
        if other_discount < 0:
            other_discount = Decimal('0')
        
        # 赠送卡消费（来自余额变动）
        gift_card_consume_amount = self.safe_decimal(gift_card.get('gift_card_consume', 0))

        # 优惠合计（大客户 + 其他 = adjust_amount，互斥拆分）
        discount_total = discount_groupbuy + member_discount + gift_card_consume_amount + big_customer_amount + other_discount + rounding_amount
        
        # 确认收入
        confirmed_income = gross_amount - discount_total
        
        # 支付方式拆分
        # CHANGE 2026-03-27 | board-finance-integration T1.1 | 新增支付方式拆分
        cash_paper_amount = self.safe_decimal(payment_split.get('cash_paper_amount', 0))
        scan_pay_amount = self.safe_decimal(payment_split.get('scan_pay_amount', 0))

        # 现金流
        platform_settlement_amount = self.safe_decimal(platform.get('settlement_amount', 0))
        platform_fee_amount = (
            self.safe_decimal(platform.get('commission_amount', 0))
            + self.safe_decimal(platform.get('service_fee', 0))
        )
        recharge_cash_inflow = self.safe_decimal(recharge.get('recharge_cash', 0))
        platform_inflow = platform_settlement_amount if platform_settlement_amount > 0 else groupbuy_pay_amount
        cash_inflow_total = cash_pay_amount + platform_inflow + recharge_cash_inflow
        
        cash_outflow_total = self.safe_decimal(expense.get('expense_amount', 0)) + platform_fee_amount
        cash_balance_change = cash_inflow_total - cash_outflow_total
        
        # 卡消费
        # CHANGE 2026-03-07 | balance 恒等式校准
        # balance_amount = recharge_card_amount + gift_card_amount
        # recharge_card_consume 只取现金充值部分（recharge_card_amount），不加 balance_amount 避免重复计算
        recharge_card_consume = card_pay_amount
        gift_card_consume = gift_card_consume_amount
        card_consume_total = recharge_card_consume + gift_card_consume
        
        # 充值统计
        recharge_count = self.safe_int(recharge.get('recharge_count', 0))
        recharge_total = self.safe_decimal(recharge.get('recharge_total', 0))
        recharge_cash = self.safe_decimal(recharge.get('recharge_cash', 0))
        recharge_gift = self.safe_decimal(recharge.get('recharge_gift', 0))
        first_recharge_count = self.safe_int(recharge.get('first_recharge_count', 0))
        first_recharge_amount = self.safe_decimal(recharge.get('first_recharge_total', 0))
        renewal_count = self.safe_int(recharge.get('renewal_count', 0))
        renewal_amount = self.safe_decimal(recharge.get('renewal_total', 0))
        
        # 订单统计
        order_count = self.safe_int(settle.get('order_count', 0))
        member_order_count = self.safe_int(settle.get('member_order_count', 0))
        guest_order_count = self.safe_int(settle.get('guest_order_count', 0))
        avg_order_amount = gross_amount / order_count if order_count > 0 else Decimal('0')
        
        return {
            'site_id': site_id,
            'tenant_id': self.config.get("app.tenant_id", site_id),
            'stat_date': stat_date,
            # 发生额
            'gross_amount': gross_amount,
            'table_fee_amount': table_fee_amount,
            'goods_amount': goods_amount,
            'assistant_pd_amount': assistant_pd_amount,
            'assistant_cx_amount': assistant_cx_amount,
            # 优惠
            'discount_total': discount_total,
            'discount_groupbuy': discount_groupbuy,
            'discount_vip': member_discount,
            'discount_gift_card': gift_card_consume_amount,
            # CHANGE 2026-03-07 | discount_manual 语义修正：存储大客户优惠（与 discount_other 互斥，两者之和 = adjust_amount）
            'discount_manual': big_customer_amount,
            'discount_rounding': rounding_amount,
            'discount_other': other_discount,
            # 确认收入
            'confirmed_income': confirmed_income,
            # 现金流
            'cash_inflow_total': cash_inflow_total,
            'cash_pay_amount': cash_pay_amount,
            'cash_paper_amount': cash_paper_amount,
            'scan_pay_amount': scan_pay_amount,
            'groupbuy_pay_amount': groupbuy_pay_amount,
            'platform_settlement_amount': platform_settlement_amount,
            'platform_fee_amount': platform_fee_amount,
            'recharge_cash_inflow': recharge_cash_inflow,
            'card_consume_total': card_consume_total,
            'recharge_card_consume': recharge_card_consume,
            'gift_card_consume': gift_card_consume,
            'cash_outflow_total': cash_outflow_total,
            'cash_balance_change': cash_balance_change,
            # 充值统计
            'recharge_count': recharge_count,
            'recharge_total': recharge_total,
            'recharge_cash': recharge_cash,
            'recharge_gift': recharge_gift,
            'first_recharge_count': first_recharge_count,
            'first_recharge_amount': first_recharge_amount,
            'renewal_count': renewal_count,
            'renewal_amount': renewal_amount,
            # 订单统计
            'order_count': order_count,
            'member_order_count': member_order_count,
            'guest_order_count': guest_order_count,
            'avg_order_amount': avg_order_amount,
        }


# 便于外部导入
__all__ = ['FinanceDailyTask']
