<?php

namespace Kylin\Payment\Services;

use Illuminate\Support\Facades\DB;
use Kylin\Payment\Facades\Payment;
use Illuminate\Contracts\Container\Container;

/**
 * 支付报表服务类
 */
class ReportService
{
    /**
     * 构造函数
     */
    public function __construct(
        protected readonly Container $app
    ) {
    }

    /**
     * 生成支付报表数据
     */
    public function generateReportData(array $params = []): array
    {
        $startDate = $params['start_date'] ?? date('Y-m-d', strtotime('-30 days'));
        $endDate = $params['end_date'] ?? date('Y-m-d');
        $gateway = $params['gateway'] ?? '';
        $status = $params['status'] ?? '';

        // 构建查询
        $query = DB::table('payment_records')
            ->whereBetween('created_at', [$startDate . ' 00:00:00', $endDate . ' 23:59:59']);

        // 添加支付方式筛选
        if (!empty($gateway)) {
            $query->where('gateway', $gateway);
        }

        // 添加状态筛选
        if (!empty($status)) {
            $query->where('status', $status);
        }

        // 执行查询
        $records = $query->get();

        // 计算统计数据
        $stats = [
            'total_count' => $records->count(),
            'total_amount' => $records->sum('amount'),
            'success_count' => $records->where('status', 'success')->count(),
            'success_amount' => $records->where('status', 'success')->sum('amount'),
            'failed_count' => $records->where('status', 'failed')->count(),
            'failed_amount' => $records->where('status', 'failed')->sum('amount'),
            'refunded_count' => $records->where('status', 'refunded')->count(),
            'refunded_amount' => $records->where('status', 'refunded')->sum('amount'),
            'success_rate' => $records->count() > 0 ? round($records->where('status', 'success')->count() / $records->count() * 100, 2) : 0,
            'refund_rate' => $records->count() > 0 ? round($records->where('status', 'refunded')->count() / $records->count() * 100, 2) : 0,
        ];

        // 按支付方式统计
        $statsByGateway = $records->groupBy('gateway')->map(function ($group) {
            return [
                'gateway' => $group->first()->gateway,
                'count' => $group->count(),
                'amount' => $group->sum('amount'),
                'success_count' => $group->where('status', 'success')->count(),
                'success_amount' => $group->where('status', 'success')->sum('amount'),
                'success_rate' => $group->count() > 0 ? round($group->where('status', 'success')->count() / $group->count() * 100, 2) : 0,
            ];
        })->values()->toArray();

        // 按日期统计
        $statsByDate = $records->groupBy(fn ($item) => $item->created_at->format('Y-m-d'))->map(function ($group, $date) {
            return [
                'date' => $date,
                'count' => $group->count(),
                'amount' => $group->sum('amount'),
                'success_count' => $group->where('status', 'success')->count(),
                'success_amount' => $group->where('status', 'success')->sum('amount'),
            ];
        })->values()->toArray();

        return [
            'params' => $params,
            'stats' => $stats,
            'statsByGateway' => $statsByGateway,
            'statsByDate' => $statsByDate,
            'records' => $records,
        ];
    }

    /**
     * 导出Excel报表
     */
    public function exportExcel(array $params = []): string
    {
        // 生成报表数据
        $reportData = $this->generateReportData($params);

        // 检查是否安装了PHPExcel或PhpSpreadsheet
        if (class_exists('PhpOffice\PhpSpreadsheet\Spreadsheet')) {
            return $this->exportWithPhpSpreadsheet($reportData);
        } elseif (class_exists('PHPExcel')) {
            return $this->exportWithPHPExcel($reportData);
        } else {
            throw new \Exception('Please install PhpSpreadsheet or PHPExcel library');
        }
    }

    /**
     * 使用PhpSpreadsheet导出Excel
     */
    protected function exportWithPhpSpreadsheet(array $reportData): string
    {
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // 设置表头
        $sheet->setCellValue('A1', '支付报表');
        $sheet->mergeCells('A1:F1');
        $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);

        // 设置统计信息
        $sheet->setCellValue('A3', '统计周期:');
        $sheet->setCellValue('B3', $reportData['params']['start_date'] . ' 至 ' . $reportData['params']['end_date']);
        $sheet->setCellValue('A4', '总订单数:');
        $sheet->setCellValue('B4', $reportData['stats']['total_count']);
        $sheet->setCellValue('A5', '总金额:');
        $sheet->setCellValue('B5', $reportData['stats']['total_amount']);
        $sheet->setCellValue('C4', '成功订单数:');
        $sheet->setCellValue('D4', $reportData['stats']['success_count']);
        $sheet->setCellValue('C5', '成功金额:');
        $sheet->setCellValue('D5', $reportData['stats']['success_amount']);
        $sheet->setCellValue('E4', '成功率:');
        $sheet->setCellValue('F4', $reportData['stats']['success_rate'] . '%');
        $sheet->setCellValue('E5', '退款率:');
        $sheet->setCellValue('F5', $reportData['stats']['refund_rate'] . '%');

