import { useState, useMemo, useCallback } from "react";
import * as XLSX from "xlsx";
import {
  BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend,
  ResponsiveContainer, ReferenceLine, Cell
} from "recharts";

const DEFAULT_THRESHOLDS = {
  ad: [0, 2000, 10000, 50000],
  fee: [0, 1000, 3000, 6000],
  traffic: [0, 50000, 200000, 500000],
  highTGI: 200,
  easyTGI: 150,
};

const LABELS = {
  ad: ["无效果收入", "效果_低", "效果_中", "效果_高", "效果_超高"],
  fee: ["无年费", "年费_低", "年费_中", "年费_高", "年费_超高"],
  traffic: ["无流量", "流量_低", "流量_中", "流量_高", "流量_超高"],
};

const REQUIRED_SCHEDULE_COLS = ["城市等级", "城市名称", "行政区", "行业", "类目", "月份", "占期周期"];
const REQUIRED_MERCHANT_COLS = ["商户ID", "商户名称", "行业", "类目", "城市名称", "效果广告收入", "年费收入", "品广收入", "是否售卖品广", "流量"];

function classifyValue(val, thresholds, labels) {
  const v = val == null || isNaN(val) ? 0 : Number(val);
  if (v <= thresholds[0]) return labels[0];
  if (v <= thresholds[1]) return labels[1];
  if (v <= thresholds[2]) return labels[2];
  if (v <= thresholds[3]) return labels[3];
  return labels[4];
}

function deduplicate(arr) {
  const seen = new Set();
  return arr.filter((r) => {
    const key = `${r["商户ID"]}|${r["城市名称"]}|${r["效果广告收入"]}|${r["年费收入"]}|${r["流量"]}`;
    if (seen.has(key)) return false;
    seen.add(key);
    return true;
  });
}

function calcTGI(data, featureCol) {
  const total = data.length;
  const buyers = data.filter((r) => r._isBuyer);
  const buyerN = buyers.length;
  const layers = [...new Set(data.map((r) => r[featureCol]))];
  return layers.map((layer) => {
    const totalInLayer = data.filter((r) => r[featureCol] === layer).length;
    const buyerInLayer = buyers.filter((r) => r[featureCol] === layer).length;
    const pctTotal = (totalInLayer / total) * 100;
    const pctBuyer = buyerN > 0 ? (buyerInLayer / buyerN) * 100 : 0;
    const tgi = pctTotal > 0 ? (pctBuyer / pctTotal) * 100 : 0;
    return {
      特征维度: featureCol.replace("分层", ""),
      分层: layer,
      总体数量: totalInLayer,
      "总体占比%": +pctTotal.toFixed(2),
      买家数量: buyerInLayer,
      "买家占比%": +pctBuyer.toFixed(2),
      TGI: +tgi.toFixed(1),
    };
  }).sort((a, b) => b.TGI - a.TGI);
}

