from __future__ import annotations

import json
import math
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib import font_manager
from matplotlib.patches import FancyBboxPatch

ROOT = Path(__file__).resolve().parent
OUT = ROOT / "outputs"
FIG = OUT / "figures"
OUT.mkdir(exist_ok=True)
FIG.mkdir(exist_ok=True)

font_candidates = [
    ROOT.parents[1] / "public" / "fonts" / "NotoSansTC-Regular.ttf",
    Path("C:/Windows/Fonts/msjh.ttc"),
]
for candidate in font_candidates:
    if candidate.exists():
        font_manager.fontManager.addfont(str(candidate))
        plt.rcParams["font.family"] = font_manager.FontProperties(fname=str(candidate)).get_name()
        break
plt.rcParams["axes.unicode_minus"] = False
plt.rcParams["figure.dpi"] = 150

COLORS = {
    "brown": "#743c22",
    "orange": "#c9702c",
    "green": "#3f7551",
    "blue": "#547b91",
    "cream": "#f7efe4",
    "red": "#a6493f",
    "ink": "#2b211c",
}

crop = pd.read_csv(ROOT / "crop-scenarios.csv")
provider = pd.read_csv(ROOT / "provider-assumptions.csv")
risk = pd.read_csv(ROOT / "risk-matrix.csv")

crop["variable_cost_per_ha_scan"] = (
    crop["flight_cost_twd_per_ha_scan"]
    + crop["expert_review_cost_twd_per_ha_scan"]
    + crop["cloud_report_cost_twd_per_ha_scan"]
)
crop["annual_service_fee"] = crop["annual_scans"] * crop["service_price_twd_per_ha_scan"]
crop["expected_avoided_loss"] = (
    crop["gross_value_at_risk_twd_per_ha_year"]
    * crop["outbreak_probability"]
    * crop["conditional_loss_share"]
    * crop["detectable_actionable_share"]
    * crop["mitigation_effectiveness"]
)
crop["annual_customer_value"] = crop["expected_avoided_loss"] + crop["labor_saving_twd_per_ha_year"]
crop["customer_net_value"] = crop["annual_customer_value"] - crop["annual_service_fee"]
crop["provider_contribution_per_ha_year"] = (
    (crop["service_price_twd_per_ha_scan"] - crop["variable_cost_per_ha_scan"])
    * crop["annual_scans"]
)
crop["value_fee_ratio"] = crop["annual_customer_value"] / crop["annual_service_fee"]
crop.to_csv(OUT / "crop-economics-results.csv", index=False, encoding="utf-8-sig")

p = dict(zip(provider["parameter"], provider["value"]))
weighted_contribution = (
    p["portfolio_rice_share"] * crop.loc[crop["crop"] == "稻作", "provider_contribution_per_ha_year"].iloc[0]
    + p["portfolio_tea_share"] * crop.loc[crop["crop"] == "茶園", "provider_contribution_per_ha_year"].iloc[0]
    + p["portfolio_orchard_share"] * crop.loc[crop["crop"] == "果園", "provider_contribution_per_ha_year"].iloc[0]
)
org_rows = []
for organizations in range(0, 11):
    residual = max(
        0.0,
        p["annual_fixed_operating_cost"] - organizations * p["anchor_organization_annual_fee"],
    )
    area = math.ceil(residual / weighted_contribution) if residual else 0
    org_rows.append(
        {
            "anchor_organizations": organizations,
            "annual_platform_fee_twd": organizations * p["anchor_organization_annual_fee"],
            "residual_fixed_cost_twd": residual,
            "break_even_portfolio_ha": area,
        }
    )
breakeven = pd.DataFrame(org_rows)
breakeven.to_csv(OUT / "provider-break-even-results.csv", index=False, encoding="utf-8-sig")

risk["risk_score"] = risk["probability_1_5"] * risk["impact_1_5"]
risk["priority"] = pd.cut(
    risk["risk_score"], bins=[0, 9, 15, 25], labels=["監測", "重要", "高優先"], include_lowest=True
)
risk.sort_values(["risk_score", "risk_id"], ascending=[False, True]).to_csv(
    OUT / "risk-priority-results.csv", index=False, encoding="utf-8-sig"
)

tea = crop.loc[crop["crop"] == "茶園"].iloc[0]
probabilities = np.round(np.arange(0.10, 0.41, 0.05), 2)
actionable = np.round(np.arange(0.35, 0.86, 0.10), 2)
sens_rows = []
for probability in probabilities:
    for share in actionable:
        avoided = (
            tea["gross_value_at_risk_twd_per_ha_year"]
            * probability
            * tea["conditional_loss_share"]
            * share
            * tea["mitigation_effectiveness"]
        )
        sens_rows.append(
            {
                "outbreak_probability": probability,
                "detectable_actionable_share": share,
                "expected_avoided_loss_twd": avoided,
                "net_value_after_fee_and_labor_twd": avoided
                + tea["labor_saving_twd_per_ha_year"]
                - tea["annual_service_fee"],
            }
        )
