"""
AI analysis service — wraps the Anthropic Claude API.
Builds an agronomic prompt from scenario data and returns a structured dict.
"""
import json
import os
from typing import Any, Dict, Optional

import anthropic

from app.models.graft_combination import GraftCombination
from app.models.plant import Plant
from app.models.soil_profile import SoilProfile

_client: Optional[anthropic.Anthropic] = None

MODEL = "claude-sonnet-4-6"


def _get_client() -> anthropic.Anthropic:
    global _client
    if _client is None:
        _client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
    return _client


def _build_prompt(
    soil: SoilProfile,
    applied_n: float,
    applied_p: float,
    applied_k: float,
    irrigation_method: str,
    irrigation_frequency_days: int,
    season: str,
    duration_days: int,
    plant: Optional[Plant] = None,
    graft: Optional[GraftCombination] = None,
) -> str:
    lines = []

    # --- Plant / Graft section ---
    if graft is not None:
        rs = graft.rootstock
        sc = graft.scion
        lines += [
            "## Graft Combination",
            f"- Rootstock: {rs.name} ({rs.species})",
            f"  - Drought tolerance: {rs.drought_tolerance}/10  |  Salinity: {rs.salinity_tolerance}/10  |  Heat: {rs.heat_tolerance}/10  |  Cold: {rs.cold_tolerance}/10",
            f"  - Root depth: {rs.root_depth_category.value}  |  pH range: {rs.optimal_ph_min}–{rs.optimal_ph_max}",
            f"  - Disease resistance: {json.dumps(rs.disease_resistance)}",
            f"  - Nutrient uptake efficiency: {json.dumps(rs.nutrient_uptake_efficiency)}",
            f"  - Growth cycle: {rs.growth_cycle_days} days",
            f"- Scion: {sc.name} ({sc.species})",
            f"  - Drought tolerance: {sc.drought_tolerance}/10  |  Salinity: {sc.salinity_tolerance}/10  |  Heat: {sc.heat_tolerance}/10  |  Cold: {sc.cold_tolerance}/10",
            f"  - pH range: {sc.optimal_ph_min}–{sc.optimal_ph_max}",
            f"  - Yield potential: {sc.yield_potential_kg_per_plant} kg/plant  |  Growth cycle: {sc.growth_cycle_days} days",
            f"  - Disease resistance: {json.dumps(sc.disease_resistance)}",
            f"- Graft compatibility score: {graft.compatibility_score:.2f}/1.0",
            f"- Vigor boost: {graft.vigor_boost}x  |  Yield modifier: {graft.yield_modifier}x",
            f"- Stress tolerance overrides: {json.dumps(graft.stress_tolerance_override)}",
        ]
        if graft.notes:
            lines.append(f"- Notes: {graft.notes}")
    else:
        p = plant
        lines += [
            "## Plant (Ungrafted)",
            f"- Name: {p.name} ({p.species})  |  Type: {p.variety_type.value}",
            f"- Drought tolerance: {p.drought_tolerance}/10  |  Salinity: {p.salinity_tolerance}/10  |  Heat: {p.heat_tolerance}/10  |  Cold: {p.cold_tolerance}/10",
            f"- pH range: {p.optimal_ph_min}–{p.optimal_ph_max}",
            f"- Root depth: {p.root_depth_category.value}",
            f"- Yield potential: {p.yield_potential_kg_per_plant} kg/plant  |  Growth cycle: {p.growth_cycle_days} days",
            f"- Disease resistance: {json.dumps(p.disease_resistance)}",
            f"- Nutrient uptake efficiency: {json.dumps(p.nutrient_uptake_efficiency)}",
        ]

    # --- Soil section ---
    lines += [
        "",
        "## Soil Profile",
        f"- Name: {soil.name}  |  Type: {soil.soil_type.value}  |  Climate zone: {soil.climate_zone}",
        f"- pH: {soil.ph_level}  |  Organic matter: {soil.organic_matter_percent}%  |  Salinity: {soil.salinity_level} dS/m",
        f"- Drainage: {soil.drainage_rate.value}  |  Water retention: {soil.water_retention.value}",
        f"- Native NPK (ppm): N={soil.native_nitrogen}  P={soil.native_phosphorus}  K={soil.native_potassium}",
        f"- Temperature range: {soil.temperature_range_min}°C – {soil.temperature_range_max}°C",
    ]
    if soil.description:
        lines.append(f"- Description: {soil.description}")

    # --- Care protocol section ---
    lines += [
        "",
        "## Care Protocol",
        f"- Applied NPK (kg/ha): N={applied_n}  P={applied_p}  K={applied_k}",
        f"- Irrigation: {irrigation_method} every {irrigation_frequency_days} day(s)",
        f"- Season: {season}",
        f"- Simulation duration: {duration_days} days",
    ]

    # --- Task instruction ---
    lines += [
        "",
        "## Task",
        "You are an expert agronomist specialising in grafting, soil science, and crop modelling.",
        "Based on the scenario above, provide a rigorous agronomic analysis.",
        "Return ONLY a valid JSON object with this exact structure — no markdown, no commentary:",
        "",
        """{
  "predicted_yield": <float, kg per plant for the full duration>,
  "survival_probability": <float, 0.0–1.0>,
  "risk_factors": [<string>, ...],
  "recommended_adjustments": {
    "nitrogen": <float, optimal kg/ha>,
    "phosphorus": <float, optimal kg/ha>,
    "potassium": <float, optimal kg/ha>,
    "irrigation_notes": "<string>",
    "additional_notes": "<string>"
  },
  "growth_timeline": [
    {"week": <int>, "stage": "<string>", "expected_height_cm": <float>, "notes": "<string>"},
    ...
  ],
  "confidence_score": <float, 0.0–1.0>,
  "ai_analysis": "<agronomic reasoning, 2–3 paragraphs covering: graft/plant performance, soil compatibility, stress risks, NPK analysis, and overall prognosis>"
}""",
    ]

    return "\n".join(lines)


def run_analysis(
    soil: SoilProfile,
    applied_n: float,
    applied_p: float,
    applied_k: float,
    irrigation_method: str,
    irrigation_frequency_days: int,
    season: str,
    duration_days: int,
    plant: Optional[Plant] = None,
    graft: Optional[GraftCombination] = None,
) -> Dict[str, Any]:
    """Call Claude and return parsed analysis dict."""
    prompt = _build_prompt(
        soil=soil,
        applied_n=applied_n,
        applied_p=applied_p,
        applied_k=applied_k,
        irrigation_method=irrigation_method,
        irrigation_frequency_days=irrigation_frequency_days,
        season=season,
        duration_days=duration_days,
        plant=plant,
        graft=graft,
    )

    client = _get_client()
    message = client.messages.create(
        model=MODEL,
        max_tokens=4096,
        system=(
            "You are an expert agronomist and plant scientist. "
            "You always respond with valid JSON only — no markdown fences, no extra text."
        ),
        messages=[{"role": "user", "content": prompt}],
    )

    raw = message.content[0].text.strip()

    # Strip accidental markdown fences if Claude adds them despite instructions
    if raw.startswith("```"):
        raw = raw.split("```")[1]
        if raw.startswith("json"):
            raw = raw[4:]
        raw = raw.strip()

    return json.loads(raw)
