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.colors import ListedColormap
from matplotlib.font_manager import FontProperties

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

FONT_PATH = ROOT.parents[1] / "public" / "fonts" / "NotoSansTC-Regular.ttf"
FONT = FontProperties(fname=str(FONT_PATH)) if FONT_PATH.exists() else None
plt.rcParams["axes.unicode_minus"] = False

audit = pd.read_csv(ROOT / "case-audit.csv")
qual = pd.read_csv(ROOT / "qualitative-cases.csv")

binary_columns = [
    "operator_controlled_site",
    "operator_controlled_social",
    "verified_ecommerce",
    "delivery_observed",
    "heritage_narrative",
    "relationship_narrative",
    "professional_advice",
    "local_story",
    "b2b_signal",
    "public_price",
]


def wilson_interval(successes: int, total: int, z: float = 1.959963984540054) -> tuple[float, float]:
    p = successes / total
    denominator = 1 + z * z / total
    centre = (p + z * z / (2 * total)) / denominator
    radius = z * math.sqrt((p * (1 - p) + z * z / (4 * total)) / total) / denominator
    return centre - radius, centre + radius


def savefig(name: str) -> None:
    plt.tight_layout()
    plt.savefig(FIG / name, dpi=200, bbox_inches="tight", facecolor="white")
    plt.close()


# Figure 1: region-balanced sampling frame.
region_order = ["北", "中", "南", "東"]
region_counts = audit["region"].value_counts().reindex(region_order)
plt.figure(figsize=(8.2, 4.4))
bars = plt.bar(region_order, region_counts, color=["#315c4c", "#6f3519", "#b26a32", "#d9a86c"])
plt.title("圖1　60家樣本的區域配置", fontproperties=FONT, fontsize=15)
plt.ylabel("案例數", fontproperties=FONT)
plt.xticks(fontproperties=FONT)
plt.yticks(range(0, 17, 3), fontproperties=FONT)
for bar, value in zip(bars, region_counts):
    plt.text(bar.get_x() + bar.get_width() / 2, value + 0.25, str(value), ha="center", fontproperties=FONT)
plt.ylim(0, 17)
savefig("figure-1-regional-sample.png")

# Figure 2: visibility tiers, deliberately neutral colors and no quality ranking.
tier_counts = audit["visibility_tier"].value_counts().reindex(["A", "B", "C"], fill_value=0)
tier_labels = ["A 行政／目錄訊號", "B 第三方市場頁", "C 業者控制通路"]
plt.figure(figsize=(8.2, 4.7))
bars = plt.barh(tier_labels, tier_counts.values, color=["#c8c2ba", "#d9a86c", "#315c4c"])
plt.title("圖2　標準搜尋可觀察的最高公開層級", fontproperties=FONT, fontsize=15)
plt.xlabel("案例數（不是能力或品質評分）", fontproperties=FONT)
plt.xticks(fontproperties=FONT)
plt.yticks(fontproperties=FONT)
for bar, value in zip(bars, tier_counts.values):
    plt.text(value + 0.5, bar.get_y() + bar.get_height() / 2, f"{value}（{value / len(audit):.1%}）", va="center", fontproperties=FONT)
plt.xlim(0, max(tier_counts.values) * 1.18)
savefig("figure-2-visibility-tiers.png")

# Figure 3: observable signals. Zero means not observed on the reviewed public pages.
signal_labels = {
    "operator_controlled_site": "自有網站",
    "operator_controlled_social": "自有社群／LINE",
    "verified_ecommerce": "可驗證線上交易",
    "delivery_observed": "明示配送",
    "heritage_narrative": "世代／歷史敘事",
    "relationship_narrative": "關係敘事",
    "professional_advice": "選米／烹煮知識",
    "local_story": "地方／生產者故事",
    "b2b_signal": "商用服務訊號",
    "public_price": "公開規格價格",
}
signal_counts = audit[binary_columns].sum().sort_values()
plt.figure(figsize=(9, 6.2))
bars = plt.barh([signal_labels[x] for x in signal_counts.index], signal_counts.values, color="#6f3519")
plt.title("圖3　60家樣本中的公開可觀察行銷訊號", fontproperties=FONT, fontsize=15)
plt.xlabel("觀察到的案例數；未觀察到不等於實際沒有", fontproperties=FONT)
plt.xticks(fontproperties=FONT)
plt.yticks(fontproperties=FONT)
for bar, value in zip(bars, signal_counts.values):
    plt.text(value + 0.12, bar.get_y() + bar.get_height() / 2, str(int(value)), va="center", fontproperties=FONT)
plt.xlim(0, max(10, signal_counts.max() + 2))
savefig("figure-3-observable-signals.png")

# Figure 4: regional distribution of controlled channels; descriptive only.
controlled = audit.assign(controlled=(audit["visibility_tier"] == "C").astype(int))
region_controlled = controlled.groupby("region")["controlled"].agg(["sum", "count"]).reindex(region_order)
plt.figure(figsize=(8.2, 4.7))
bars = plt.bar(region_order, region_controlled["sum"], color="#315c4c")
plt.title("圖4　各區域觀察到的業者控制通路", fontproperties=FONT, fontsize=15)
plt.ylabel("案例數（各區樣本皆為15家）", fontproperties=FONT)
plt.xticks(fontproperties=FONT)
plt.yticks(range(0, 5), fontproperties=FONT)
for bar, value in zip(bars, region_controlled["sum"]):
    plt.text(bar.get_x() + bar.get_width() / 2, value + 0.08, str(int(value)), ha="center", fontproperties=FONT)
