import json
from datetime import datetime
from pathlib import Path
from typing import Optional
import structlog

logger = structlog.get_logger()


class ReportGenerator:
    """生成结构化的工程报告"""

    def __init__(self, output_dir: str = "./reports"):
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)

    def generate_engineering_report(self, state: dict) -> str:
        """生成完整的工程任务报告"""
        task_id = state.get("task_id", "unknown")
        now = datetime.utcnow().strftime("%Y-%m-%d %Human:%M:%S UTC")

        sections = [
            self._header(task_id, now),
            self._user_request_section(state),
            self._architecture_section(state),
            self._implementation_section(state),
            self._test_section(state),
            self._review_section(state),
            self._diff_section(state),
            self._footer(state),
        ]

        report = "\n\n".join(s for s in sections if s)
        self._save_report(task_id, report)
        return report

    def generate_pr_description(self, state: dict) -> str:
        """生成 PR 描述文档"""
        diff = state.get("diff_result", {})
        review = state.get("review_result", {})
        tests = state.get("test_result", {})

        lines = [
            f"## Summary\n{state.get('user_request', '')}",
            "",
            "## Changes",
        ]

        if diff.get("modified"):
            lines.append("**Modified files:**")
            for f in diff["modified"]:
                lines.append(f"- `{f}`")

        if diff.get("added"):
            lines.append("\n**Added files:**")
            for f in diff["added"]:
                lines.append(f"- `{f}`")

        if diff.get("deleted"):
            lines.append("\n**Deleted files:**")
            for f in diff["deleted"]:
                lines.append(f"- `{f}`")

        dl = diff.get("diff_lines", {})
        if dl:
            lines.append(f"\n**+{dl.get('added', 0)} insertions, -{dl.get('removed', 0)} deletions**")

        # Tests
        lines += [
            "",
            "## Tests",
            f"- Passed: {tests.get('passed', 'N/A')}",
            f"- Failed: {tests.get('failed', 'N/A')}",
            f"- Coverage: {tests.get('coverage', 'N/A')}",
        ]

        # Review
        if review.get("bugs"):
            lines += ["", "## Issues Found (addressed)", *[f"- {b}" for b in review["bugs"]]]

        lines += ["", "---", "_Generated by AI Engineering Employee Platform V2_"]
        return "\n".join(lines)

    def _header(self, task_id: str, timestamp: str) -> str:
        return f"""# AI Engineering Report
**Task ID:** `{task_id}`
**Generated:** {timestamp}
**Status:** Completed
"""

    def _user_request_section(self, state: dict) -> str:
        return f"""## User Request
{state.get('user_request', 'N/A')}
"""

    def _architecture_section(self, state: dict) -> str:
        arch = state.get("architecture_plan", {})
        if not arch:
            return ""
        return f"""## Architecture Plan
```json
{json.dumps(arch, indent=2, ensure_ascii=False)}
```
"""

    def _implementation_section(self, state: dict) -> str:
        code = state.get("code_result", {})
        if not code:
            return ""
        lines = ["## Implementation"]
        if code.get("files_changed"):
            lines.append("\n**Files Changed:**")
            for f in code["files_changed"]:
                lines.append(f"- `{f}`")
        if code.get("output"):
            lines.append(f"\n**Output:**\n```\n{code['output'][:2000]}\n```")
        return "\n".join(lines)

    def _test_section(self, state: dict) -> str:
        tests = state.get("test_result", {})
        if not tests:
            return ""
        lines = [
            "## Test Results",
            f"- ✅ Passed: {tests.get('passed', 'N/A')}",
            f"- ❌ Failed: {tests.get('failed', 'N/A')}",
            f"- 📊 Coverage: {tests.get('coverage', 'N/A')}",
        ]
        if tests.get("output"):
            lines.append(f"\n**Output:**\n```\n{tests['output'][:1500]}\n```")
        return "\n".join(lines)

    def _review_section(self, state: dict) -> str:
        review = state.get("review_result", {})
        if not review:
            return ""
        lines = ["## Code Review"]
        for category in ("bugs", "security", "performance", "suggestions"):
            items = review.get(category, [])
            if items:
                lines.append(f"\n### {category.capitalize()}")
                for item in items:
                    lines.append(f"- {item}")
        return "\n".join(lines)

    def _diff_section(self, state: dict) -> str:
        diff = state.get("diff_result", {})
        if not diff:
            return ""
        dl = diff.get("diff_lines", {})
        lines = [
            "## Git Diff Summary",
            f"- Modified: {len(diff.get('modified', []))} files",
            f"- Added: {len(diff.get('added', []))} files",
            f"- Deleted: {len(diff.get('deleted', []))} files",
            f"- Lines: +{dl.get('added', 0)} / -{dl.get('removed', 0)}",
        ]
        return "\n".join(lines)

    def _footer(self, state: dict) -> str:
        return f"""---
_AI Engineering Employee Platform V2 | Executor: {state.get('selected_executor', 'N/A')} | Attempts: {state.get('attempts', 0)}_"""

    def _save_report(self, task_id: str, content: str):
        path = self.output_dir / f"report_{task_id[:8]}.md"
        path.write_text(content, encoding="utf-8")
        logger.info("Report saved", path=str(path))