sensitivity = pd.DataFrame(sens_rows)
sensitivity.to_csv(OUT / "tea-sensitivity-grid.csv", index=False, encoding="utf-8-sig")

# Figure 1: service architecture
fig, ax = plt.subplots(figsize=(12, 5.8))
ax.set_xlim(0, 12)
ax.set_ylim(0, 6)
ax.axis("off")
steps = [
    (0.4, 3.7, "1 空中巡田", "UAV找異常區\n不直接下診斷"),
    (3.25, 3.7, "2 眼前複核", "智慧眼鏡/手機\n引導標準採樣"),
    (6.1, 3.7, "3 AI分流", "病害候選、信心\n未知類別與轉介"),
    (8.95, 3.7, "4 經濟決策", "預期損失、處置成本\n優先順序與紀錄"),
]
for x, y, title, subtitle in steps:
    box = FancyBboxPatch(
        (x, y), 2.35, 1.35, boxstyle="round,pad=0.18",
        facecolor=COLORS["cream"], edgecolor=COLORS["brown"], linewidth=1.6
    )
    ax.add_patch(box)
    ax.text(x + 1.175, y + 0.88, title, ha="center", va="center", fontsize=13, fontweight="bold", color=COLORS["brown"])
    ax.text(x + 1.175, y + 0.35, subtitle, ha="center", va="center", fontsize=10, color=COLORS["ink"])
for x in [2.75, 5.6, 8.45]:
    ax.annotate("", xy=(x + 0.42, 4.38), xytext=(x, 4.38), arrowprops=dict(arrowstyle="->", lw=2, color=COLORS["orange"]))
ax.add_patch(FancyBboxPatch((1.0, 0.65), 10.0, 1.55, boxstyle="round,pad=0.2", facecolor="#edf5ef", edgecolor=COLORS["green"], linewidth=1.4))
ax.text(6, 1.75, "可驗證服務層", ha="center", fontsize=13, fontweight="bold", color=COLORS["green"])
ax.text(6, 1.25, "每一筆建議都保留影像來源、模型版本、信心值、人工複核、處置決定與後續結果", ha="center", fontsize=10.5)
ax.text(6, 0.85, "最終處置由具責任的農民／植保專業人員決定；系統不得把模型輸出包裝成確診或保證", ha="center", fontsize=10.5)
ax.set_title("圖1　從異常偵測到可追溯決策的服務架構", fontsize=16, fontweight="bold", pad=10)
fig.tight_layout()
fig.savefig(FIG / "figure-1-service-architecture.png", bbox_inches="tight")
plt.close(fig)

# Figure 2: customer value versus annual fee
fig, ax = plt.subplots(figsize=(10, 6))
x = np.arange(len(crop))
w = 0.35
ax.bar(x - w / 2, crop["annual_customer_value"], width=w, label="情境年價值", color=COLORS["green"])
ax.bar(x + w / 2, crop["annual_service_fee"], width=w, label="情境年服務費", color=COLORS["orange"])
ax.axhline(0, color="#777", lw=0.8)
for i, row in crop.iterrows():
    ax.text(i - w / 2, row["annual_customer_value"] + 250, f'{row["annual_customer_value"]:,.0f}', ha="center", fontsize=9)
    ax.text(i + w / 2, row["annual_service_fee"] + 250, f'{row["annual_service_fee"]:,.0f}', ha="center", fontsize=9)
ax.set_xticks(x, crop["crop"])
ax.set_ylabel("新臺幣／公頃／年")
ax.set_title("圖2　三種作物情境的可捕捉價值與服務費", fontweight="bold")
ax.legend(frameon=False)
ax.grid(axis="y", alpha=0.2)
fig.tight_layout()
fig.savefig(FIG / "figure-2-customer-value-fee.png", bbox_inches="tight")
plt.close(fig)

# Figure 3: provider contribution
fig, ax = plt.subplots(figsize=(9, 5.8))
bars = ax.bar(crop["crop"], crop["provider_contribution_per_ha_year"], color=[COLORS["blue"], COLORS["green"], COLORS["orange"]])
for bar, value in zip(bars, crop["provider_contribution_per_ha_year"]):
    ax.text(bar.get_x() + bar.get_width() / 2, value + 80, f"{value:,.0f}", ha="center", fontweight="bold")
ax.set_ylabel("每公頃年貢獻（新臺幣）")
ax.set_title("圖3　服務提供者的每公頃年貢獻情境", fontweight="bold")
ax.grid(axis="y", alpha=0.2)
fig.tight_layout()
fig.savefig(FIG / "figure-3-provider-contribution.png", bbox_inches="tight")
plt.close(fig)