function runAnalysis(scheduleData, merchantData, thresholds) {
  let merchants = merchantData.map((r) => ({
    ...r,
    流量: r["流量"] == null || isNaN(r["流量"]) ? 0 : Number(r["流量"]),
    效果广告收入: Number(r["效果广告收入"]) || 0,
    年费收入: Number(r["年费收入"]) || 0,
    品广收入: Number(r["品广收入"]) || 0,
  }));
  merchants = deduplicate(merchants);
  merchants.forEach((r) => {
    r._isBuyer = r["品广收入"] > 0;
    r["效果分层"] = classifyValue(r["效果广告收入"], thresholds.ad, LABELS.ad);
    r["年费分层"] = classifyValue(r["年费收入"], thresholds.fee, LABELS.fee);
    r["流量分层"] = classifyValue(r["流量"], thresholds.traffic, LABELS.traffic);
  });

  const tgiOverall = {
    效果分层: calcTGI(merchants, "效果分层"),
    年费分层: calcTGI(merchants, "年费分层"),
    流量分层: calcTGI(merchants, "流量分层"),
  };

  const tgiLookup = {};
  for (const [feat, rows] of Object.entries(tgiOverall)) {
    tgiLookup[feat] = {};
    rows.forEach((r) => (tgiLookup[feat][r["分层"]] = r.TGI));
  }

  const categories = [...new Set(merchants.map((r) => r["类目"]))];
  const catTGI = {};
  const catTGILookup = {};
  categories.forEach((cat) => {
    const sub = merchants.filter((r) => r["类目"] === cat);
    if (sub.length < 10 || !sub.some((r) => r._isBuyer)) return;
    catTGI[cat] = {
      效果分层: calcTGI(sub, "效果分层"),
      年费分层: calcTGI(sub, "年费分层"),
      流量分层: calcTGI(sub, "流量分层"),
    };
    catTGILookup[cat] = {};
    for (const [feat, rows] of Object.entries(catTGI[cat])) {
      catTGILookup[cat][feat] = {};
      rows.forEach((r) => (catTGILookup[cat][feat][r["分层"]] = r.TGI));
    }
  });

  merchants.forEach((r) => {
    const cat = r["类目"];
    const lookup = catTGILookup[cat] || {};
    const t1 = (lookup["效果分层"] || {})[r["效果分层"]] ?? tgiLookup["效果分层"][r["效果分层"]] ?? 100;
    const t2 = (lookup["年费分层"] || {})[r["年费分层"]] ?? tgiLookup["年费分层"][r["年费分层"]] ?? 100;
    const t3 = (lookup["流量分层"] || {})[r["流量分层"]] ?? tgiLookup["流量分层"][r["流量分层"]] ?? 100;
    r._tgiAd = t1;
    r._tgiFee = t2;
    r._tgiTraffic = t3;
    r._score = +((t1 + t2 + t3) / 3).toFixed(1);
    r._label = r._score >= thresholds.highTGI ? "高潜力" : r._score >= thresholds.easyTGI ? "较容易" : r._score >= 100 ? "一般" : "较难";
  });

  const easySell = merchants.filter(
    (r) => !r._isBuyer && (r._label === "高潜力" || r._label === "较容易")
  );

  const sellable = scheduleData.filter((r) => r["占期周期"] === "可售卖");
  const merchantByCityCategory = {};
  easySell.forEach((r) => {
    const key = `${r["城市名称"]}||${r["类目"]}`;
    if (!merchantByCityCategory[key]) merchantByCityCategory[key] = [];
    merchantByCityCategory[key].push(r);
  });

  const matched = sellable.map((s) => {
    const key = `${s["城市名称"]}||${s["类目"]}`;
    const list = merchantByCityCategory[key] || [];
    const uniqueNames = [...new Set(list.map((m) => m["商户名称"]))];
    return {
      城市等级: s["城市等级"],
      城市名称: s["城市名称"],
      行政区: s["行政区"] ?? "",
      行业: s["行业"],
      类目: s["类目"],
      月份: s["月份"],
      占期周期: s["占期周期"],
      高潜商户数: uniqueNames.length,
      商户名单: uniqueNames.join("、"),
    };
  });

  return {
    merchants,
    tgiOverall: [...tgiOverall["效果分层"], ...tgiOverall["年费分层"], ...tgiOverall["流量分层"]],
    tgiOverallByDim: tgiOverall,
    catTGI,
    catCategories: Object.keys(catTGI).sort(),
    matched,
    stats: {
      totalMerchants: merchants.length,
      buyers: merchants.filter((r) => r._isBuyer).length,
      easySellCount: easySell.length,
      matchedWithMerchants: matched.filter((r) => r["高潜商户数"] > 0).length,
      totalSellable: matched.length,
    },
  };
}

