"""BugReporter — create Jira sub-task bugs when tests fail.

Creates a Bug sub-task under the original ticket with:
  - Failure details (step, expected vs actual)
  - Screenshot attachment
  - Structured labels for filtering
"""

from __future__ import annotations

import logging
from pathlib import Path
from textwrap import dedent
from typing import Any

from antiqa.jira.agent import JiraAgent

log = logging.getLogger("antiqa.jira")


class BugReporter:
    """Automatically files bug sub-tasks for test failures."""

    LABELS = ["antiqa-bug", "automated-testing"]

    def __init__(self, jira_agent: JiraAgent) -> None:
        self.agent = jira_agent

    def report_failure(
        self,
        parent_key: str,
        test_case_title: str,
        failure_summary: str,
        failed_step: str,
        expected: str,
        actual: str,
        screenshot_path: str | Path | None = None,
        priority: str = "Medium",
        extra_context: str = "",
    ) -> dict[str, Any]:
        """Create a bug sub-task under *parent_key* for a test failure.

        Returns the created issue dict (key, url) or an error dict.
        """
        summary = f"[AntiQA Bug] {test_case_title} - {failure_summary}"
        description = self._build_description(
            test_case_title=test_case_title,
            failed_step=failed_step,
            expected=expected,
            actual=actual,
            extra_context=extra_context,
        )

        result = self.agent.create_issue(
            summary=summary,
            description=description,
            issuetype="Bug",
            parent_key=parent_key,
            labels=self.LABELS,
            priority=priority,
        )

        if "error" in result:
            log.error("Bug creation failed: %s", result["error"])
            return result

        bug_key = result["key"]

        if screenshot_path:
            self.agent.attach_file(
                issue_key=bug_key,
                file_path=str(screenshot_path),
                filename=f"failure_{bug_key}.png",
            )

        # Also comment on the parent ticket about the bug
        self.agent.add_comment(
            parent_key,
            f"AntiQA detected a failure in *{test_case_title}*.\n"
            f"Bug filed: [{bug_key}|{result.get('url', '')}]\n"
            f"Summary: {failure_summary}",
        )

        log.info("Bug %s filed under %s", bug_key, parent_key)
        return result

    def report_flow_result(
        self,
        parent_key: str,
        flow_name: str,
        flow_result: Any,
    ) -> list[dict[str, Any]]:
        """File bug tickets for each failed step in a FlowResult."""
        from antiqa.flows.runner import FlowResult

        if not isinstance(flow_result, FlowResult):
            raise TypeError(f"Expected FlowResult, got {type(flow_result)}")

        bugs: list[dict[str, Any]] = []

        for step in flow_result.failed_steps:
            ar = step.action_result
            screenshot_path = Path(ar.screenshot_path) if ar.screenshot_path else None
            if screenshot_path and not screenshot_path.exists():
                screenshot_path = None

            bug = self.report_failure(
                parent_key=parent_key,
                test_case_title=f"{flow_name} / Step {step.step_number}",
                failure_summary=ar.error or "Step failed",
                failed_step=f"[{step.action}] {step.description}",
                expected="Step should succeed",
                actual=ar.error or "Unknown failure",
                screenshot_path=screenshot_path,
            )
            bugs.append(bug)

        return bugs

    def report_health_issues(
        self,
        parent_key: str,
        flow_name: str,
        health_issues: list,
    ) -> list[dict[str, Any]]:
        """File Jira bug sub-tasks for critical runtime health issues.

        Groups related issues (e.g. multiple console errors) into a single bug
        and attaches all relevant screenshots.
        """
        from antiqa.browser.health import HealthIssue, IssueCategory, IssueSeverity

        critical = [i for i in health_issues if i.severity == IssueSeverity.CRITICAL]
        if not critical:
            return []

        # Group issues by category for cleaner bug reports
        by_category: dict[str, list[HealthIssue]] = {}
        for issue in critical:
            cat = issue.category.value
            by_category.setdefault(cat, []).append(issue)

        bugs: list[dict[str, Any]] = []
        category_labels = {
            "console_error": "Console Errors",
            "js_exception": "JS Exceptions",
            "api_failure": "API Failures",
            "network_error": "Network Errors",
            "page_crash": "Page Crash",
            "security": "Security Issues",
        }

        for cat_key, issues in by_category.items():
            cat_label = category_labels.get(cat_key, cat_key)
            summary = f"[AntiQA Health] {flow_name} — {len(issues)} {cat_label}"

            # Build description with all issues in the category
            desc_lines = [
                f"h3. Runtime Health Issues — AntiQA\n",
                f"*Flow:* {flow_name}",
                f"*Category:* {cat_label}",
                f"*Count:* {len(issues)}\n",
                "h4. Issues Detected:\n",
            ]
            for idx, issue in enumerate(issues, 1):
                desc_lines.append(f"# *{issue.message}*")
                if issue.url:
                    desc_lines.append(f"   URL: {issue.url}")
                if issue.details:
                    desc_lines.append(f"   Details: {issue.details}")

            desc_lines.append(
                "\n----\n_This bug was automatically filed by [AntiQA|https://github.com/antiqa]._"
            )
            description = "\n".join(desc_lines)

            result = self.agent.create_issue(
                summary=summary,
                description=description,
                issuetype="Bug",
                parent_key=parent_key,
                labels=self.LABELS + [f"antiqa-{cat_key}"],
                priority="High" if cat_key in ("js_exception", "page_crash", "security") else "Medium",
            )

            if "error" in result:
                log.error("Health bug creation failed: %s", result["error"])
                bugs.append(result)
                continue

            bug_key = result["key"]

            # Attach all screenshots from this category's issues
            attached = set()
            for issue in issues:
                if issue.screenshot_path and issue.screenshot_path not in attached:
                    sp = Path(issue.screenshot_path)
                    if sp.exists():
                        self.agent.attach_file(
                            issue_key=bug_key,
                            file_path=str(sp),
                            filename=f"health_{bug_key}_{sp.name}",
                        )
                        attached.add(issue.screenshot_path)

            # Comment on parent ticket
            screenshot_note = f" ({len(attached)} screenshot(s) attached)" if attached else ""
            self.agent.add_comment(
                parent_key,
                f"AntiQA detected *{len(issues)} {cat_label.lower()}* during _{flow_name}_{screenshot_note}.\n"
                f"Bug filed: [{bug_key}|{result.get('url', '')}]",
            )

            log.info("Health bug %s filed under %s (%d %s)", bug_key, parent_key, len(issues), cat_label)
            bugs.append(result)

        return bugs

    @staticmethod
    def _build_description(
        test_case_title: str,
        failed_step: str,
        expected: str,
        actual: str,
        extra_context: str,
        probable_fix: str = "",
        user_impact: str = "",
        regression_test: str = "",
    ) -> str:
        desc = dedent(f"""\
            h3. Automated Bug Report — AntiQA

            *Test Case:* {test_case_title}

            *Failed Step:* {failed_step}

            *Expected:* {expected}

            *Actual:* {actual}
        """)
        if extra_context:
            desc += f"\n*Additional Context:*\n{extra_context}\n"

        if probable_fix:
            desc += f"\nh4. Suggested Fix\n{probable_fix}\n"

        if user_impact:
            desc += f"\nh4. User Impact\n{user_impact}\n"

        if regression_test:
            desc += f"\nh4. Recommended Regression Test\n{regression_test}\n"

        desc += "\n----\n_This bug was automatically filed by [AntiQA|https://github.com/antiqa]._"
        return desc