# Figure 4: break-even portfolio
fig, ax = plt.subplots(figsize=(10, 5.8))
ax.plot(breakeven["anchor_organizations"], breakeven["break_even_portfolio_ha"], marker="o", lw=2.4, color=COLORS["brown"])
ax.fill_between(breakeven["anchor_organizations"], breakeven["break_even_portfolio_ha"], alpha=0.12, color=COLORS["orange"])
for _, row in breakeven.iloc[::2].iterrows():
    ax.annotate(f'{int(row["break_even_portfolio_ha"]):,} ha', (row["anchor_organizations"], row["break_even_portfolio_ha"]), xytext=(0, 8), textcoords="offset points", ha="center", fontsize=8)
ax.set_xlabel("付費錨定組織數")
ax.set_ylabel("損益兩平組合面積（公頃）")
ax.set_title("圖4　組織平台費如何改變所需服務面積", fontweight="bold")
ax.grid(alpha=0.25)
fig.tight_layout()
fig.savefig(FIG / "figure-4-break-even-area.png", bbox_inches="tight")
plt.close(fig)

# Figure 5: tea sensitivity
pivot = sensitivity.pivot(index="outbreak_probability", columns="detectable_actionable_share", values="net_value_after_fee_and_labor_twd")
fig, ax = plt.subplots(figsize=(10, 6.2))
im = ax.imshow(pivot.values, cmap="RdYlGn", aspect="auto")
ax.set_xticks(np.arange(len(pivot.columns)), [f"{v:.0%}" for v in pivot.columns])
ax.set_yticks(np.arange(len(pivot.index)), [f"{v:.0%}" for v in pivot.index])
ax.set_xlabel("可偵測且可處置比例")
ax.set_ylabel("病害事件年機率")
for r in range(pivot.shape[0]):
    for c in range(pivot.shape[1]):
        ax.text(c, r, f"{pivot.iloc[r, c]/1000:.1f}k", ha="center", va="center", fontsize=8)
fig.colorbar(im, ax=ax, label="扣除服務費後淨價值（新臺幣／公頃／年）")
ax.set_title("圖5　茶園情境對事件機率與可處置比例的敏感度", fontweight="bold")
fig.tight_layout()
fig.savefig(FIG / "figure-5-tea-sensitivity.png", bbox_inches="tight")
plt.close(fig)

# Figure 6: risk priorities
fig, ax = plt.subplots(figsize=(10, 7))
priority_colors = {"監測": COLORS["blue"], "重要": COLORS["orange"], "高優先": COLORS["red"]}
for _, row in risk.iterrows():
    ax.scatter(row["probability_1_5"], row["impact_1_5"], s=80 + row["risk_score"] * 8, color=priority_colors[str(row["priority"])], alpha=0.8, edgecolor="white")
    ax.text(row["probability_1_5"] + 0.05, row["impact_1_5"] + 0.05, row["risk_id"], fontsize=8)
ax.set_xlim(0.7, 5.4)
ax.set_ylim(0.7, 5.4)
ax.set_xticks(range(1, 6))
ax.set_yticks(range(1, 6))
ax.set_xlabel("可能性（研究者排序，非事故機率）")
ax.set_ylabel("影響程度")
ax.set_title("圖6　創業服務風險優先矩陣", fontweight="bold")
ax.grid(alpha=0.25)
fig.tight_layout()
fig.savefig(FIG / "figure-6-risk-matrix.png", bbox_inches="tight")
plt.close(fig)

results = {
    "study_type": "transparent techno-economic scenario analysis",
    "doi": "10.5281/zenodo.21510234",
    "crop_count": int(len(crop)),
    "risk_count": int(len(risk)),
    "high_priority_risk_count": int((risk["risk_score"] >= 16).sum()),
    "weighted_provider_contribution_twd_per_ha_year": round(float(weighted_contribution), 2),
    "break_even_ha_zero_anchor_orgs": int(breakeven.loc[breakeven["anchor_organizations"] == 0, "break_even_portfolio_ha"].iloc[0]),
    "break_even_ha_six_anchor_orgs": int(breakeven.loc[breakeven["anchor_organizations"] == 6, "break_even_portfolio_ha"].iloc[0]),
    "crop_results": crop[
        ["crop", "annual_customer_value", "annual_service_fee", "customer_net_value", "provider_contribution_per_ha_year", "value_fee_ratio"]
    ].round(2).to_dict(orient="records"),
    "limitations": [
        "All monetary values, probabilities, and risk scores are researcher-defined assumptions.",
        "No field images, farm records, disease samples, customer willingness-to-pay data, or audited business costs were used.",
        "Scenario outputs are not market averages, quotations, diagnoses, legal determinations, or performance guarantees.",
    ],
}
(ROOT / "analysis-results.json").write_text(json.dumps(results, ensure_ascii=False, indent=2), encoding="utf-8")
print(json.dumps(results, ensure_ascii=False, indent=2))
