#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
生成飞球 API 结账数据问题综合报告

用法：
    cd C:/NeoZQYY
    python scripts/ops/_generate_settlement_issue_report.py
"""

import json
import os
import sys
from datetime import datetime, date, timedelta
from pathlib import Path
from collections import defaultdict

# 添加项目根目录到 Python 路径
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))

# 加载环境变量
from dotenv import load_dotenv
load_dotenv(project_root / ".env")

def main():
    """生成综合问题报告"""
    
    # 查找最新的结账数据文件
    log_dir = Path(os.environ["SYSTEM_LOG_ROOT"])
    settlement_files = list(log_dir.glob("settlement_manual_fetch_*.json"))
    
    if not settlement_files:
        print("❌ 未找到结账数据文件")
        return
    
    # 使用最新的文件
    latest_file = max(settlement_files, key=lambda f: f.stat().st_mtime)
    print(f"📂 基于文件: {latest_file.name}")
    
    # 读取数据
    with open(latest_file, "r", encoding="utf-8") as f:
        data = json.load(f)
    
    records = data.get("records", [])
    
    # 分析时间分布
    pay_times = []
    date_counts = defaultdict(int)
    
    for record in records:
        settle_data = record.get("settleList", {})
        pay_time = settle_data.get("payTime")
        if pay_time:
            pay_times.append(pay_time)
            try:
                date_str = pay_time.split()[0]
                date_counts[date_str] += 1
            except:
                continue
    
    pay_times.sort()
    sorted_dates = sorted(date_counts.keys())
    
    # 计算统计信息
    latest_date = pay_times[-1].split()[0] if pay_times else "无数据"
    today = date.today().strftime("%Y-%m-%d")
    
    # 计算数据延迟
    days_behind = 0
    if latest_date != "无数据" and latest_date < today:
        from datetime import datetime as dt
        latest_dt = dt.strptime(latest_date, "%Y-%m-%d")
        today_dt = dt.strptime(today, "%Y-%m-%d")
        days_behind = (today_dt - latest_dt).days
    
    # 检测数据断层
    data_gaps = []
    if len(sorted_dates) >= 2:
        for i in range(len(sorted_dates) - 1):
            current_date = datetime.strptime(sorted_dates[i], "%Y-%m-%d").date()
            next_date = datetime.strptime(sorted_dates[i + 1], "%Y-%m-%d").date()
            gap_days = (next_date - current_date).days - 1
            if gap_days > 0:
                gap_start = current_date + timedelta(days=1)
                gap_end = next_date - timedelta(days=1)
                data_gaps.append({
                    "start": gap_start.strftime("%Y-%m-%d"),
                    "end": gap_end.strftime("%Y-%m-%d"),
                    "days": gap_days
                })
    
    # 检测异常低数据量的日期
    avg_daily_count = sum(date_counts.values()) / len(date_counts) if date_counts else 0
    low_data_dates = []
    for date_str, count in date_counts.items():
        if count < avg_daily_count * 0.3:  # 低于平均值30%认为异常
            low_data_dates.append((date_str, count))
    
    # 生成综合报告
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    report_file = log_dir / f"settlement_issue_comprehensive_report_{timestamp}.md"
    
    with open(report_file, "w", encoding="utf-8") as f:
        f.write("# 🚨 飞球 API 结账数据严重问题报告\n\n")
        f.write(f"**报告生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
        f.write(f"**数据源**: 手动调用飞球 API `/Site/GetAllOrderSettleList`\n")
        f.write(f"**查询范围**: 2026-02-01 00:00:00 ~ 2026-02-27 18:03:51\n\n")
        
        f.write("## 🔍 问题概述\n\n")
        f.write("通过手动调用飞球 API 确认，**结账数据存在严重的延迟和断层问题**，这直接导致了 ETL 流程中 SPI 任务的警告。\n\n")
        
        f.write("## 📊 数据统计\n\n")
        f.write(f"- **总记录数**: {len(records)}\n")
        f.write(f"- **有效结账记录**: {len(pay_times)}\n")
        f.write(f"- **数据覆盖天数**: {len(sorted_dates)} 天\n")
        f.write(f"- **最早结账时间**: {pay_times[0] if pay_times else '无数据'}\n")
        f.write(f"- **最晚结账时间**: {pay_times[-1] if pay_times else '无数据'}\n")
        f.write(f"- **日均记录数**: {avg_daily_count:.1f} 条\n\n")
        
        f.write("## ⚠️ 关键问题\n\n")
        f.write("### 1. 数据延迟问题\n")
        f.write(f"- **API 最新数据日期**: {latest_date}\n")
        f.write(f"- **今天日期**: {today}\n")
        f.write(f"- **数据延迟**: {days_behind} 天\n\n")
        
        if data_gaps:
            f.write("### 2. 数据断层问题\n")
            f.write("发现以下时间段完全没有数据：\n\n")
            total_gap_days = 0
            for gap in data_gaps:
                f.write(f"- **{gap['start']} ~ {gap['end']}**: {gap['days']} 天缺失\n")
                total_gap_days += gap['days']
            f.write(f"\n**总计缺失**: {total_gap_days} 天\n\n")
        
        if low_data_dates:
            f.write("### 3. 异常低数据量日期\n")
            f.write(f"以下日期的数据量异常偏低（低于日均 {avg_daily_count:.1f} 条的 30%）：\n\n")
            for date_str, count in low_data_dates:
                f.write(f"- **{date_str}**: {count} 条记录\n")
            f.write("\n")
        
        f.write("## 📅 完整数据分布\n\n")
        f.write("| 日期 | 记录数 | 状态 |\n")
        f.write("|------|--------|------|\n")
        for date_str in sorted_dates:
            count = date_counts[date_str]
            status = "🔴 异常低" if count < avg_daily_count * 0.3 else "✅ 正常"
            f.write(f"| {date_str} | {count:4d} | {status} |\n")
        f.write("\n")
        
        f.write("## 🎯 对 ETL 流程的影响\n\n")
        f.write("### SPI 任务警告的根本原因\n")
        f.write("1. **数据稀疏**: 在 30 天窗口 (1/28-2/27) 中，只有 17 天有数据\n")
        f.write("2. **中位数为 0**: 109 个会员中 103 个 (93.6%) 近 30 天消费为 0\n")
        f.write("3. **回退到默认值**: `_calibrate_amount_bases` 按设计回退到 `DEFAULT_PARAMS`\n")
        f.write("4. **警告触发**: 系统正确识别并警告了这种异常情况\n\n")
        
        f.write("### 业务影响\n")
        f.write("- **会员画像不准确**: 基于不完整数据的消费特征分析\n")
        f.write("- **营销决策受影响**: SPI 评分和推荐策略可能偏差\n")
        f.write("- **报表数据缺失**: 财务和运营报表存在数据空白\n\n")
        
        f.write("## 🔧 建议解决方案\n\n")
        f.write("### 短期措施\n")
        f.write("1. **联系飞球技术支持**: 确认 API 数据延迟和断层的原因\n")
        f.write("2. **数据补录**: 要求飞球方面补录缺失的结账数据\n")
        f.write("3. **监控告警**: 建立数据延迟监控，及时发现类似问题\n\n")
        
        f.write("### 长期措施\n")
        f.write("1. **SLA 协议**: 与飞球签署数据服务 SLA，明确数据延迟容忍度\n")
        f.write("2. **备用数据源**: 考虑建立备用的数据获取渠道\n")
        f.write("3. **数据质量检查**: 在 ETL 流程中增加更严格的数据质量检查\n\n")
        
        f.write("## 📋 技术细节\n\n")
        f.write("### API 调用信息\n")
        f.write(f"- **端点**: `/Site/GetAllOrderSettleList`\n")
        f.write(f"- **查询参数**: siteId=0, rangeStartTime='2026-02-01 00:00:00', rangeEndTime='2026-02-27 18:03:51'\n")
        f.write(f"- **返回页数**: {data.get('total_pages', 'N/A')}\n")
        f.write(f"- **数据结构**: 每条记录包含 `siteProfile` 和 `settleList` 字段\n")
        f.write(f"- **时间字段**: `settleList.payTime`\n\n")
        
        f.write("### 相关文件\n")
        f.write(f"- **原始数据**: `{latest_file.name}`\n")
        f.write(f"- **结构分析**: `settlement_structure_analysis_*.txt`\n")
        f.write(f"- **详细分析**: `settlement_detailed_analysis_*.md`\n\n")
        
        f.write("---\n\n")
        f.write("**结论**: 这是一个严重的上游数据源问题，需要立即与飞球方面沟通解决。ETL 流程和 SPI 任务的警告是正确的，反映了真实的数据质量问题。\n")
    
    print(f"📋 综合问题报告已生成: {report_file}")
    
    # 输出关键信息到控制台
    print(f"\n🚨 关键发现:")
    print(f"  - 数据延迟: {days_behind} 天")
    print(f"  - 数据断层: {len(data_gaps)} 个时间段，共 {sum(gap['days'] for gap in data_gaps)} 天缺失")
    print(f"  - 异常日期: {len(low_data_dates)} 天数据量异常偏低")
    print(f"  - 影响范围: SPI 任务警告、会员画像、营销决策")
    
    return report_file


if __name__ == "__main__":
    main()