#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数据导出模块 - 导出所有诊所的回访记录到Excel
"""

import os
import json
import io
from datetime import datetime
from typing import Dict, List, Any
import pymysql
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter

class DataExporter:
    """数据导出器"""
    
    def __init__(self):
        # 检查是否在Docker容器中运行
        if os.path.exists('/app'):
            # Docker容器内，连接MySQL容器
            self.db_config = {
                'host': 'mysql',
                'port': 3306,
                'user': 'callback_user',
                'password': 'dev_password_123',
                'database': 'callback_system',
                'charset': 'utf8mb4',
                'use_unicode': True,
                'init_command': 'SET NAMES utf8mb4'
            }
        else:
            # 本地运行，连接本地MySQL
            self.db_config = {
                'host': 'localhost',
                'port': 3306,
                'user': 'callback_user',
                'password': 'dev_password_123',
                'database': 'callback_system',
                'charset': 'utf8mb4',
                'use_unicode': True,
                'init_command': 'SET NAMES utf8mb4'
            }
        
    def get_clinic_data(self) -> Dict[str, Any]:
        """获取所有诊所的数据"""
        try:
            connection = pymysql.connect(**self.db_config)
            cursor = connection.cursor()
            
            # 获取所有回访记录，同时关联患者表获取诊所信息
            cursor.execute("""
                SELECT
                    cr.case_number,
                    cr.callback_methods,
                    cr.callback_result,
                    cr.callback_record,
                    cr.operator,
                    cr.create_time,
                    cr.update_time,
                    cr.next_appointment_time,
                    cr.failure_reason,
                    cr.abandon_reason,
                    cr.ai_feedback_type,
                    cr.failure_reason_note,
                    cr.abandon_reason_note,
                    cr.ai_feedback_note,
                    cr.callback_status,
                    p.clinic_name
                FROM callback_records cr
                LEFT JOIN patients p ON cr.case_number = p.case_number
                ORDER BY cr.case_number, cr.create_time
            """)
            
            records = cursor.fetchall()
            
            # 按诊所分组数据
            clinic_data = {}
            print(f"处理 {len(records)} 条记录...")
            
            for record in records:
                case_number = record[0]
                clinic_name = record[15] or '未知门诊'  # 从patients表获取诊所名称（索引更新为15）

                if clinic_name not in clinic_data:
                    clinic_data[clinic_name] = {
                        'records': [],
                        'unique_patients': set(),  # 使用set来统计唯一患者
                        'patient_final_status': {},  # 记录每个患者的最终回访状态
                        'total_count': 0,
                        'success_count': 0,
                        'failed_count': 0,
                        'pending_count': 0
                    }

                # 处理callback_methods字段 - 解析JSON字符串
                callback_methods_raw = record[1]
                try:
                    if isinstance(callback_methods_raw, str):
                        callback_methods = json.loads(callback_methods_raw)
                    else:
                        callback_methods = callback_methods_raw if callback_methods_raw else []
                except (json.JSONDecodeError, TypeError):
                    # 如果解析失败，尝试直接使用原始值
                    callback_methods = [str(callback_methods_raw)] if callback_methods_raw else []

                # 添加记录
                clinic_data[clinic_name]['records'].append({
                    'case_number': case_number,
                    'callback_methods': callback_methods,
                    'callback_result': record[2],
                    'callback_record': record[3],
                    'operator': record[4],
                    'create_time': record[5],
                    'update_time': record[6],
                    'next_appointment_time': record[7],
                    'failure_reason': record[8],
                    'abandon_reason': record[9],
                    'ai_feedback_type': record[10],
                    'failure_reason_note': record[11],
                    'abandon_reason_note': record[12],
                    'ai_feedback_note': record[13],
                    'callback_status': record[14]
                })
                
                # 统计唯一患者数
                clinic_data[clinic_name]['unique_patients'].add(case_number)
                
                # 统计记录总数
                clinic_data[clinic_name]['total_count'] += 1
                
                # 记录每个患者的回访状态（按时间顺序，后面的会覆盖前面的）
                clinic_data[clinic_name]['patient_final_status'][case_number] = record[2]
            
            # 统计每个诊所的患者最终回访状态
            for clinic_name in clinic_data:
                clinic_data[clinic_name]['unique_patient_count'] = len(clinic_data[clinic_name]['unique_patients'])
                
                # 重置计数
                clinic_data[clinic_name]['success_count'] = 0
                clinic_data[clinic_name]['failed_count'] = 0
                clinic_data[clinic_name]['pending_count'] = 0
                
                # 统计每个患者的最终回访状态
                for final_status in clinic_data[clinic_name]['patient_final_status'].values():
                    if final_status == '成功':
                        clinic_data[clinic_name]['success_count'] += 1
                    elif final_status == '不成功':
                        clinic_data[clinic_name]['failed_count'] += 1
                    else:
                        clinic_data[clinic_name]['pending_count'] += 1
            
            connection.close()
            return clinic_data
            
        except Exception as e:
            print(f"获取诊所数据失败: {e}")
            return {}
    
    def _get_clinic_id_from_case(self, case_number: str, clinic_config: Dict) -> str:
        """根据病历号获取诊所ID - 已废弃，现在直接从patients表获取"""
        # 这个方法已经不再使用，保留只是为了兼容性
        return 'unknown'
    
    def _get_clinic_config(self) -> Dict:
        """获取诊所配置 - 已废弃，现在直接从patients表获取"""
        # 这个方法已经不再使用，保留只是为了兼容性
        return {}
    
    def export_to_excel(self, output_path: str = None) -> str:
        """导出数据到Excel文件"""
        if not output_path:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            output_path = f"回访记录导出_{timestamp}.xlsx"
        
        # 获取数据
        clinic_data = self.get_clinic_data()
        
        # 创建工作簿
        wb = Workbook()
        
        # 创建总览表
        self._create_summary_sheet(wb, clinic_data)
        
        # 创建各诊所详细表
        print(f"开始创建诊所详细表...")
        for clinic_name, data in clinic_data.items():
            if data['records']:
                print(f"创建诊所表: {clinic_name} - {data['total_count']} 条记录)")
                self._create_clinic_sheet(wb, clinic_name, data)
            else:
                print(f"跳过空诊所: {clinic_name} - {data['total_count']} 条记录)")
        
        print(f"Excel工作表列表: {wb.sheetnames}")
        
        # 删除默认的Sheet
        if 'Sheet' in wb.sheetnames:
            wb.remove(wb['Sheet'])
        
        # 保存文件
        wb.save(output_path)
        return output_path

    def export_to_memory(self) -> bytes:
        """导出数据到内存缓冲区，返回二进制数据"""
        # 获取数据
        clinic_data = self.get_clinic_data()

        # 创建工作簿
        wb = Workbook()

        # 创建总览表
        self._create_summary_sheet(wb, clinic_data)

        # 创建各诊所详细表
        print(f"开始创建诊所详细表...")
        for clinic_name, data in clinic_data.items():
            if data['records']:
                print(f"创建诊所表: {clinic_name} - {data['total_count']} 条记录)")
                self._create_clinic_sheet(wb, clinic_name, data)
            else:
                print(f"跳过空诊所: {clinic_name} - {data['total_count']} 条记录)")

        print(f"Excel工作表列表: {wb.sheetnames}")

        # 删除默认的Sheet
        if 'Sheet' in wb.sheetnames:
            wb.remove(wb['Sheet'])

        # 保存到内存缓冲区
        buffer = io.BytesIO()
        wb.save(buffer)
        buffer.seek(0)
        return buffer.getvalue()
    
    def _create_summary_sheet(self, wb: Workbook, clinic_data: Dict[str, Any]):
        """创建总览表"""
        ws = wb.create_sheet("总览")
        
        # 设置标题
        title = "患者回访记录系统 - 数据总览"
        ws['A1'] = title
        ws.merge_cells('A1:F1')
        
        # 设置标题样式
        title_font = Font(size=16, bold=True)
        title_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid")
        title_alignment = Alignment(horizontal="center", vertical="center")
        
        ws['A1'].font = title_font
        ws['A1'].fill = title_fill
        ws['A1'].alignment = title_alignment
        
        # 设置列标题
        headers = ["诊所名称", "已回访患者数", "成功", "不成功", "放弃回访", "成功率"]
        for col, header in enumerate(headers, 1):
            cell = ws.cell(row=3, column=col, value=header)
            cell.font = Font(bold=True)
            cell.fill = PatternFill(start_color="D9E1F2", end_color="D9E1F2", fill_type="solid")
            cell.alignment = Alignment(horizontal="center")
        
        # 填充数据
        row = 4
        total_unique_patients = 0
        total_success = 0
        
        for clinic_name, data in clinic_data.items():
            records = data['records']
            if not records:
                continue
                
            success_count = data['success_count']
            unsuccessful_count = data['failed_count']
            abandon_count = data['pending_count']
            unique_patient_count = data['unique_patient_count']  # 使用唯一患者数
            
            total_unique_patients += unique_patient_count
            total_success += success_count
            
            # 计算成功率（基于唯一患者数）
            success_rate = (success_count / unique_patient_count) * 100 if unique_patient_count > 0 else 0
            
            ws.cell(row=row, column=1, value=clinic_name)
            ws.cell(row=row, column=2, value=unique_patient_count)  # 显示已回访患者数
            ws.cell(row=row, column=3, value=success_count)
            ws.cell(row=row, column=4, value=unsuccessful_count)
            ws.cell(row=row, column=5, value=abandon_count)
            ws.cell(row=row, column=6, value=f"{success_rate:.1f}%")
            
            row += 1
        
        # 添加总计行
        if total_unique_patients > 0:
            total_success_rate = (total_success / total_unique_patients) * 100
            ws.cell(row=row, column=1, value="总计")
            ws.cell(row=row, column=2, value=total_unique_patients)  # 显示总已回访患者数
            ws.cell(row=row, column=3, value=total_success)
            ws.cell(row=row, column=6, value=f"{total_success_rate:.1f}%")
            
            # 设置总计行样式
            for col in range(1, 7):
                cell = ws.cell(row=row, column=col)
                cell.font = Font(bold=True)
                cell.fill = PatternFill(start_color="FFE699", end_color="FFE699", fill_type="solid")
        
        # 调整列宽
        for col in range(1, 7):
            ws.column_dimensions[get_column_letter(col)].width = 15
        
        # 设置边框
        self._add_borders(ws, 3, row, 6)
    
    def _create_clinic_sheet(self, wb: Workbook, clinic_name: str, data: Dict[str, Any]):
        """创建诊所详细表"""
        sheet_name = clinic_name[:31] if len(clinic_name) > 31 else clinic_name  # Excel工作表名限制31字符
        
        ws = wb.create_sheet(sheet_name)
        
        # 设置标题
        title = f"{clinic_name} - 回访记录详情"
        ws['A1'] = title
        ws.merge_cells('A1:M1')
        
        # 设置标题样式
        title_font = Font(size=14, bold=True)
        title_fill = PatternFill(start_color="70AD47", end_color="70AD47", fill_type="solid")
        title_alignment = Alignment(horizontal="center", vertical="center")
        
        ws['A1'].font = title_font
        ws['A1'].fill = title_fill
        ws['A1'].alignment = title_alignment
        
        # 设置列标题
        headers = ["序号", "病例号", "回访方式", "回访结果", "操作员", "创建时间", "更新时间", "详细记录",
                  "下次预约时间", "不成功备注", "放弃回访备注", "AI反馈类型", "AI反馈备注"]
        for col, header in enumerate(headers, 1):
            cell = ws.cell(row=3, column=col, value=header)
            cell.font = Font(bold=True)
            cell.fill = PatternFill(start_color="C6EFCE", end_color="C6EFCE", fill_type="solid")
            cell.alignment = Alignment(horizontal="center")
        
        # 填充数据
        for row_idx, record in enumerate(data['records'], 4):
            ws.cell(row=row_idx, column=1, value=row_idx - 3)
            ws.cell(row=row_idx, column=2, value=record['case_number'])
            ws.cell(row=row_idx, column=3, value=', '.join(record['callback_methods']))
            ws.cell(row=row_idx, column=4, value=record['callback_result'])
            ws.cell(row=row_idx, column=5, value=record['operator'])
            ws.cell(row=row_idx, column=6, value=record['create_time'].strftime("%Y-%m-%d %H:%M:%S") if record['create_time'] else "")
            ws.cell(row=row_idx, column=7, value=record['update_time'].strftime("%Y-%m-%d %H:%M:%S") if record['update_time'] else "")
            ws.cell(row=row_idx, column=8, value=record['callback_record'])

            # 新增字段
            ws.cell(row=row_idx, column=9, value=record.get('next_appointment_time', '') or '')

            # 备注字段：根据回访结果显示相应的备注
            failure_note = record.get('failure_reason_note', '') or ''
            abandon_note = record.get('abandon_reason_note', '') or ''
            ws.cell(row=row_idx, column=10, value=failure_note)
            ws.cell(row=row_idx, column=11, value=abandon_note)

            # AI反馈：分别显示AI反馈类型和备注
            ai_feedback_type = record.get('ai_feedback_type', '') or ''
            ai_feedback_note = record.get('ai_feedback_note', '') or ''
            ws.cell(row=row_idx, column=12, value=ai_feedback_type)
            ws.cell(row=row_idx, column=13, value=ai_feedback_note)
            
            # 根据回访结果设置颜色
            if record['callback_result'] == '成功':
                fill_color = "C6EFCE"  # 绿色
            elif record['callback_result'] == '不成功':
                fill_color = "FFC7CE"  # 红色
            elif record['callback_result'] == '放弃回访':
                fill_color = "FFEB9C"  # 黄色
            else:
                fill_color = "FFFFFF"  # 白色
            
            for col in range(1, 14):  # 更新为13列
                ws.cell(row=row_idx, column=col).fill = PatternFill(start_color=fill_color, end_color=fill_color, fill_type="solid")

        # 调整列宽
        column_widths = [8, 15, 20, 12, 15, 20, 20, 50, 18, 25, 25, 25, 30]  # 新增5列的宽度
        for col, width in enumerate(column_widths, 1):
            ws.column_dimensions[get_column_letter(col)].width = width

        # 设置边框
        self._add_borders(ws, 3, len(data['records']) + 3, 13)  # 更新为13列
    
    def _add_borders(self, ws, start_row: int, end_row: int, end_col: int):
        """添加边框"""
        thin_border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        
        for row in range(start_row, end_row + 1):
            for col in range(1, end_col + 1):
                ws.cell(row=row, column=col).border = thin_border

def main():
    """主函数"""
    exporter = DataExporter()
    output_file = exporter.export_to_excel()
    print(f"数据导出完成！文件保存为: {output_file}")

if __name__ == "__main__":
    main() 