"""HTML 测试报告生成器"""

import json
from datetime import datetime
from pathlib import Path
from typing import List, Optional

from ...cases.case_executor import CaseResult, StepResult
from ...reference import INFO


class HtmlReporter:
    """HTML 测试报告生成器"""

    def __init__(self, report_dir: str = 'result/report'):
        """初始化报告生成器

        Args:
            report_dir: 报告输出目录
        """
        self._report_dir = Path(report_dir)
        self._report_dir.mkdir(parents=True, exist_ok=True)

    def generate(
        self,
        results: List[CaseResult],
        title: str = 'KDTest 测试报告',
        output_file: Optional[str] = None
    ) -> str:
        """生成 HTML 报告

        Args:
            results: 测试结果列表
            title: 报告标题
            output_file: 输出文件名

        Returns:
            str: 报告文件路径
        """
        # 生成文件名
        if not output_file:
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            output_file = f'report_{timestamp}.html'

        report_path = self._report_dir / output_file

        # 统计数据
        total = len(results)
        passed = sum(1 for r in results if r.is_passed)
        failed = sum(1 for r in results if r.is_failed)
        skipped = total - passed - failed
        duration = sum(r.duration for r in results)
        pass_rate = (passed / total * 100) if total > 0 else 0

        # 生成 HTML
        html = self._generate_html(
            title=title,
            results=results,
            total=total,
            passed=passed,
            failed=failed,
            skipped=skipped,
            duration=duration,
            pass_rate=pass_rate,
        )

        # 写入文件
        with open(report_path, 'w', encoding='utf-8') as f:
            f.write(html)

        INFO(f"报告已生成: {report_path}")
        return str(report_path)

    def _generate_html(
        self,
        title: str,
        results: List[CaseResult],
        total: int,
        passed: int,
        failed: int,
        skipped: int,
        duration: float,
        pass_rate: float,
    ) -> str:
        """生成 HTML 内容"""
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        # 生成用例行
        case_rows = []
        for i, result in enumerate(results, 1):
            status_class = 'passed' if result.is_passed else 'failed'
            status_text = '通过' if result.is_passed else '失败'

            steps_html = self._generate_steps_html(result.step_results)

            case_rows.append(f'''
            <tr class="case-row {status_class}" onclick="toggleSteps(this)">
                <td>{i}</td>
                <td>{result.case.id}</td>
                <td>{result.case.name}</td>
                <td>{result.case.sheet}</td>
                <td class="status-{status_class}">{status_text}</td>
                <td>{result.duration:.2f}s</td>
            </tr>
            <tr class="steps-row" style="display: none;">
                <td colspan="6">
                    <table class="steps-table">
                        <thead>
                            <tr>
                                <th>步骤</th>
                                <th>关键字</th>
                                <th>描述</th>
                                <th>状态</th>
                                <th>耗时</th>
                                <th>错误</th>
                            </tr>
                        </thead>
                        <tbody>
                            {steps_html}
                        </tbody>
                    </table>
                </td>
            </tr>
            ''')

        cases_html = '\n'.join(case_rows)

        return f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{title}</title>
    <style>
        * {{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }}
        body {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background-color: #f5f7fa;
            color: #333;
            line-height: 1.6;
        }}
        .container {{
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
        }}
        .header {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            border-radius: 10px;
            margin-bottom: 20px;
        }}
        .header h1 {{
            font-size: 28px;
            margin-bottom: 10px;
        }}
        .header .timestamp {{
            opacity: 0.8;
        }}
        .summary {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 20px;
        }}
        .summary-card {{
            background: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            text-align: center;
        }}
        .summary-card .value {{
            font-size: 36px;
            font-weight: bold;
            margin-bottom: 5px;
        }}
        .summary-card .label {{
            color: #666;
        }}
        .summary-card.total .value {{ color: #409eff; }}
        .summary-card.passed .value {{ color: #67c23a; }}
        .summary-card.failed .value {{ color: #f56c6c; }}
        .summary-card.rate .value {{ color: #e6a23c; }}
        .results {{
            background: white;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            overflow: hidden;
        }}
        .results h2 {{
            padding: 20px;
            border-bottom: 1px solid #eee;
        }}
        table {{
            width: 100%;
            border-collapse: collapse;
        }}
        th, td {{
            padding: 12px 15px;
            text-align: left;
            border-bottom: 1px solid #eee;
        }}
        th {{
            background: #f8f9fa;
            font-weight: 600;
        }}
        .case-row {{
            cursor: pointer;
            transition: background-color 0.2s;
        }}
        .case-row:hover {{
            background-color: #f5f7fa;
        }}
        .status-passed {{
            color: #67c23a;
            font-weight: 600;
        }}
        .status-failed {{
            color: #f56c6c;
            font-weight: 600;
        }}
        .steps-table {{
            margin: 10px;
            background: #fafafa;
        }}
        .steps-table th {{
            background: #f0f0f0;
        }}
        .error-text {{
            color: #f56c6c;
            font-size: 12px;
            max-width: 300px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }}
        .footer {{
            text-align: center;
            padding: 20px;
            color: #999;
        }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>{title}</h1>
            <div class="timestamp">生成时间: {timestamp}</div>
        </div>

        <div class="summary">
            <div class="summary-card total">
                <div class="value">{total}</div>
                <div class="label">总用例数</div>
            </div>
            <div class="summary-card passed">
                <div class="value">{passed}</div>
                <div class="label">通过</div>
            </div>
            <div class="summary-card failed">
                <div class="value">{failed}</div>
                <div class="label">失败</div>
            </div>
            <div class="summary-card rate">
                <div class="value">{pass_rate:.1f}%</div>
                <div class="label">通过率</div>
            </div>
            <div class="summary-card">
                <div class="value">{duration:.1f}s</div>
                <div class="label">总耗时</div>
            </div>
        </div>

        <div class="results">
            <h2>测试用例详情</h2>
            <table>
                <thead>
                    <tr>
                        <th>#</th>
                        <th>用例ID</th>
                        <th>用例名称</th>
                        <th>Sheet</th>
                        <th>状态</th>
                        <th>耗时</th>
                    </tr>
                </thead>
                <tbody>
                    {cases_html}
                </tbody>
            </table>
        </div>

        <div class="footer">
            Powered by KDTest-Playwright v2.0.0
        </div>
    </div>

    <script>
        function toggleSteps(row) {{
            const stepsRow = row.nextElementSibling;
            if (stepsRow.style.display === 'none') {{
                stepsRow.style.display = 'table-row';
            }} else {{
                stepsRow.style.display = 'none';
            }}
        }}
    </script>
</body>
</html>'''

    def _generate_steps_html(self, step_results: List[StepResult]) -> str:
        """生成步骤 HTML"""
        rows = []
        for i, step_result in enumerate(step_results, 1):
            status_class = 'passed' if step_result.is_passed else 'failed'
            status_text = '通过' if step_result.is_passed else '失败'
            error_text = step_result.error or ''

            rows.append(f'''
            <tr>
                <td>{i}</td>
                <td>{step_result.step.keyword}</td>
                <td>{step_result.step.description or '-'}</td>
                <td class="status-{status_class}">{status_text}</td>
                <td>{step_result.duration:.2f}s</td>
                <td class="error-text" title="{error_text}">{error_text[:50]}</td>
            </tr>
            ''')

        return '\n'.join(rows)
