from typing import List, Optional, Tuple

from app.agents.base_agent import BaseAgent
from app.models.schemas import PreviousReviewContext, SubReview
from app.services.gemini_service import GeminiService
from app.services.reference_docs import ReferenceDocsService


class BrandAgent(BaseAgent):
    """Brand Agent - analyzes proofs against Barclays brand guidelines using Gemini."""

    name = "Brand Agent"

    def __init__(self, gemini_service: GeminiService, reference_docs: ReferenceDocsService):
        """
        Initialize the Brand Agent.

        Args:
            gemini_service: Service for making Gemini API calls
            reference_docs: Service for loading reference documents
        """
        self.gemini = gemini_service
        self.reference_docs = reference_docs

    def _get_brand_context(self, brand: str) -> str:
        """
        Get the appropriate brand specification based on the brand selection.

        Args:
            brand: Brand name ('Barclays' or 'Barclaycard')

        Returns:
            Brand specification content
        """
        if brand == "Barclays":
            return self.reference_docs.get_barclays_brand_spec()
        else:
            # Default to Barclaycard
            return self.reference_docs.get_barclaycard_brand_spec()

    def _build_revision_context(self, previous_review: PreviousReviewContext) -> str:
        """Build prompt section for revision-aware analysis."""
        issues_list = "\n".join(f"  - {issue}" for issue in previous_review.issues) if previous_review.issues else "  (No issues)"
        return f"""
---

**REVISION CONTEXT**

This is a revision of a previously reviewed proof. The previous version (Version {previous_review.version}) had the following brand review:

- RAG Status: {previous_review.ragStatus}
- Feedback: {previous_review.feedback}
- Issues identified:
{issues_list}

When analyzing this revision, you MUST:
1. Compare against the previous issues and determine which have been RESOLVED
2. Identify which previous issues are still OUTSTANDING (not fixed)
3. Identify any NEW issues introduced in this revision

Your response MUST include:
- resolvedIssues: Array of issues from the previous version that have been fixed
- outstandingIssues: Array of issues from the previous version that remain unfixed
- newIssues: Array of new issues not present in the previous version

---
"""

    async def analyze(
        self,
        images: List[Tuple[bytes, str]],
        previous_review: Optional[PreviousReviewContext] = None,
        brand: str = "Barclaycard",
        channel: Optional[str] = None,
        sub_channel: Optional[str] = None,
        proof_type: Optional[str] = None,
        on_fallback=None,
    ) -> SubReview:
        """
        Analyze the proof for brand guideline adherence.

        Args:
            images: List of (file_data, mime_type) tuples representing the proof
            previous_review: Optional context from previous version for revision-aware analysis
            brand: Brand to analyze against ('Barclays' or 'Barclaycard')
            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:
            SubReview with brand compliance assessment
        """
        # Get the appropriate brand specification
        brand_context = self._get_brand_context(brand)

        # Build revision context if available
        revision_context = ""
        if previous_review:
            revision_context = self._build_revision_context(previous_review)

        prompt = f"""You are a brand expert for {brand}. Your role is to analyze marketing proofs for adherence to {brand} brand guidelines.

Here is the {brand} brand specification to use for your analysis:

{brand_context}
{revision_context}
---

**PROOF METADATA**
- Channel: {channel or "Not specified"}
- Sub-Channel: {sub_channel or "Not specified"}
- Proof Type: {proof_type or "Not specified"}

Use this metadata to focus your analysis on the specific brand requirements for this channel and format.
---

Analyze the uploaded proof against the {brand} brand specification above, checking for:

1. **Logo Usage**: Is the {brand} logo used correctly? Check minimum size, clear space, placement, and that it hasn't been altered. Verify correct logo colors per guidelines.

2. **Card Portal** (if applicable for {brand}): If the Card Portal asset is present, verify it follows sizing rules (stroke weight and corner radius based on shortest side), proper border color, rotation limits, and that the logo is not placed outside it.

3. **Color Palette**: Are only approved {brand} masterbrand colors used? Check for proper WCAG-compliant color pairings and that sacred/primary colors are used appropriately.

4. **Typography**: Is Barclays Effra (or Arial fallback) used correctly? Check font weights (Medium/Bold for headings, Regular/Medium for body), sizes per type scale, and line spacing.

5. **Design Principles**: Does the overall design reflect the brand principles defined in the specification?

6. **Sacred Assets**: Verify that sacred/primary brand assets are present and not altered or misused.

7. **Accessibility**: Check for legible font sizes, proper contrast, and appropriate use of special typography elements per guidelines.

Provide your analysis as a JSON object. Be specific about any issues found.

IMPORTANT: Do NOT include page numbers, document names, or source citations in your feedback (e.g., no "Page 10", "per Page 12", "Social Media Guidelines Page 8"). All feedback must be self-contained and directly actionable without requiring users to look up external references.

RAG Status Guidelines:
- **Green**: Fully compliant with brand guidelines, no issues
- **Amber**: Minor deviations that should be addressed but don't severely impact brand integrity
- **Red**: Significant brand guideline issues that must be fixed before use

If the proof is nonsensical, not a marketing material, or cannot be analyzed, set analysisStatus to 'low_confidence'.

**Response Format:**
- Keep feedback brief and scannable
- Use bullet points for each finding
- Structure each feedback bullet as two clearly labelled parts separated by a line break:
  **Issue:** [Clear description of what's wrong]
  **Recommendation:** [Actionable fix — what to do and how]
- Always capitalise "Issue:" and "Recommendation:" and bold them with double asterisks (**)
- Always place the Recommendation on a new line after the Issue (not on the same line)
- Example:
  "• **Issue:** The logo is placed in the bottom-left corner, which doesn't align with brand guidelines.
  **Recommendation:** Move the logo to the top-right corner as specified in the brand guidelines."
- 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.
"""

        # Determine if revision fields should be included
        include_revision_fields = previous_review is not None

        # Use single-image or multi-image analysis depending on input
        if len(images) == 1:
            file_data, file_type = images[0]
            return await self.gemini.analyze_with_image(
                prompt, file_data, file_type, include_revision_fields=include_revision_fields, on_fallback=on_fallback
            )
        else:
            return await self.gemini.analyze_with_images(
                prompt, images, include_revision_fields=include_revision_fields, on_fallback=on_fallback
            )