        // 设置支付记录表头
        $sheet->setCellValue('A7', '订单号');
        $sheet->setCellValue('B7', '支付方式');
        $sheet->setCellValue('C7', '金额');
        $sheet->setCellValue('D7', '状态');
        $sheet->setCellValue('E7', '支付时间');
        $sheet->setCellValue('F7', '支付网关订单号');

        // 设置表头样式
        $sheet->getStyle('A7:F7')->getFont()->setBold(true);
        $sheet->getStyle('A7:F7')->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('DDDDDD');

        // 填充支付记录数据
        $row = 8;
        foreach ($reportData['records'] as $record) {
            $sheet->setCellValue('A' . $row, $record->out_trade_no);
            $sheet->setCellValue('B' . $row, $record->gateway);
            $sheet->setCellValue('C' . $row, $record->amount);
            $sheet->setCellValue('D' . $row, $record->status);
            $sheet->setCellValue('E' . $row, $record->created_at);
            $sheet->setCellValue('F' . $row, $record->gateway_trade_no ?? '');
            $row++;
        }

        // 自动调整列宽
        foreach (range('A', 'F') as $column) {
            $sheet->getColumnDimension($column)->setAutoSize(true);
        }

        // 生成Excel文件
        $filename = 'payment_report_' . date('YmdHis') . '.xlsx';
        $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
        $writer->save(storage_path('app/' . $filename));

