import { useEffect, useMemo, useRef, useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import { Alert, App, Button, Card, DatePicker, Input, InputNumber, Select, Table, Tag } from "antd";
import dayjs, { type Dayjs } from "dayjs";
import { ReportModal } from "./ReportView";
import {
  conclusionText,
  defaultCalibration,
  formatNumber,
  formatPercent,
  materialOptions,
  materialTiers,
  validityText,
  verdictDisplay,
  type CalculationResult,
  type LimitTier,
  type MaterialType,
  type SampleInput
} from "./types";

type MeasurementRow = {
  key: number;
  ra: number | null;
  th: number | null;
  k: number | null;
};

type CalibrationRow = { key: string; name: string } & (typeof defaultCalibration)["ra"];

type FocusableInput = { focus: () => void };

type Props = {
  initialInput?: SampleInput;
  onSaved: () => void;
};

function rowsFromInput(input?: SampleInput): MeasurementRow[] {
  if (!input) return [{ key: 1, ra: 100, th: 110, k: 560 }];
  const n = input.ra.measured_values.length;
  return Array.from({ length: n }, (_, i) => ({
    key: i + 1,
    ra: input.ra.measured_values[i] ?? null,
    th: input.th.measured_values[i] ?? null,
    k: input.k.measured_values[i] ?? null
  }));
}

function CalculatorPanel({ initialInput, onSaved }: Props) {
  const { message } = App.useApp();
  const [rows, setRows] = useState<MeasurementRow[]>(() => rowsFromInput(initialInput));
  const [materialType, setMaterialType] = useState<MaterialType>(
    initialInput?.material_type ?? "BuildingMainBody"
  );
  const [sampleId, setSampleId] = useState<string>(initialInput?.sample_id ?? "");
  const [calcDate, setCalcDate] = useState<Dayjs | null>(
    initialInput?.calculation_date ? dayjs(initialInput.calculation_date) : dayjs()
  );
  const [result, setResult] = useState<CalculationResult | null>(null);
  const [lastInput, setLastInput] = useState<SampleInput | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [reportOpen, setReportOpen] = useState(false);
  const firstCellRefs = useRef<Record<number, FocusableInput | null>>({});

  const dataSource = useMemo(() => rows, [rows]);

  const updateRow = (key: number, field: keyof Omit<MeasurementRow, "key">, value: number | null) => {
    setRows((current) => current.map((row) => (row.key === key ? { ...row, [field]: value } : row)));
  };

  const addRow = () => {
    const key = Date.now();
    setRows((current) => [...current, { key, ra: null, th: null, k: null }]);
    window.setTimeout(() => firstCellRefs.current[key]?.focus(), 0);
  };

  const removeRow = (key: number) => {
    setRows((current) => current.filter((row) => row.key !== key));
  };

  const buildInput = (): SampleInput => {
    const toValues = (field: keyof Omit<MeasurementRow, "key">) =>
      rows.map((row) => row[field]).filter((value): value is number => typeof value === "number");

    return {
      ra: { measured_values: toValues("ra"), calibration: defaultCalibration.ra },
      th: { measured_values: toValues("th"), calibration: defaultCalibration.th },
      k: { measured_values: toValues("k"), calibration: defaultCalibration.k },
      material_type: materialType,
      sample_id: sampleId.trim() ? sampleId.trim() : null,
      calculation_date: calcDate ? calcDate.format("YYYY-MM-DD") : null
    };
  };

  const calculate = async () => {
    setLoading(true);
    setError(null);
    const input = buildInput();
    try {
      const response = await invoke<CalculationResult>("calculate", { input });
      setResult(response);
      setLastInput(input);
    } catch (err) {
      setResult(null);
      setLastInput(null);
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setLoading(false);
    }
  };

  // 复算：带入历史记录后自动计算一次。
  useEffect(() => {
    if (initialInput) void calculate();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const save = async () => {
    if (!result || !lastInput) return;
    setSaving(true);
    try {
      await invoke<number>("save_record", {
        args: { input: lastInput, result, created_at: new Date().toISOString() }
      });
      message.success("已保存到历史");
      onSaved();
    } catch (err) {
      message.error(`保存失败：${String(err)}`);
    } finally {
      setSaving(false);
    }
  };

  const tiers = materialTiers[materialType];

  return (
    <section className="workspace">
      <div className="content-grid">
        <Card title="重复测量值" className="panel measurements-panel">
          <div className="measurement-table">
            <Table<MeasurementRow>
              pagination={false}
              dataSource={dataSource}
              rowKey="key"
              size="small"
              columns={[
                { title: "序号", key: "index", width: 56, align: "center", render: (_, _row, index) => index + 1 },
                {
                  title: "Ra-226",
                  dataIndex: "ra",
                  render: (_, row) => (
                    <InputNumber
                      ref={(instance) => {
                        firstCellRefs.current[row.key] = instance;
                      }}
                      value={row.ra}
                      min={0}
                      onChange={(value) => updateRow(row.key, "ra", value)}
                    />
                  )
                },
                {
                  title: "Th-232",
                  dataIndex: "th",
                  render: (_, row) => (
                    <InputNumber value={row.th} min={0} onChange={(value) => updateRow(row.key, "th", value)} />
                  )
                },
                {
                  title: "K-40",
                  dataIndex: "k",
                  render: (_, row) => (
                    <InputNumber value={row.k} min={0} onChange={(value) => updateRow(row.key, "k", value)} />
                  )
                },
                {
                  title: "",
                  key: "action",
                  width: 88,
                  render: (_, row) => (
                    <Button danger size="small" disabled={rows.length <= 1} onClick={() => removeRow(row.key)}>
                      删除
                    </Button>
                  )
                }
              ]}
            />
          </div>
          <div className="measurement-actions">
            <Button size="small" block onClick={addRow}>
              添加次数
            </Button>
            <Button type="primary" size="small" block loading={loading} onClick={() => void calculate()}>
              计算
            </Button>
            <Button size="small" block loading={saving} disabled={!result} onClick={() => void save()}>
              保存到历史
            </Button>
            <Button size="small" block disabled={!result} onClick={() => setReportOpen(true)}>
              预览 / 导出 PDF
            </Button>
          </div>
        </Card>

        <Card title="样品信息 / 校准参数 / 限值" className="panel compact-panel">
          <div className="sample-form">
            <div className="sample-field">
              <span className="sample-label">样品编号</span>
              <Input value={sampleId} placeholder="可选" onChange={(event) => setSampleId(event.target.value)} />
            </div>
            <div className="sample-field">
              <span className="sample-label">计算日期</span>
              <DatePicker value={calcDate} onChange={setCalcDate} style={{ width: "100%" }} />
            </div>
            <div className="sample-field">
              <span className="sample-label">材料类型</span>
              <Select<MaterialType>
                value={materialType}
                options={materialOptions}
                onChange={setMaterialType}
                style={{ width: "100%" }}
              />
            </div>
          </div>

          <div className="sample-tables">
            <Table<CalibrationRow>
              className="calibration-table"
              pagination={false}
              size="small"
              rowKey="key"
              dataSource={[
                { key: "ra", name: "Ra", ...defaultCalibration.ra },
                { key: "th", name: "Th", ...defaultCalibration.th },
                { key: "k", name: "K", ...defaultCalibration.k }
              ]}
              columns={[
                { title: "核素", dataIndex: "name", align: "center" },
                { title: "a", dataIndex: "factor", align: "center" },
                {
                  title: "U",
                  dataIndex: "expanded_uncertainty_percent",
                  align: "center",
                  render: (value: number) => `${value}%`
                },
                { title: "k", dataIndex: "coverage_factor", align: "center" }
              ]}
            />

            <Table<LimitTier>
              className="limit-table"
              pagination={false}
              size="small"
              rowKey="label"
              dataSource={tiers}
              columns={[
                { title: "级别", dataIndex: "label", align: "center" },
                { title: "IRa 限", dataIndex: "ira", align: "center", render: (value: number | null) => value ?? "—" },
                { title: "Ir 限", dataIndex: "ir", align: "center", render: (value: number | null) => value ?? "—" }
              ]}
            />
          </div>
        </Card>
      </div>

      {error ? <Alert type="error" message={error} showIcon /> : null}

      <div className="results-area">
        {result && lastInput ? (
          <>
            <Card
              title="分析判定"
              className="panel analysis-panel"
              extra={
                <span className="analysis-meta">
                  {sampleId.trim() || "未编号"} · {calcDate ? calcDate.format("YYYY-MM-DD") : "无日期"} ·{" "}
                  {result.measurement_count} 次测量
                </span>
              }
            >
              <div className="analysis-grid">
                <div className="result-tile conclusion-tile">
                  <span>有效性</span>
                  <Tag color={validityText[result.analysis.validity].color}>
                    {validityText[result.analysis.validity].text}
                  </Tag>
                  <small>总比活度 {formatNumber(result.analysis.total_calibrated_activity, 1)} Bq/kg（阈值 37）</small>
                </div>
                <div className="result-tile conclusion-tile">
                  <span>最终判定</span>
                  <Tag color={verdictDisplay(result.analysis.verdict).color}>
                    {verdictDisplay(result.analysis.verdict).text}
                  </Tag>
                  {result.analysis.verdict === "NeedMoreMeasurements" ? <small>真值区间跨越极限值</small> : null}
                </div>
                <div className="result-tile">
                  <span>IRa 真值区间</span>
                  <strong>{formatNumber(result.ira.value)}</strong>
                  <small>
                    [{formatNumber(result.ira.p2_5)}, {formatNumber(result.ira.p97_5)}] · k=2{" "}
                    {formatNumber(result.ira.relative_expanded_uncertainty_percent, 2)}%
                  </small>
                </div>
                <div className="result-tile">
                  <span>Ir 真值区间</span>
                  <strong>{formatNumber(result.ir.value)}</strong>
                  <small>
                    [{formatNumber(result.ir.p2_5)}, {formatNumber(result.ir.p97_5)}] · k=2{" "}
                    {formatNumber(result.ir.relative_expanded_uncertainty_percent, 2)}%
                  </small>
                </div>
              </div>
            </Card>

            <div className="results-row">
              <Card title="计算结果（GUM 法）" className="panel">
                <div className="result-grid">
                  <ResultTile title="IRa" value={result.ira.value} uncertainty={result.ira.relative_uncertainty_percent} />
                  <ResultTile title="Ir" value={result.ir.value} uncertainty={result.ir.relative_uncertainty_percent} />
                  <div className="result-tile conclusion-tile">
                    <span>不确定度判定</span>
                    <Tag color={result.conclusion === "Ok" ? "success" : "warning"}>
                      {conclusionText[result.conclusion]}
                    </Tag>
                  </div>
                </div>
                <Table<{ name: string } & CalculationResult["ra"]>
                  pagination={false}
                  rowKey="name"
                  size="small"
                  dataSource={[
                    { name: "Ra-226", ...result.ra },
                    { name: "Th-232", ...result.th },
                    { name: "K-40", ...result.k }
                  ]}
                  columns={[
                    { title: "核素", dataIndex: "name" },
                    { title: "均值", dataIndex: "mean_measured", render: (value: number) => formatNumber(value) },
                    { title: "校准活度", dataIndex: "mean_calibrated", render: (value: number) => formatNumber(value) },
                    { title: "A 类", dataIndex: "type_a_uncertainty", render: (value: number) => formatNumber(value) },
                    { title: "B 类相对", dataIndex: "type_b_relative", render: (value) => formatNumber(value * 100, 3) + "%" },
                    { title: "合成", dataIndex: "combined_uncertainty", render: (value: number) => formatNumber(value) }
                  ]}
                />
              </Card>

              <Card title={`蒙特卡洛仿真（MCM，${result.mcm.iterations} 次）`} className="panel">
                <div className="result-grid">
                  <div className="result-tile">
                    <span>综合合格概率</span>
                    <strong>{formatPercent(result.mcm.overall_pass_probability)}</strong>
                    <small>IRa 与 Ir 同时合格</small>
                  </div>
                  <div className="result-tile">
                    <span>不符合概率</span>
                    <strong>{formatPercent(result.mcm.overall_fail_probability)}</strong>
                    <small>95% 置信概率下</small>
                  </div>
                  <div className="result-tile conclusion-tile">
                    <span>仿真判定</span>
                    <Tag color={result.mcm.overall_fail_probability < 0.05 ? "success" : "warning"}>
                      {result.mcm.overall_fail_probability < 0.05 ? "合格（不符合概率<5%）" : "不合格风险"}
                    </Tag>
                  </div>
                </div>
                <Table<{ name: string } & CalculationResult["mcm"]["ira"]>
                  pagination={false}
                  rowKey="name"
                  size="small"
                  dataSource={[
                    { name: "IRa", ...result.mcm.ira },
                    { name: "Ir", ...result.mcm.ir }
                  ]}
                  columns={[
                    { title: "指数", dataIndex: "name" },
                    { title: "平均值", dataIndex: "mean", render: (value: number) => formatNumber(value) },
                    { title: "标准偏差", dataIndex: "std_dev", render: (value: number) => formatNumber(value) },
                    { title: "P2.5", dataIndex: "p2_5", render: (value: number) => formatNumber(value) },
                    { title: "P97.5", dataIndex: "p97_5", render: (value: number) => formatNumber(value) },
                    { title: "标准值", dataIndex: "standard_value", render: (value: number) => formatNumber(value, 2) },
                    {
                      title: "合格概率",
                      dataIndex: "pass_probability",
                      render: (value: number) => <Tag color={value >= 0.95 ? "success" : "warning"}>{formatPercent(value)}</Tag>
                    }
                  ]}
                />
              </Card>
            </div>
          </>
        ) : (
          <div className="results-placeholder">请计算后查看结果</div>
        )}
      </div>

      <ReportModal
        open={reportOpen}
        onClose={() => setReportOpen(false)}
        detail={result && lastInput ? { input: lastInput, result } : null}
      />
    </section>
  );
}

function ResultTile(props: { title: string; value: number; uncertainty: number }) {
  return (
    <div className="result-tile">
      <span>{props.title}</span>
      <strong>{formatNumber(props.value)}</strong>
      <small>相对不确定度 {formatNumber(props.uncertainty, 2)}%</small>
    </div>
  );
}

export { CalculatorPanel };