function generateExcel(result) {
  const wb = XLSX.utils.book_new();
  const ws1 = XLSX.utils.json_to_sheet(result.tgiOverall);
  XLSX.utils.book_append_sheet(wb, ws1, "整体TGI分析");

  const catRows = [];
  for (const [cat, dims] of Object.entries(result.catTGI)) {
    for (const [, rows] of Object.entries(dims)) {
      rows.forEach((r) => catRows.push({ 类目: cat, ...r }));
    }
  }
  const ws2 = XLSX.utils.json_to_sheet(catRows);
  XLSX.utils.book_append_sheet(wb, ws2, "分类目TGI分析");

  const ws3 = XLSX.utils.json_to_sheet(result.matched);
  XLSX.utils.book_append_sheet(wb, ws3, "可售卖档期-高潜商户");

  const buf = XLSX.write(wb, { type: "array", bookType: "xlsx" });
  const blob = new Blob([buf], { type: "application/octet-stream" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = "品广TGI分析结果.xlsx";
  a.click();
  URL.revokeObjectURL(url);
}

function FileUploader({ label, onData, status, required }) {
  const handleFile = useCallback((e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (evt) => {
      const wb = XLSX.read(evt.target.result, { type: "array" });
      const ws = wb.Sheets[wb.SheetNames[0]];
      const data = XLSX.utils.sheet_to_json(ws);
      onData(data, file.name);
    };
    reader.readAsArrayBuffer(file);
  }, [onData]);

  return (
    <div className={`border-2 border-dashed rounded-xl p-6 text-center transition-all ${status === "ok" ? "border-green-400 bg-green-50" : status === "error" ? "border-red-400 bg-red-50" : "border-gray-300 bg-white hover:border-blue-400 hover:bg-blue-50"}`}>
      <p className="text-sm font-medium text-gray-700 mb-2">{label}</p>
      <label className="inline-block cursor-pointer">
        <span className="px-4 py-2 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700 transition-colors">
          选择文件
        </span>
        <input type="file" accept=".xlsx,.xls" className="hidden" onChange={handleFile} />
      </label>
      {status === "ok" && <p className="mt-2 text-green-600 text-xs">列名校验通过</p>}
      {status === "error" && <p className="mt-2 text-red-600 text-xs">列名不匹配，请检查文件</p>}
    </div>
  );
}

function ThresholdConfig({ thresholds, onChange }) {
  const [open, setOpen] = useState(false);
  const update = (key, idx, val) => {
    const next = { ...thresholds };
    if (idx !== null) {
      next[key] = [...next[key]];
      next[key][idx] = Number(val) || 0;
    } else {
      next[key] = Number(val) || 0;
    }
    onChange(next);
  };
  const dims = [
    { key: "ad", label: "效果广告收入阈值" },
    { key: "fee", label: "年费收入阈值" },
    { key: "traffic", label: "流量阈值" },
  ];
  return (
    <div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
      <button onClick={() => setOpen(!open)} className="w-full px-5 py-3 flex items-center justify-between text-left hover:bg-gray-50 transition-colors">
        <span className="font-medium text-gray-800">参数配置</span>
        <svg className={`w-5 h-5 text-gray-500 transition-transform ${open ? "rotate-180" : ""}`} fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" /></svg>
      </button>
      {open && (
        <div className="px-5 pb-5 space-y-4">
          {dims.map(({ key, label }) => (
            <div key={key}>
              <p className="text-xs font-medium text-gray-500 mb-1">{label}</p>
              <div className="flex gap-2">
                {thresholds[key].map((v, i) => (
                  <input key={i} type="number" value={v} onChange={(e) => update(key, i, e.target.value)}
                    className="w-24 px-2 py-1 border border-gray-300 rounded-md text-sm text-center focus:outline-none focus:ring-2 focus:ring-blue-400" />
                ))}
              </div>
            </div>
          ))}
          <div className="flex gap-6">
            <div>
              <p className="text-xs font-medium text-gray-500 mb-1">高潜力TGI阈值</p>
              <input type="number" value={thresholds.highTGI} onChange={(e) => update("highTGI", null, e.target.value)}
                className="w-24 px-2 py-1 border border-gray-300 rounded-md text-sm text-center focus:outline-none focus:ring-2 focus:ring-blue-400" />
            </div>
            <div>
              <p className="text-xs font-medium text-gray-500 mb-1">较容易TGI阈值</p>
              <input type="number" value={thresholds.easyTGI} onChange={(e) => update("easyTGI", null, e.target.value)}
                className="w-24 px-2 py-1 border border-gray-300 rounded-md text-sm text-center focus:outline-none focus:ring-2 focus:ring-blue-400" />
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function StatCards({ stats }) {
  const items = [
    { label: "去重后商户总数", value: stats.totalMerchants.toLocaleString(), color: "text-gray-800" },
    { label: "品广买家数", value: stats.buyers.toLocaleString(), color: "text-blue-600" },
    { label: "易售卖商户(未购买)", value: stats.easySellCount.toLocaleString(), color: "text-orange-600" },
    { label: "可售卖档期总数", value: stats.totalSellable.toLocaleString(), color: "text-gray-600" },
    { label: "匹配到高潜商户的档期", value: stats.matchedWithMerchants.toLocaleString(), color: "text-green-600" },
  ];
  return (
    <div className="grid grid-cols-5 gap-3">
      {items.map((it) => (
        <div key={it.label} className="bg-white rounded-xl shadow-sm border border-gray-200 p-4 text-center">
          <p className={`text-2xl font-bold ${it.color}`}>{it.value}</p>
          <p className="text-xs text-gray-500 mt-1">{it.label}</p>
        </div>
      ))}
    </div>
  );
}

const TGI_COLORS = { "效果": "#4472C4", "年费": "#ED7D31", "流量": "#70AD47" };

function TGIChart({ data }) {
  const dims = ["效果", "年费", "流量"];
  return (
    <div className="grid grid-cols-3 gap-4">
      {dims.map((dim) => {
        const rows = data.filter((r) => r["特征维度"] === dim).sort((a, b) => b.TGI - a.TGI);
        return (
          <div key={dim} className="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
            <p className="text-sm font-semibold text-gray-700 mb-2 text-center">{dim}维度 TGI</p>
            <ResponsiveContainer width="100%" height={220}>
              <BarChart data={rows} layout="vertical" margin={{ left: 10, right: 20, top: 5, bottom: 5 }}>
                <CartesianGrid strokeDasharray="3 3" />
                <XAxis type="number" tick={{ fontSize: 11 }} />
                <YAxis dataKey="分层" type="category" width={90} tick={{ fontSize: 11 }} />
                <Tooltip formatter={(v) => v.toFixed(1)} />
                <ReferenceLine x={100} stroke="#e74c3c" strokeDasharray="4 4" label={{ value: "100", position: "top", fontSize: 10, fill: "#e74c3c" }} />
                <Bar dataKey="TGI" radius={[0, 4, 4, 0]}>
                  {rows.map((r, i) => (
                    <Cell key={i} fill={r.TGI >= 150 ? TGI_COLORS[dim] : r.TGI >= 100 ? "#a8c7e8" : "#d9d9d9"} />
                  ))}
                </Bar>
              </BarChart>
            </ResponsiveContainer>
          </div>
        );
      })}
    </div>
  );
}

function DataTable({ columns, data, highlightFn, maxHeight = "500px" }) {
  return (
    <div className="overflow-auto border border-gray-200 rounded-lg" style={{ maxHeight }}>
      <table className="w-full text-sm">
        <thead className="sticky top-0 z-10">
          <tr>
            {columns.map((col) => (
              <th key={col} className="bg-blue-600 text-white px-3 py-2 text-center whitespace-nowrap font-medium text-xs">{col}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {data.map((row, ri) => {
            const hl = highlightFn?.(row);
            return (
              <tr key={ri} className={`border-b border-gray-100 ${hl === "green" ? "bg-green-50" : hl === "yellow" ? "bg-yellow-50" : ri % 2 === 0 ? "bg-white" : "bg-gray-50"}`}>
                {columns.map((col) => (
                  <td key={col} className="px-3 py-1.5 text-center whitespace-nowrap text-xs">{row[col] ?? ""}</td>
                ))}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

const TABS = ["整体TGI分析", "分类目TGI分析", "可售卖档期-高潜商户匹配"];

export default function App() {
  const [scheduleData, setScheduleData] = useState(null);
  const [merchantData, setMerchantData] = useState(null);
  const [scheduleStatus, setScheduleStatus] = useState(null);
  const [merchantStatus, setMerchantStatus] = useState(null);
  const [scheduleName, setScheduleName] = useState("");
  const [merchantName, setMerchantName] = useState("");
  const [thresholds, setThresholds] = useState(DEFAULT_THRESHOLDS);
  const [result, setResult] = useState(null);
  const [activeTab, setActiveTab] = useState(0);
  const [catFilter, setCatFilter] = useState("");
  const [cityFilter, setCityFilter] = useState("");
  const [catFilterMatch, setCatFilterMatch] = useState("");
  const [processing, setProcessing] = useState(false);

  const handleSchedule = useCallback((data, name) => {
    const cols = Object.keys(data[0] || {});
    const ok = REQUIRED_SCHEDULE_COLS.every((c) => cols.includes(c));
    setScheduleData(ok ? data : null);
    setScheduleStatus(ok ? "ok" : "error");
    setScheduleName(name);
    setResult(null);
  }, []);

  const handleMerchant = useCallback((data, name) => {
    const cols = Object.keys(data[0] || {});
    const ok = REQUIRED_MERCHANT_COLS.every((c) => cols.includes(c));
    setMerchantData(ok ? data : null);
    setMerchantStatus(ok ? "ok" : "error");
    setMerchantName(name);
    setResult(null);
  }, []);

  const canRun = scheduleData && merchantData;

  const handleRun = () => {
    setProcessing(true);
    setTimeout(() => {
      const res = runAnalysis(scheduleData, merchantData, thresholds);
      setResult(res);
      setProcessing(false);
      setCatFilter(res.catCategories[0] || "");
    }, 50);
  };

  const filteredCatTGI = useMemo(() => {
    if (!result || !catFilter || !result.catTGI[catFilter]) return [];
    const dims = result.catTGI[catFilter];
    return [...dims["效果分层"], ...dims["年费分层"], ...dims["流量分层"]];
  }, [result, catFilter]);

  const filteredMatched = useMemo(() => {
    if (!result) return [];
    let data = result.matched;
    if (cityFilter) data = data.filter((r) => r["城市名称"] === cityFilter);
    if (catFilterMatch) data = data.filter((r) => r["类目"] === catFilterMatch);
    return data;
  }, [result, cityFilter, catFilterMatch]);

  const matchedCities = useMemo(() => result ? [...new Set(result.matched.map((r) => r["城市名称"]))].sort() : [], [result]);
  const matchedCategories = useMemo(() => result ? [...new Set(result.matched.map((r) => r["类目"]))].sort() : [], [result]);

  return (
    <div className="min-h-screen bg-gradient-to-br from-slate-50 to-blue-50">
      <div className="max-w-7xl mx-auto px-6 py-8">
        {/* Header */}
        <div className="mb-8">
          <h1 className="text-2xl font-bold text-gray-900">品广 TGI 分析工具</h1>
          <p className="text-sm text-gray-500 mt-1">
            上传「档期查询」和「商户名单」Excel，自动完成去重、TGI特征分析、易售卖商户识别与可售卖档期匹配
          </p>
        </div>

        {/* Upload + Config */}
        <div className="space-y-4 mb-6">
          <div className="grid grid-cols-2 gap-4">
            <FileUploader label={scheduleName ? `品广档期查询：${scheduleName}` : "上传「品广档期查询」Excel"} onData={handleSchedule} status={scheduleStatus} />
            <FileUploader label={merchantName ? `品广商户名单：${merchantName}` : "上传「品广商户名单」Excel"} onData={handleMerchant} status={merchantStatus} />
          </div>
          <ThresholdConfig thresholds={thresholds} onChange={setThresholds} />
          <button
            onClick={handleRun}
            disabled={!canRun || processing}
            className={`w-full py-3 rounded-xl text-white font-semibold text-sm transition-all ${canRun && !processing ? "bg-blue-600 hover:bg-blue-700 shadow-md hover:shadow-lg" : "bg-gray-300 cursor-not-allowed"}`}
          >
            {processing ? "分析中..." : "开始分析"}
          </button>
        </div>

        {/* Results */}
        {result && (
          <div className="space-y-4">
            <StatCards stats={result.stats} />

            {/* Tabs */}
            <div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
              <div className="flex border-b border-gray-200">
                {TABS.map((tab, i) => (
                  <button key={tab} onClick={() => setActiveTab(i)}
                    className={`flex-1 py-3 text-sm font-medium transition-colors ${activeTab === i ? "text-blue-600 border-b-2 border-blue-600 bg-blue-50" : "text-gray-500 hover:text-gray-800 hover:bg-gray-50"}`}>
                    {tab}
                  </button>
                ))}
              </div>

              <div className="p-5">
                {activeTab === 0 && (
                  <div className="space-y-4">
                    <TGIChart data={result.tgiOverall} />
                    <DataTable
                      columns={["特征维度", "分层", "总体数量", "总体占比%", "买家数量", "买家占比%", "TGI"]}
                      data={result.tgiOverall}
                      highlightFn={(r) => r.TGI >= 150 ? "green" : r.TGI >= 100 ? "yellow" : null}
                    />
                  </div>
                )}

                {activeTab === 1 && (
                  <div className="space-y-3">
                    <select value={catFilter} onChange={(e) => setCatFilter(e.target.value)}
                      className="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-400">
                      {result.catCategories.map((c) => <option key={c} value={c}>{c}</option>)}
                    </select>
                    {filteredCatTGI.length > 0 && (
                      <DataTable
                        columns={["特征维度", "分层", "总体数量", "总体占比%", "买家数量", "买家占比%", "TGI"]}
                        data={filteredCatTGI}
                        highlightFn={(r) => r.TGI >= 200 ? "green" : r.TGI >= 100 ? "yellow" : null}
                      />
                    )}
                  </div>
                )}

                {activeTab === 2 && (
                  <div className="space-y-3">
                    <div className="flex gap-3">
                      <select value={cityFilter} onChange={(e) => setCityFilter(e.target.value)}
                        className="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-400">
                        <option value="">全部城市</option>
                        {matchedCities.map((c) => <option key={c} value={c}>{c}</option>)}
                      </select>
                      <select value={catFilterMatch} onChange={(e) => setCatFilterMatch(e.target.value)}
                        className="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-400">
                        <option value="">全部类目</option>
                        {matchedCategories.map((c) => <option key={c} value={c}>{c}</option>)}
                      </select>
                      <span className="self-center text-xs text-gray-500">
                        共 {filteredMatched.length} 条 / 有商户 {filteredMatched.filter((r) => r["高潜商户数"] > 0).length} 条
                      </span>
                    </div>
                    <DataTable
                      columns={["城市等级", "城市名称", "行政区", "行业", "类目", "月份", "占期周期", "高潜商户数", "商户名单"]}
                      data={filteredMatched}
                      highlightFn={(r) => r["高潜商户数"] > 0 ? "green" : null}
                      maxHeight="600px"
                    />
                  </div>
                )}
              </div>
            </div>

            {/* Download */}
            <button
              onClick={() => generateExcel(result)}
              className="w-full py-3 rounded-xl bg-green-600 hover:bg-green-700 text-white font-semibold text-sm shadow-md hover:shadow-lg transition-all"
            >
              下载完整分析结果 Excel
            </button>
          </div>
        )}
      </div>
    </div>
  );
}