        return $filename;
    }

    /**
     * 使用PHPExcel导出Excel
     */
    protected function exportWithPHPExcel(array $reportData): string
    {
        $objPHPExcel = new \PHPExcel();
        $sheet = $objPHPExcel->getActiveSheet();

        // 设置表头
        $sheet->setCellValue('A1', '支付报表');
        $sheet->mergeCells('A1:F1');
        $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);

        // 设置统计信息
        $sheet->setCellValue('A3', '统计周期:');
        $sheet->setCellValue('B3', $reportData['params']['start_date'] . ' 至 ' . $reportData['params']['end_date']);
        $sheet->setCellValue('A4', '总订单数:');
        $sheet->setCellValue('B4', $reportData['stats']['total_count']);
        $sheet->setCellValue('A5', '总金额:');
        $sheet->setCellValue('B5', $reportData['stats']['total_amount']);
        $sheet->setCellValue('C4', '成功订单数:');
        $sheet->setCellValue('D4', $reportData['stats']['success_count']);
        $sheet->setCellValue('C5', '成功金额:');
        $sheet->setCellValue('D5', $reportData['stats']['success_amount']);
        $sheet->setCellValue('E4', '成功率:');
        $sheet->setCellValue('F4', $reportData['stats']['success_rate'] . '%');
        $sheet->setCellValue('E5', '退款率:');
        $sheet->setCellValue('F5', $reportData['stats']['refund_rate'] . '%');

        // 设置支付记录表头
        $sheet->setCellValue('A7', '订单号');
        $sheet->setCellValue('B7', '支付方式');
        $sheet->setCellValue('C7', '金额');
        $sheet->setCellValue('D7', '状态');
        $sheet->setCellValue('E7', '支付时间');
        $sheet->setCellValue('F7', '支付网关订单号');

        // 设置表头样式
        $sheet->getStyle('A7:F7')->getFont()->setBold(true);
        $sheet->getStyle('A7:F7')->getFill()->setFillType(\PHPExcel_Style_Fill::FILL_SOLID)->getStartColor()->setARGB('DDDDDD');

        // 填充支付记录数据
        $row = 8;
        foreach ($reportData['records'] as $record) {
            $sheet->setCellValue('A' . $row, $record->out_trade_no);
            $sheet->setCellValue('B' . $row, $record->gateway);
            $sheet->setCellValue('C' . $row, $record->amount);
            $sheet->setCellValue('D' . $row, $record->status);
            $sheet->setCellValue('E' . $row, $record->created_at);
            $sheet->setCellValue('F' . $row, $record->gateway_trade_no ?? '');
            $row++;
        }

        // 自动调整列宽
        foreach (range('A', 'F') as $column) {
            $sheet->getColumnDimension($column)->setAutoSize(true);
        }

        // 生成Excel文件
        $filename = 'payment_report_' . date('YmdHis') . '.xlsx';
        $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
        $objWriter->save(storage_path('app/' . $filename));

        return $filename;
    }

    /**
     * 导出PDF报表
     */
    public function exportPdf(array $params = []): string
    {
        // 生成报表数据
        $reportData = $this->generateReportData($params);

        // 检查是否安装了TCPDF或mPDF
        if (class_exists('TCPDF')) {
            return $this->exportWithTCPDF($reportData);
        } elseif (class_exists('mPDF')) {
            return $this->exportWithMPDF($reportData);
        } else {
            throw new \Exception('Please install TCPDF or mPDF library');
        }
    }

    /**
     * 使用TCPDF导出PDF
     */
    protected function exportWithTCPDF(array $reportData): string
    {
        $pdf = new \TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
        $pdf->SetCreator(PDF_CREATOR);
        $pdf->SetAuthor('Kylin Payment');
        $pdf->SetTitle('支付报表');
        $pdf->SetSubject('支付报表');
        $pdf->SetKeywords('支付,报表,Excel,PDF');

        // 设置默认字体
        $pdf->SetFont('dejavusans', '', 10);

        // 添加页面
        $pdf->AddPage();

        // 生成HTML内容
        $html = $this->generatePdfHtml($reportData);

        // 输出HTML内容
        $pdf->writeHTML($html, true, false, true, false, '');

        // 生成PDF文件
        $filename = 'payment_report_' . date('YmdHis') . '.pdf';
        $pdf->Output(storage_path('app/' . $filename), 'F');

        return $filename;
    }

    /**
     * 使用mPDF导出PDF
     */
    protected function exportWithMPDF(array $reportData): string
    {
        $mpdf = new \mPDF();
        $mpdf->SetTitle('支付报表');
        $mpdf->SetAuthor('Kylin Payment');

        // 生成HTML内容
        $html = $this->generatePdfHtml($reportData);

        // 输出HTML内容
        $mpdf->WriteHTML($html);

        // 生成PDF文件
        $filename = 'payment_report_' . date('YmdHis') . '.pdf';
        $mpdf->Output(storage_path('app/' . $filename), 'F');

        return $filename;
    }

    /**
     * 生成PDF的HTML内容
     */
    protected function generatePdfHtml(array $reportData): string
    {
        $html = '<h1 align="center">支付报表</h1>';
        $html .= '<p>统计周期: ' . $reportData['params']['start_date'] . ' 至 ' . $reportData['params']['end_date'] . '</p>';

        // 添加统计信息表格
        $html .= '<table border="1" cellpadding="5" cellspacing="0">';
        $html .= '<tr><th colspan="2">统计信息</th></tr>';
        $html .= '<tr><td>总订单数:</td><td>' . $reportData['stats']['total_count'] . '</td></tr>';
        $html .= '<tr><td>总金额:</td><td>' . $reportData['stats']['total_amount'] . '</td></tr>';
        $html .= '<tr><td>成功订单数:</td><td>' . $reportData['stats']['success_count'] . '</td></tr>';
        $html .= '<tr><td>成功金额:</td><td>' . $reportData['stats']['success_amount'] . '</td></tr>';
        $html .= '<tr><td>成功率:</td><td>' . $reportData['stats']['success_rate'] . '%</td></tr>';
        $html .= '<tr><td>退款率:</td><td>' . $reportData['stats']['refund_rate'] . '%</td></tr>';
        $html .= '</table>';

        // 添加支付记录表格
        $html .= '<h2>支付记录</h2>';
        $html .= '<table border="1" cellpadding="5" cellspacing="0">';
        $html .= '<tr><th>订单号</th><th>支付方式</th><th>金额</th><th>状态</th><th>支付时间</th><th>支付网关订单号</th></tr>';

        foreach ($reportData['records'] as $record) {
            $html .= '<tr>';
            $html .= '<td>' . $record->out_trade_no . '</td>';
            $html .= '<td>' . $record->gateway . '</td>';
            $html .= '<td>' . $record->amount . '</td>';
            $html .= '<td>' . $record->status . '</td>';
            $html .= '<td>' . $record->created_at . '</td>';
            $html .= '<td>' . ($record->gateway_trade_no ?? '') . '</td>';
            $html .= '</tr>';
        }

        $html .= '</table>';

        return $html;
    }

    /**
     * 导出CSV报表
     */
    public function exportCsv(array $params = []): string
    {
        // 生成报表数据
        $reportData = $this->generateReportData($params);

        // 生成CSV文件
        $filename = 'payment_report_' . date('YmdHis') . '.csv';
        $filePath = storage_path('app/' . $filename);

        $handle = fopen($filePath, 'w');

        // 写入BOM以支持中文
        fwrite($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));

        // 写入表头
        fputcsv($handle, ['订单号', '支付方式', '金额', '状态', '支付时间', '支付网关订单号']);

        // 写入数据
        foreach ($reportData['records'] as $record) {
            fputcsv($handle, [
                $record->out_trade_no,
                $record->gateway,
                $record->amount,
                $record->status,
                $record->created_at,
                $record->gateway_trade_no ?? '',
            ]);
        }

        fclose($handle);

        return $filename;
    }
}
