from __future__ import annotations

import csv
import json
import statistics
from collections import defaultdict
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np


ROOT = Path(__file__).resolve().parent
FIGURES = ROOT / "figures"
FIGURES.mkdir(exist_ok=True)

BINARY_FIELDS = [
    "recurring_rice_offer",
    "automatic_recurring_charge",
    "prepaid_multi_delivery",
    "quantity_control_disclosed",
    "schedule_control_disclosed",
    "skip_pause_disclosed",
    "cancel_terms_disclosed",
    "household_usage_guidance",
    "human_assistance_disclosed",
    "fresh_milling_disclosed",
    "farmer_origin_narrative",
    "broad_cross_category_assortment",
    "bulk_or_multipack",
    "rapid_delivery",
    "physical_network_or_pickup",
    "visible_price_promotion",
    "unit_price_displayed",
]

INDEX_FIELDS = {
    "relationship_service_index": [
        "quantity_control_disclosed",
        "schedule_control_disclosed",
        "skip_pause_disclosed",
        "household_usage_guidance",
        "human_assistance_disclosed",
        "fresh_milling_disclosed",
        "farmer_origin_narrative",
    ],
    "consumer_control_index": [
        "quantity_control_disclosed",
        "schedule_control_disclosed",
        "skip_pause_disclosed",
        "cancel_terms_disclosed",
    ],
    "scale_convenience_index": [
        "broad_cross_category_assortment",
        "bulk_or_multipack",
        "rapid_delivery",
        "physical_network_or_pickup",
        "visible_price_promotion",
        "unit_price_displayed",
    ],
    "subscription_infrastructure_index": [
        "recurring_rice_offer",
        "automatic_recurring_charge",
        "prepaid_multi_delivery",
    ],
}

GROUP_LABELS = {
    "small_specialist": "小型／專門米業服務",
    "large_chain_format": "大型連鎖通路型態",
}


def read_rows() -> list[dict[str, object]]:
    with (ROOT / "channels.csv").open(encoding="utf-8-sig", newline="") as handle:
        rows: list[dict[str, object]] = list(csv.DictReader(handle))
    for row in rows:
        for field in BINARY_FIELDS:
            row[field] = int(str(row[field]))
        for index_name, components in INDEX_FIELDS.items():
            row[index_name] = sum(int(row[field]) for field in components)
    return rows


def mean(values: list[float]) -> float:
    return sum(values) / len(values)


rows = read_rows()
with (ROOT / "price-examples.csv").open(encoding="utf-8-sig", newline="") as handle:
    price_rows = list(csv.DictReader(handle))
groups: dict[str, list[dict[str, object]]] = defaultdict(list)
for row in rows:
    groups[str(row["group"])].append(row)

group_summary: dict[str, object] = {}
for group, group_rows in groups.items():
    group_summary[group] = {
        "label": GROUP_LABELS[group],
        "n": len(group_rows),
        "index_means": {
            index_name: round(mean([float(row[index_name]) for row in group_rows]), 2)
            for index_name in INDEX_FIELDS
        },
        "feature_prevalence": {
            field: {
                "count": sum(int(row[field]) for row in group_rows),
                "total": len(group_rows),
                "percent": round(sum(int(row[field]) for row in group_rows) / len(group_rows) * 100, 1),
            }
            for field in BINARY_FIELDS
        },
    }

channel_scores = [
    {
        "channel_id": row["channel_id"],
        "operator": row["operator"],
        "channel_format": row["channel_format"],
        "group": row["group"],
        **{name: int(row[name]) for name in INDEX_FIELDS},
    }
    for row in rows
]

results = {
    "accessed_on": "2026-07-14",
    "sample_size": len(rows),
    "group_sizes": {group: len(group_rows) for group, group_rows in groups.items()},
    "index_definitions": {name: fields for name, fields in INDEX_FIELDS.items()},
    "group_summary": group_summary,
    "channel_scores": channel_scores,
    "illustrative_price_examples": {
        group: {
            "n": len([row for row in price_rows if row["group"] == group]),
            "median_twd_per_kg": round(
                statistics.median(
                    float(row["derived_twd_per_kg"])
                    for row in price_rows
                    if row["group"] == group
                ),
                2,
            ),
            "min_twd_per_kg": min(
                float(row["derived_twd_per_kg"])
                for row in price_rows
                if row["group"] == group
            ),
            "max_twd_per_kg": max(
                float(row["derived_twd_per_kg"])
                for row in price_rows
                if row["group"] == group
            ),
        }
        for group in groups
    },
    "price_comparability_warning": (
        "價格列是少量目的性示例，不是平衡SKU樣本；小型方案包含多次配送、鮮碾、策展或人工服務，連鎖價格也可能受會員、地區、促銷與運費影響，不得解讀為市場平均或品質調整後價差。"
    ),
    "interpretation_guardrail": (
        "0只表示指定公開頁面未觀察到明確資訊；指標是描述性公開資訊編碼，不代表能力、品質、法令遵循、顧客滿意或經營績效。"
    ),
}

(ROOT / "analysis-results.json").write_text(
    json.dumps(results, ensure_ascii=False, indent=2) + "\n", encoding="utf-8"
)