plt.ylim(0, 4)
savefig("figure-4-regional-controlled-channels.png")

# Figure 5: a sensitivity funnel, not a conversion funnel or causal sequence.
funnel_labels = ["納入抽樣框", "具市場內容頁（B或C）", "業者控制通路（C）", "可驗證線上交易", "明示配送", "公開規格價格"]
funnel_values = [len(audit), int((audit.visibility_tier != "A").sum()), int((audit.visibility_tier == "C").sum()), int(audit.verified_ecommerce.sum()), int(audit.delivery_observed.sum()), int(audit.public_price.sum())]
plt.figure(figsize=(9, 5.2))
bars = plt.barh(funnel_labels[::-1], funnel_values[::-1], color=["#c8c2ba", "#d9a86c", "#b26a32", "#6f3519", "#315c4c", "#315c4c"])
plt.title("圖5　不同嚴格度下的數位轉譯可觀察範圍", fontproperties=FONT, fontsize=15)
plt.xlabel("案例數；各列是定義門檻，不代表顧客轉換路徑", fontproperties=FONT)
plt.xticks(fontproperties=FONT)
plt.yticks(fontproperties=FONT)
for bar, value in zip(bars, funnel_values[::-1]):
    plt.text(value + 0.6, bar.get_y() + bar.get_height() / 2, str(value), va="center", fontproperties=FONT)
plt.xlim(0, 66)
savefig("figure-5-definition-sensitivity.png")

# Figure 6: qualitative matrix uses two discrete colors and cell labels.
qual_columns = ["relationship_narrative", "heritage_narrative", "professional_advice", "operator_controlled_channel", "transaction_function", "delivery_signal", "product_story", "service_contact"]
qual_labels = ["關係敘事", "歷史傳承", "專業建議", "自有通路", "交易功能", "配送訊號", "產品故事", "服務聯絡"]
matrix = qual[qual_columns].to_numpy(dtype=int)
plt.figure(figsize=(10.5, 6.2))
plt.imshow(matrix, aspect="auto", cmap=ListedColormap(["#eeeae4", "#315c4c"]), vmin=0, vmax=1)
plt.xticks(range(len(qual_labels)), qual_labels, rotation=35, ha="right", fontproperties=FONT)
plt.yticks(range(len(qual)), qual["case_name"], fontproperties=FONT)
plt.title("圖6　資訊豐富案例的質性文本訊號矩陣", fontproperties=FONT, fontsize=15)
for i in range(matrix.shape[0]):
    for j in range(matrix.shape[1]):
        plt.text(j, i, "有" if matrix[i, j] else "未見", ha="center", va="center", color="white" if matrix[i, j] else "#6b625a", fontsize=8, fontproperties=FONT)
plt.figtext(0.5, 0.005, "灰色＝未觀察到；綠色＝觀察到。這不是成效評分。", ha="center", fontproperties=FONT, fontsize=9)
savefig("figure-6-qualitative-matrix.png")

controlled_n = int((audit.visibility_tier == "C").sum())
market_facing_n = int((audit.visibility_tier != "A").sum())
ci_low, ci_high = wilson_interval(controlled_n, len(audit))

tier_summary = pd.DataFrame({
    "visibility_tier": ["A", "B", "C"],
    "count": tier_counts.values,
    "share": tier_counts.values / len(audit),
})
tier_summary.to_csv(OUT / "visibility-tier-summary.csv", index=False, encoding="utf-8-sig")

signal_summary = pd.DataFrame({
    "signal": signal_counts.index,
    "count": signal_counts.values.astype(int),
    "share": signal_counts.values / len(audit),
})
signal_summary.to_csv(OUT / "signal-summary.csv", index=False, encoding="utf-8-sig")
region_controlled.reset_index().to_csv(OUT / "regional-controlled-summary.csv", index=False, encoding="utf-8-sig")

results = {
    "sample_n": int(len(audit)),
    "regions": {k: int(v) for k, v in region_counts.items()},
    "visibility_tiers": {k: int(v) for k, v in tier_counts.items()},
    "market_facing_pages_n": market_facing_n,
    "market_facing_pages_share": market_facing_n / len(audit),
    "operator_controlled_channel_n": controlled_n,
    "operator_controlled_channel_share": controlled_n / len(audit),
    "operator_controlled_channel_wilson_95": [ci_low, ci_high],
    "signals": {key: int(audit[key].sum()) for key in binary_columns},
    "qualitative_cases_n": int(len(qual)),
    "interpretation_boundary": "All values are publicly observable content signals as of 2026-07-17, not business capability, quality, revenue, loyalty, or causal effects.",
}
(ROOT / "analysis-results.json").write_text(json.dumps(results, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
print(json.dumps(results, ensure_ascii=False, indent=2))
