from __future__ import annotations

from ai_orchestrator.schemas.workflow_models import CriticResult, ValidationSummary


class CriticAgent:
    def review(
        self,
        *,
        goal: str,
        patch: str,
        file_writes: list[dict] | None,
        repo_context: dict,
        validation_result: ValidationSummary | None = None,
    ) -> CriticResult:
        issues: list[str] = []
        repair_guidance: list[str] = []
        seen_issues: set[str] = set()
        seen_guidance: set[str] = set()
        fix_oriented_goal = any(keyword in goal.lower() for keyword in ["fix", "repair", "resolve"])
        has_change_proposal = bool(patch.strip()) or bool(file_writes)

        if fix_oriented_goal and not has_change_proposal:
            issue = "No code change was generated for a fix-oriented task."
            issues.append(issue)
            seen_issues.add(issue)
            guidance = "Produce a concrete unified diff or a full-file rewrite before retrying."
            repair_guidance.append(guidance)
            seen_guidance.add(guidance)

        if validation_result is not None and not validation_result.valid:
            for failed_check in validation_result.failed_checks:
                issue = f"Validation failed for `{failed_check}`."
                if issue not in seen_issues:
                    issues.append(issue)
                    seen_issues.add(issue)
            for check in validation_result.checks:
                for structured_error in check.structured_errors:
                    detail = self._format_structured_error(check.name, structured_error)
                    if detail not in seen_issues:
                        issues.append(detail)
                        seen_issues.add(detail)
                    if structured_error.file:
                        guidance = (
                            "Resolve "
                            f"{structured_error.error_type} in {structured_error.file}"
                            + (f":{structured_error.line}" if structured_error.line else "")
                            + (f" ({structured_error.message})" if structured_error.message else "")
                        )
                        if guidance not in seen_guidance:
                            repair_guidance.append(guidance)
                            seen_guidance.add(guidance)

        important_files = repo_context.get("important_files", [])
        if not important_files:
            guidance = "Review the repository entry points and key modules before broad changes."
            if guidance not in seen_guidance:
                repair_guidance.append(guidance)

        result = "pass" if not issues else "fail"
        return CriticResult(result=result, issues=issues, repair_guidance=repair_guidance)

    @staticmethod
    def _format_structured_error(check_name, structured_error) -> str:
        location = structured_error.file or "unknown file"
        if structured_error.line:
            location = f"{location}:{structured_error.line}"
        detail = structured_error.message or structured_error.error_type
        return f"{check_name} {structured_error.error_type} at {location}: {detail}"