font_path = Path(__file__).resolve().parents[2] / "public" / "fonts" / "NotoSansTC-Regular.ttf"
if font_path.exists():
    from matplotlib.font_manager import FontProperties

    font = FontProperties(fname=str(font_path))
    plt.rcParams["axes.unicode_minus"] = False
else:
    font = None


def set_font(axis):
    if not font:
        return
    for item in [axis.title, axis.xaxis.label, axis.yaxis.label, *axis.get_xticklabels(), *axis.get_yticklabels()]:
        item.set_fontproperties(font)


colors = {"small_specialist": "#9a4f22", "large_chain_format": "#315c4c"}

# Figure 1: normalized index profile
fig, ax = plt.subplots(figsize=(10.5, 6.2))
index_order = list(INDEX_FIELDS)
index_labels = ["關係型服務", "消費者控制", "規模便利", "訂閱基礎"]
maxima = np.array([len(INDEX_FIELDS[name]) for name in index_order], dtype=float)
x = np.arange(len(index_order))
width = 0.34
for offset, group in zip((-width / 2, width / 2), ("small_specialist", "large_chain_format")):
    values = np.array([group_summary[group]["index_means"][name] for name in index_order]) / maxima * 100
    bars = ax.bar(x + offset, values, width, label=GROUP_LABELS[group], color=colors[group])
    for bar, value in zip(bars, values):
        ax.text(bar.get_x() + bar.get_width() / 2, value + 2, f"{value:.0f}%", ha="center", fontsize=9, fontproperties=font)
ax.set_title("圖1　兩類通路的公開資訊指標輪廓（標準化為0–100）", fontproperties=font, fontsize=15)
ax.set_ylabel("占該指標可觀察項目的比例（%）", fontproperties=font)
ax.set_xticks(x, index_labels, fontproperties=font)
ax.set_ylim(0, 110)
ax.grid(axis="y", alpha=0.2)
ax.legend(prop=font, frameon=False)
set_font(ax)
fig.tight_layout()
fig.savefig(FIGURES / "figure-1-index-profile.png", dpi=180)
plt.close(fig)

# Figure 2: channel positioning
fig, ax = plt.subplots(figsize=(10.5, 7.2))
for row in rows:
    x_value = float(row["scale_convenience_index"])
    y_value = float(row["relationship_service_index"])
    group = str(row["group"])
    ax.scatter(x_value, y_value, s=100, color=colors[group], edgecolor="white", linewidth=1.2)
    ax.annotate(str(row["channel_id"]), (x_value, y_value), xytext=(5, 6), textcoords="offset points", fontproperties=font, fontsize=9)
ax.axvline(3, color="#aaa39a", linewidth=1, linestyle="--")
ax.axhline(3.5, color="#aaa39a", linewidth=1, linestyle="--")
ax.set_xlim(-0.4, 6.4)
ax.set_ylim(-0.4, 7.5)
ax.set_xlabel("規模便利指標（0–6）", fontproperties=font)
ax.set_ylabel("關係型服務指標（0–7）", fontproperties=font)
ax.set_title("圖2　通路定位：規模便利與關係型服務不是同一條軸線", fontproperties=font, fontsize=15)
ax.grid(alpha=0.16)
set_font(ax)
fig.tight_layout()
fig.savefig(FIGURES / "figure-2-positioning.png", dpi=180)
plt.close(fig)

# Figure 3: selected feature prevalence
selected = [
    ("recurring_rice_offer", "白米週期服務"),
    ("automatic_recurring_charge", "自動扣款"),
    ("quantity_control_disclosed", "數量／內容控制"),
    ("skip_pause_disclosed", "跳過／暫停"),
    ("household_usage_guidance", "家庭用量引導"),
    ("fresh_milling_disclosed", "鮮碾揭露"),
    ("broad_cross_category_assortment", "跨品類一站購足"),
    ("rapid_delivery", "快速配送"),
    ("physical_network_or_pickup", "實體網絡／取貨"),
    ("unit_price_displayed", "單位價格顯示"),
]
matrix = np.array([
    [group_summary[group]["feature_prevalence"][field]["percent"] for field, _ in selected]
    for group in ("small_specialist", "large_chain_format")
])
fig, ax = plt.subplots(figsize=(12, 4.6))
image = ax.imshow(matrix, cmap="YlOrBr", vmin=0, vmax=100, aspect="auto")
for i in range(matrix.shape[0]):
    for j in range(matrix.shape[1]):
        ax.text(j, i, f"{matrix[i, j]:.0f}%", ha="center", va="center", color="#2a211b", fontproperties=font, fontsize=9)
ax.set_xticks(range(len(selected)), [label for _, label in selected], rotation=30, ha="right", fontproperties=font)
ax.set_yticks([0, 1], [GROUP_LABELS["small_specialist"], GROUP_LABELS["large_chain_format"]], fontproperties=font)
ax.set_title("圖3　指定公開頁面中主要功能與價值訊號的觀察比例", fontproperties=font, fontsize=15)
colorbar = fig.colorbar(image, ax=ax)
colorbar.set_label("觀察比例（%）", fontproperties=font)
set_font(ax)
fig.tight_layout()
fig.savefig(FIGURES / "figure-3-feature-heatmap.png", dpi=180)
plt.close(fig)

print(json.dumps(results, ensure_ascii=False, indent=2))
