"""每日收支详细统计（供 /jituan/houtai/szxx，旧 /houtai/szxx 不变）。"""
from datetime import date

from django.db.models import Sum
from django.db.models.functions import ExtractDay, ExtractMonth, ExtractYear

from config.models import DailyIncomeStat, DailyPayoutStat
from jituan.services.club_context import (
    filter_club_char_field,
    resolve_club_id_from_request,
    resolve_club_scope,
)
from jituan.services.daily_finance_display import (
    sum_income_stat_for_date,
    sum_payout_stat_for_date,
    today_income_for_dashboard,
)


def _month_bounds(y, m):
    start = date(int(y), int(m), 1)
    if int(m) == 12:
        end = date(int(y) + 1, 1, 1)
    else:
        end = date(int(y), int(m) + 1, 1)
    return start, end


def _year_bounds(y):
    y = int(y)
    return date(y, 1, 1), date(y + 1, 1, 1)


def build_szxx_payload(request, granularity, year, month, summary_date):
    """
    与 SzxxView 返回结构一致。
    统一用 date 字段查询（与 /houtai/caiwu 四个板子一致），不用 year/month/day 冗余列。
    """
    now = date.today()
    income_base = filter_club_char_field(DailyIncomeStat.objects.all(), request, field='club_id')
    payout_base = filter_club_char_field(DailyPayoutStat.objects.all(), request, field='club_id')

    if granularity == 'day':
        if not year or not month:
            return None, '按日统计需要年份和月份'
        year, month = int(year), int(month)
        chart_start, chart_end = _month_bounds(year, month)

        income_rows = (
            income_base.filter(date__gte=chart_start, date__lt=chart_end)
            .annotate(day_key=ExtractDay('date'))
            .values('day_key')
            .annotate(total_income=Sum('total_amount'), total_count=Sum('total_count'))
            .order_by('day_key')
        )
        payout_rows = (
            payout_base.filter(date__gte=chart_start, date__lt=chart_end)
            .annotate(day_key=ExtractDay('date'))
            .values('day_key')
            .annotate(total_payout=Sum('total_amount'), total_count=Sum('total_count'))
            .order_by('day_key')
        )

        if not summary_date:
            summary_date = now.strftime('%Y-%m-%d')
        summary_d = date.fromisoformat(str(summary_date)[:10])
        if summary_d == now:
            inc_amount, inc_count = today_income_for_dashboard(summary_d, request)
        else:
            inc_amount, inc_count = sum_income_stat_for_date(summary_d, request)
        pay_amount, pay_count = sum_payout_stat_for_date(summary_d, request)
        income_summary = {'total_income': inc_amount, 'total_count': inc_count}
        payout_summary = {'total_payout': pay_amount, 'total_count': pay_count}

        def _fmt_day(key):
            return f'{year}-{month:02d}-{int(key):02d}'

    elif granularity == 'month':
        if not year:
            return None, '按月统计需要年份'
        year = int(year)
        chart_start, chart_end = _year_bounds(year)

        income_rows = (
            income_base.filter(date__gte=chart_start, date__lt=chart_end)
            .annotate(month_key=ExtractMonth('date'))
            .values('month_key')
            .annotate(total_income=Sum('total_amount'), total_count=Sum('total_count'))
            .order_by('month_key')
        )
        payout_rows = (
            payout_base.filter(date__gte=chart_start, date__lt=chart_end)
            .annotate(month_key=ExtractMonth('date'))
            .values('month_key')
            .annotate(total_payout=Sum('total_amount'), total_count=Sum('total_count'))
            .order_by('month_key')
        )

        if not summary_date:
            summary_date = now.strftime('%Y-%m')
        parts = str(summary_date).split('-')
        s_start, s_end = _month_bounds(parts[0], parts[1])
        income_summary = income_base.filter(date__gte=s_start, date__lt=s_end).aggregate(
            total_income=Sum('total_amount'), total_count=Sum('total_count'),
        )
        payout_summary = payout_base.filter(date__gte=s_start, date__lt=s_end).aggregate(
            total_payout=Sum('total_amount'), total_count=Sum('total_count'),
        )

        def _fmt_day(key):
            return f'{year}-{int(key):02d}'

    elif granularity == 'year':
        income_rows = (
            income_base.annotate(year_key=ExtractYear('date'))
            .values('year_key')
            .annotate(total_income=Sum('total_amount'), total_count=Sum('total_count'))
            .order_by('year_key')
        )
        payout_rows = (
            payout_base.annotate(year_key=ExtractYear('date'))
            .values('year_key')
            .annotate(total_payout=Sum('total_amount'), total_count=Sum('total_count'))
            .order_by('year_key')
        )

        if not summary_date:
            summary_date = str(now.year)
        s_start, s_end = _year_bounds(int(summary_date))
        income_summary = income_base.filter(date__gte=s_start, date__lt=s_end).aggregate(
            total_income=Sum('total_amount'), total_count=Sum('total_count'),
        )
        payout_summary = payout_base.filter(date__gte=s_start, date__lt=s_end).aggregate(
            total_payout=Sum('total_amount'), total_count=Sum('total_count'),
        )

        def _fmt_day(key):
            return str(int(key))

    else:
        return None, '无效的颗粒度'

    data_map = {}
    if granularity == 'day':
        key_field = 'day_key'
    elif granularity == 'month':
        key_field = 'month_key'
    else:
        key_field = 'year_key'

    for item in income_rows:
        key = item[key_field]
        data_map[key] = {
            'income': float(item['total_income'] or 0),
            'income_count': item['total_count'] or 0,
            'payout': 0.0,
            'payout_count': 0,
        }

    for item in payout_rows:
        key = item[key_field]
        if key not in data_map:
            data_map[key] = {'income': 0.0, 'income_count': 0, 'payout': 0.0, 'payout_count': 0}
        data_map[key]['payout'] = float(item['total_payout'] or 0)
        data_map[key]['payout_count'] = item['total_count'] or 0

    time_series = []
    for key, vals in data_map.items():
        profit = round(vals['income'] - vals['payout'], 2)
        time_series.append({
            'date': _fmt_day(key),
            'income': vals['income'],
            'payout': vals['payout'],
            'profit': profit,
        })
    time_series.sort(key=lambda x: x['date'])

    total_income = float(income_summary['total_income'] or 0)
    total_payout = float(payout_summary['total_payout'] or 0)

    return {
        'club_id': resolve_club_id_from_request(request),
        'scope': resolve_club_scope(request),
        'time_series': time_series,
        'summary': {
            'total_income': total_income,
            'total_income_count': income_summary['total_count'] or 0,
            'total_payout': total_payout,
            'total_payout_count': payout_summary['total_count'] or 0,
            'total_profit': round(total_income - total_payout, 2),
        },
    }, None
