from typing import Optional

from app.models.schemas import SubReview, RagStatus, OverallStatus
from app.services.gemini_service import GeminiService


class LeadAgent:
    """
    Lead Agent - synthesizes specialist agent reviews into a final summary.

    Applies the decision logic:
    - Financial promotion detected → Requires Manual Legal Review
    - Any Error status → Analysis Error
    - Any Red status → Failed
    - Otherwise → Passed
    """

    name = "Lead Agent"

    def __init__(self, gemini_service: GeminiService):
        """
        Initialize the Lead Agent.

        Args:
            gemini_service: Service for making Gemini API calls (for summary generation)
        """
        self.gemini = gemini_service

    def _build_revision_context(self, previous_analysis: dict, reviews: dict[str, SubReview]) -> str:
        """Build revision context section for the synthesis prompt."""
        previous_version = previous_analysis.get("version", "N/A")

        # Aggregate resolved/outstanding/new issues across all agents
        all_resolved = []
        all_outstanding = []
        all_new = []

        for agent_name, review in reviews.items():
            if review.resolvedIssues:
                all_resolved.extend([f"[{agent_name}] {issue}" for issue in review.resolvedIssues])
            if review.outstandingIssues:
                all_outstanding.extend([f"[{agent_name}] {issue}" for issue in review.outstandingIssues])
            if review.newIssues:
                all_new.extend([f"[{agent_name}] {issue}" for issue in review.newIssues])

        resolved_list = "\n".join(f"  - {issue}" for issue in all_resolved) if all_resolved else "  (None)"
        outstanding_list = "\n".join(f"  - {issue}" for issue in all_outstanding) if all_outstanding else "  (None)"
        new_list = "\n".join(f"  - {issue}" for issue in all_new) if all_new else "  (None)"

        return f"""
---

**REVISION CONTEXT**

This is a revision (comparing against Version {previous_version}). The analysis has identified the following changes:

**RESOLVED ISSUES** (fixed in this revision):
{resolved_list}

**OUTSTANDING ISSUES** (still need attention):
{outstanding_list}

**NEW ISSUES** (introduced in this revision):
{new_list}

In your summary:
1. Acknowledge this is a revision and summarize the progress made
2. Highlight any resolved issues positively
3. Emphasize outstanding issues that still need to be addressed
4. Call out any regressions (new issues) that were introduced

---
"""

    async def synthesize(
        self,
        reviews: dict[str, SubReview],
        previous_analysis: Optional[dict] = None,
        channel: Optional[str] = None,
        sub_channel: Optional[str] = None,
        proof_type: Optional[str] = None,
        on_fallback=None,
    ) -> tuple[OverallStatus, str, str | None]:
        """
        Synthesize specialist reviews into final status and summary.

        Args:
            reviews: Dictionary mapping agent names to their SubReview results
            previous_analysis: Optional dict containing the previous version's analysis
                             results. When provided, enables revision-aware summary.
            channel: Target channel (e.g. "Social", "Digital")
            sub_channel: Target sub-channel (e.g. "Meta", "Google")
            proof_type: Proof format type (e.g. "In-feed 1x1", "Banner")

        Returns:
            Tuple of (overall_status, summary, financial_promotion_reason)
        """
        legal_review = reviews.get("Risk & Control Agent")

        # Check for financial promotion (from Legal Agent)
        is_financial_promotion = (
            legal_review is not None
            and legal_review.isFinancialPromotion is True
        )
        financial_promotion_reason = (
            legal_review.financialPromotionReason
            if legal_review and legal_review.financialPromotionReason
            else None
        )

        # Build revision context if previous analysis is available
        revision_context = ""
        if previous_analysis and previous_analysis.get("version"):
            revision_context = self._build_revision_context(previous_analysis, reviews)

        # Build proof metadata context
        metadata_context = f"""
**PROOF METADATA**
- Channel: {channel or "Not specified"}
- Sub-Channel: {sub_channel or "Not specified"}
- Proof Type: {proof_type or "Not specified"}
"""

        # Build the prompt for Gemini to generate summary
        prompt = f"""
You are a Lead Agent responsible for auditing a marketing proof. You have received feedback from specialist AI agents.
Your task is to determine the final status and write a concise, professional summary to the user.

{metadata_context}

Here is the logic you must follow:
1. The Risk & Control Agent has determined if this is a financial promotion: {is_financial_promotion}.
2. If it IS a financial promotion, the final verdict MUST be 'Requires Manual Legal Review'. Your summary should state this clearly, explain that a separate manual legal review is required, and then summarize any other issues found by the other agents.
3. If it is NOT a financial promotion, follow the standard logic:
    a. If ANY specialist agent reports a 'ragStatus' of 'Error', the final verdict MUST be 'Analysis Error'.
    b. If ANY specialist agent reports a 'Red' status (and there are no 'Error' statuses), the final verdict MUST be 'Failed'.
    c. If there are NO 'Red' or 'Error' statuses, the final verdict is 'Passed'.

Your summary should:
- For a 'Requires Manual Legal Review' verdict, start by stating this. Then, consolidate feedback from all agents, highlighting critical issues ('Red' items) or suggestions ('Amber' items).
- For an 'Analysis Error' verdict, explain that the proof could not be reliably processed and has been logged for human review. Advise the user to try again with a revised proof.
- For a 'Failed' status, highlight the critical 'Red' issues that must be addressed.
- For a 'Passed' status, mention any 'Amber' areas for consideration, if they exist, while maintaining an encouraging tone.

**Response Format:**
- IMPORTANT: The first line MUST follow this exact pattern based on the status:
  - For 'Failed': "This proof has failed due to [brief description of the critical issues]."
  - For 'Passed' (with amber items): "This proof has passed with minor considerations for [brief description]."
  - For 'Passed' (clean): "This proof has passed all checks."
  - For 'Analysis Error': "This proof could not be reliably processed."
  - For 'Requires Manual Legal Review': "This proof requires manual legal review."
- Do NOT prefix the opening line with "Verdict:", "Summary:", "Result:", or any other label.
- Follow the opening line with bullet points (max 3-5 bullets)
- Structure each bullet as two clearly labelled parts separated by a line break:
  **Issue:** [Clear description of what's wrong]
  **Recommendation:** [Actionable fix]
- Always capitalise "Issue:" and "Recommendation:" and bold them with double asterisks (**)
- Example:
  "• **Issue:** The logo is positioned in the top-left corner, which doesn't align with brand guidelines.
  **Recommendation:** Move the logo to the bottom-right corner."
- Do NOT include page numbers, document names, or source citations. Keep all feedback self-contained and actionable.
- For 'Passed': briefly note any amber items in 1-2 bullets
- IMPORTANT: Use British English spelling throughout all output (e.g. "authorised" not "authorized", "colour" not "color", "capitalise" not "capitalize", "organised" not "organized", "centre" not "center", "analysed" not "analyzed").
- IMPORTANT: Never use the words "violation", "violates", or "violated" in your output. Use constructive alternatives such as "issue", "doesn't align with", "doesn't meet", or "conflicts with".
- IMPORTANT: Use Plain English throughout. Choose simple, clear words over complex vocabulary. Prefer: "add" over "incorporate/integrate", "about" over "regarding", "qualifies as" over "constitutes", "use" over "utilise", "before" over "prior to", "to" over "in order to", "try" over "endeavour", "then" over "subsequently", "put in place" over "implement", "keep/contain" over "constrain", "standard interest rate" over "reversion rate". Avoid unnecessary jargon (e.g. use "exaggerated claim" instead of "puffery"). Feedback should be easy to understand for all users.
- IMPORTANT: Apply consistent punctuation and capitalisation throughout:
  (a) Always capitalise the first word after a full stop, including labels like "Recommendation:" and "Issue:".
  (b) End every bullet point with a full stop if it is a complete sentence. If bullets are short fragments, omit the full stop — but be consistent within the same output.
  (c) Write "e.g." with no comma after it (e.g. "Apply rotation" not "e.g., Apply rotation").
- IMPORTANT: When providing example corrections in recommendations, always show the example in the format you are recommending. If recommending sentence case, write the example in sentence case (e.g. "Apply now" not "Apply Now"). If quoting the user's original error, show it first, then the corrected version: "Change 'Apply Now' to 'Apply now' (sentence case)."
- IMPORTANT: Always spell out acronyms in full on first use, with the abbreviation in parentheses. Use the short form only for subsequent mentions within the same output. Common acronyms to expand include: WCAG (Web Content Accessibility Guidelines), FSCS (Financial Services Compensation Scheme), GDE (Global Digital Expression), APR (Annual Percentage Rate), CTA (Call-to-Action), FCA (Financial Conduct Authority), PRA (Prudential Regulation Authority), T&Cs (Terms and Conditions). Apply this rule to any acronym, not only those listed here.
{revision_context}
Here are the specialist reviews:
{self._format_reviews(reviews)}

Now, provide your final status and summary as a JSON object.
"""

        result = await self.gemini.generate_summary(prompt, on_fallback=on_fallback)

        overall_status = OverallStatus(result.get("overallStatus", "Analysis Error"))
        summary = result.get("summary", "Unable to generate summary.")

        # Override with financial promotion logic if applicable
        if is_financial_promotion:
            overall_status = OverallStatus.REQUIRES_MANUAL_LEGAL_REVIEW

        return overall_status, summary, financial_promotion_reason

    def _format_reviews(self, reviews: dict[str, SubReview]) -> str:
        """Format reviews as a readable string for the prompt."""
        formatted = []
        for agent_name, review in reviews.items():
            formatted.append(f"""
{agent_name}:
  RAG Status: {review.ragStatus}
  Feedback: {review.feedback}
  Issues: {review.issues if review.issues else 'None'}
""")
        return "\n".join(formatted)

    def determine_status_locally(self, reviews: dict[str, SubReview]) -> OverallStatus:
        """
        Determine overall status using local logic (without Gemini).

        This can be used as a fallback or for faster processing.
        """
        legal_review = reviews.get("Risk & Control Agent")

        # Check for financial promotion
        if legal_review and legal_review.isFinancialPromotion:
            return OverallStatus.REQUIRES_MANUAL_LEGAL_REVIEW

        # Check for Error status
        for review in reviews.values():
            if review.ragStatus == RagStatus.ERROR:
                return OverallStatus.ANALYSIS_ERROR

        # Check for Red status
        for review in reviews.values():
            if review.ragStatus == RagStatus.RED:
                return OverallStatus.FAILED

        return OverallStatus.PASSED
