"""
backend/agents/matching_agent.py

Scores how well an applicant's preferences match an open contract's
requirements using a single Gemini call. Returns a 0-100 score and
a short explanation — used to rank applicants before the poster picks one.
"""

import json
from agents.base_agent import BaseAgent

_MATCHING_PROMPT = """You are a matching agent. Your job is to score how well an applicant's
preferences align with an open contract's requirements.

Contract type: {contract_type}

CONTRACT REQUIREMENTS (what the poster needs):
{requirements}

APPLICANT PREFERENCES (what the applicant brings / wants):
{preferences}

Evaluate on these axes:
1. Core match — does the applicant fundamentally fit what the contract needs?
2. Budget/rate alignment — are financial expectations compatible?
3. Timeline/availability — do schedules overlap?
4. Skills/criteria — do they have what is required?
5. Flexibility potential — could a negotiation bridge remaining gaps?

RESPOND ONLY with valid JSON in this exact format:
{{
  "match_score": <integer 0-100>,
  "match_reasoning": "<one concise sentence explaining the score>",
  "key_alignments": ["<thing 1 that matches well>", "<thing 2>"],
  "key_gaps": ["<gap 1>", "<gap 2>"]
}}

Scoring guide:
90-100 → Nearly perfect fit, minimal negotiation needed
70-89  → Good fit, small gaps bridgeable in negotiation
50-69  → Moderate fit, notable differences but workable
30-49  → Weak fit, significant gaps — negotiation will be hard
0-29   → Poor fit, fundamental incompatibility
"""


class MatchingAgent(BaseAgent):
    def __init__(self):
        super().__init__(system_prompt="You are a concise JSON-only matching agent.")

    async def score_applicant(
        self,
        contract_requirements: dict,
        applicant_preferences: dict,
        contract_type: str,
    ) -> dict:
        """
        Score how well an applicant matches a contract.

        Returns:
            {
                "match_score": int (0-100),
                "match_reasoning": str,
                "key_alignments": list[str],
                "key_gaps": list[str],
            }
        On failure returns a safe default with score=0.
        """
        prompt = _MATCHING_PROMPT.format(
            contract_type=contract_type,
            requirements=json.dumps(contract_requirements, indent=2),
            preferences=json.dumps(applicant_preferences, indent=2),
        )
        try:
            # self.call() returns a dict — BaseAgent already handles JSON parsing
            result = await self.call(prompt)
            if "error" in result:
                raise ValueError(result["error"])
            # Clamp score to 0-100
            result["match_score"] = max(0, min(100, int(result.get("match_score", 0))))
            return result
        except Exception as e:
            print(f"[MatchingAgent] score_applicant failed: {e}")
            return {
                "match_score": 0,
                "match_reasoning": "Could not compute score.",
                "key_alignments": [],
                "key_gaps": [],
            }


# Module-level singleton
_agent = None


def get_matching_agent() -> MatchingAgent:
    global _agent
    if _agent is None:
        _agent = MatchingAgent()
    return _agent


async def score_applicant(
    contract_requirements: dict,
    applicant_preferences: dict,
    contract_type: str,
) -> dict:
    """Convenience wrapper — use the module-level singleton."""
    return await get_matching_agent().score_applicant(
        contract_requirements, applicant_preferences, contract_type
    )
