"use client";

import { ArrowRightLeft } from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  CONVERT_ERROR_MESSAGES,
  convertUnitValue,
  formatUnitNumber,
  getConvertibleUnits,
  getUnitByCode,
  type UnitDimension,
} from "@/lib/units";
import { cn } from "@/lib/utils";

export type UnitConverterProps = {
  dimension: UnitDimension;
  defaultFromCode?: string;
  defaultToCode?: string;
  defaultValue?: number;
  className?: string;
  showBaseValue?: boolean;
  onChange?: (payload: {
    inputValue: number;
    fromCode: string;
    toCode: string;
    resultValue: number | null;
    baseValue: number | null;
  }) => void;
};

export function UnitConverter({
  dimension,
  defaultFromCode,
  defaultToCode,
  defaultValue = 1,
  className,
  showBaseValue = true,
  onChange,
}: UnitConverterProps) {
  const units = useMemo(() => getConvertibleUnits(dimension), [dimension]);
  const [fromCode, setFromCode] = useState(
    defaultFromCode ?? units[0]?.unitCode ?? ""
  );
  const [toCode, setToCode] = useState(
    defaultToCode ?? units[1]?.unitCode ?? units[0]?.unitCode ?? ""
  );
  const [inputValue, setInputValue] = useState(String(defaultValue));

  const numericValue = Number(inputValue);
  const result = useMemo(() => {
    if (!fromCode || !toCode || inputValue.trim() === "") return null;
    return convertUnitValue(numericValue, fromCode, toCode);
  }, [fromCode, inputValue, numericValue, toCode]);

  const fromUnit = getUnitByCode(fromCode);
  const toUnit = getUnitByCode(toCode);
  const baseUnit = units.find((u) => u.unitCode === fromUnit?.baseUnitCode);

  useEffect(() => {
    if (!onChange) return;
    onChange({
      inputValue: numericValue,
      fromCode,
      toCode,
      resultValue: result?.ok ? result.value : null,
      baseValue: result?.ok ? result.baseValue : null,
    });
  }, [fromCode, numericValue, onChange, result, toCode]);

  return (
    <div className={cn("space-y-3", className)}>
      <div className="grid gap-3 sm:grid-cols-[1fr_auto_1fr] sm:items-end">
        <div className="space-y-2">
          <Label className="text-xs text-muted-foreground">输入值</Label>
          <div className="flex gap-2">
            <Input
              type="number"
              inputMode="decimal"
              value={inputValue}
              onChange={(e) => setInputValue(e.target.value)}
              className="bg-background"
              placeholder="数值"
            />
            <Select value={fromCode} onValueChange={setFromCode}>
              <SelectTrigger className="w-[130px] shrink-0 bg-background">
                <SelectValue placeholder="单位" />
              </SelectTrigger>
              <SelectContent>
                {units.map((u) => (
                  <SelectItem key={u.unitCode} value={u.unitCode}>
                    {u.symbol}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        </div>

        <div className="hidden justify-center pb-2 sm:flex">
          <ArrowRightLeft className="h-4 w-4 text-muted-foreground" />
        </div>

        <div className="space-y-2">
          <Label className="text-xs text-muted-foreground">换算结果</Label>
          <div className="flex gap-2">
            <div
              className={cn(
                "flex h-10 flex-1 items-center rounded-md border border-input bg-muted/40 px-3 text-sm",
                result && !result.ok && "border-destructive/50 text-destructive"
              )}
            >
              {result?.ok
                ? formatUnitNumber(result.value)
                : result && !result.ok
                  ? CONVERT_ERROR_MESSAGES[result.reason]
                  : "—"}
            </div>
            <Select value={toCode} onValueChange={setToCode}>
              <SelectTrigger className="w-[130px] shrink-0 bg-background">
                <SelectValue placeholder="单位" />
              </SelectTrigger>
              <SelectContent>
                {units.map((u) => (
                  <SelectItem key={u.unitCode} value={u.unitCode}>
                    {u.symbol}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        </div>
      </div>

      {showBaseValue && result?.ok && baseUnit && (
        <p className="text-xs text-muted-foreground">
          基准值（{baseUnit.symbol}）：
          <code className="ml-1 rounded bg-muted px-1.5 py-0.5 text-foreground">
            {formatUnitNumber(result.baseValue)}
          </code>
          {fromUnit && toUnit && (
            <span className="ml-2">
              {formatUnitNumber(numericValue)} {fromUnit.symbol} ={" "}
              {formatUnitNumber(result.value)} {toUnit.symbol}
            </span>
          )}
        </p>
      )}
    </div>
  );
}

export type UnitValueInputProps = {
  dimension: UnitDimension;
  value?: number | null;
  unitCode?: string;
  onValueChange?: (value: number | null) => void;
  onUnitChange?: (unitCode: string) => void;
  label?: string;
  placeholder?: string;
  disabled?: boolean;
  className?: string;
};

/** 带单位下拉的数值输入，适合表单场景 */
export function UnitValueInput({
  dimension,
  value,
  unitCode,
  onValueChange,
  onUnitChange,
  label,
  placeholder = "请输入数值",
  disabled,
  className,
}: UnitValueInputProps) {
  const units = useMemo(() => getConvertibleUnits(dimension), [dimension]);
  const [internalUnit, setInternalUnit] = useState(unitCode ?? units[0]?.unitCode ?? "");
  const selectedUnit = unitCode ?? internalUnit;

  return (
    <div className={cn("space-y-2", className)}>
      {label ? <Label>{label}</Label> : null}
      <div className="flex gap-2">
        <Input
          type="number"
          inputMode="decimal"
          value={value ?? ""}
          disabled={disabled}
          placeholder={placeholder}
          className="bg-background"
          onChange={(e) => {
            const raw = e.target.value;
            onValueChange?.(raw === "" ? null : Number(raw));
          }}
        />
        <Select
          value={selectedUnit}
          disabled={disabled}
          onValueChange={(code) => {
            setInternalUnit(code);
            onUnitChange?.(code);
          }}
        >
          <SelectTrigger className="w-[120px] shrink-0 bg-background">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            {units.map((u) => (
              <SelectItem key={u.unitCode} value={u.unitCode}>
                {u.symbol}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>
    </div>
  );
}

export type SeedCountWeightConverterProps = {
  className?: string;
  defaultTkw?: number;
  defaultCount?: number;
};

/** 粒数 ↔ 重量，依赖批次千粒重 TKW */
export function SeedCountWeightConverter({
  className,
  defaultTkw = 25,
  defaultCount = 10000,
}: SeedCountWeightConverterProps) {
  const [tkw, setTkw] = useState(String(defaultTkw));
  const [count, setCount] = useState(String(defaultCount));
  const [weightG, setWeightG] = useState<string | null>(null);
  const [mode, setMode] = useState<"count_to_weight" | "weight_to_count">("count_to_weight");

  const tkwNum = Number(tkw);
  const countNum = Number(count);

  const computed = useMemo(() => {
    if (!Number.isFinite(tkwNum) || tkwNum <= 0) {
      return { error: CONVERT_ERROR_MESSAGES.invalid_tkw as string };
    }
    if (mode === "count_to_weight") {
      if (!Number.isFinite(countNum)) return { error: CONVERT_ERROR_MESSAGES.invalid_value };
      const g = (countNum * tkwNum) / 1000;
      return { g, kg: g / 1000 };
    }
    const w = Number(weightG);
    if (!Number.isFinite(w)) return { error: CONVERT_ERROR_MESSAGES.invalid_value };
    const seeds = (w * 1000) / tkwNum;
    return { seeds };
  }, [countNum, mode, tkwNum, weightG]);

  return (
    <div className={cn("space-y-4", className)}>
      <div className="flex flex-wrap gap-2">
        <Badge
          variant={mode === "count_to_weight" ? "default" : "outline"}
          className="cursor-pointer"
          onClick={() => setMode("count_to_weight")}
        >
          粒 → 重量
        </Badge>
        <Badge
          variant={mode === "weight_to_count" ? "default" : "outline"}
          className="cursor-pointer"
          onClick={() => setMode("weight_to_count")}
        >
          重量 → 粒
        </Badge>
      </div>

      <div className="grid gap-3 sm:grid-cols-3">
        <div className="space-y-2">
          <Label>千粒重 TKW (g/1000粒)</Label>
          <Input
            type="number"
            value={tkw}
            onChange={(e) => setTkw(e.target.value)}
            className="bg-background"
          />
        </div>

        {mode === "count_to_weight" ? (
          <div className="space-y-2">
            <Label>粒数</Label>
            <Input
              type="number"
              value={count}
              onChange={(e) => setCount(e.target.value)}
              className="bg-background"
            />
          </div>
        ) : (
          <div className="space-y-2">
            <Label>重量 (g)</Label>
            <Input
              type="number"
              value={weightG ?? ""}
              onChange={(e) => setWeightG(e.target.value)}
              className="bg-background"
            />
          </div>
        )}

        <div className="space-y-2">
          <Label>结果</Label>
          <div className="flex h-10 items-center rounded-md border border-input bg-muted/40 px-3 text-sm">
            {"error" in computed ? (
              <span className="text-destructive">{computed.error}</span>
            ) : mode === "count_to_weight" ? (
              <>
                {formatUnitNumber(computed.g!)} g（
                {formatUnitNumber(computed.kg!, 4)} kg）
              </>
            ) : (
              <>{formatUnitNumber(computed.seeds!, 0)} 粒</>
            )}
          </div>
        </div>
      </div>

      <p className="text-xs text-muted-foreground">
        公式：重量(g) = 粒数 × 千粒重 / 1000；无 TKW 时粒与 g/kg 不可自动换算。
      </p>
    </div>
  );
}

export type PackageSpecConverterProps = {
  className?: string;
};

/** 包装单位：数量 × 规格 → 总量 */
export function PackageSpecConverter({ className }: PackageSpecConverterProps) {
  const [packageCount, setPackageCount] = useState("10");
  const [specAmount, setSpecAmount] = useState("25");
  const [specUnit, setSpecUnit] = useState("KG");

  const massUnits = getConvertibleUnits("mass");
  const result = useMemo(() => {
    const n = Number(packageCount);
    const s = Number(specAmount);
    if (!Number.isFinite(n) || !Number.isFinite(s)) return null;
    const total = n * s;
    return convertUnitValue(total, specUnit, specUnit);
  }, [packageCount, specAmount, specUnit]);

  const displayKg = useMemo(() => {
    const n = Number(packageCount);
    const s = Number(specAmount);
    if (!Number.isFinite(n) || !Number.isFinite(s)) return null;
    return convertUnitValue(n * s, specUnit, "KG");
  }, [packageCount, specAmount, specUnit]);

  return (
    <div className={cn("space-y-3", className)}>
      <div className="grid gap-3 sm:grid-cols-[1fr_auto_1fr_auto] sm:items-end">
        <div className="space-y-2">
          <Label>包装数量</Label>
          <Input
            type="number"
            value={packageCount}
            onChange={(e) => setPackageCount(e.target.value)}
            className="bg-background"
          />
        </div>
        <span className="hidden pb-2 text-muted-foreground sm:block">×</span>
        <div className="space-y-2">
          <Label>每袋/管/盒规格</Label>
          <div className="flex gap-2">
            <Input
              type="number"
              value={specAmount}
              onChange={(e) => setSpecAmount(e.target.value)}
              className="bg-background"
            />
            <Select value={specUnit} onValueChange={setSpecUnit}>
              <SelectTrigger className="w-[90px] shrink-0 bg-background">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {massUnits.map((u) => (
                  <SelectItem key={u.unitCode} value={u.unitCode}>
                    {u.symbol}
                  </SelectItem>
                ))}
                <SelectItem value="SEED">粒</SelectItem>
              </SelectContent>
            </Select>
          </div>
        </div>
        <div className="space-y-2">
          <Label>合计</Label>
          <div className="flex h-10 items-center rounded-md border border-input bg-muted/40 px-3 text-sm">
            {result?.ok ? (
              <>
                {formatUnitNumber(result.value)} {getUnitByCode(specUnit)?.symbol}
                {displayKg?.ok && specUnit !== "KG" && (
                  <span className="ml-2 text-muted-foreground">
                    ≈ {formatUnitNumber(displayKg.value)} kg
                  </span>
                )}
              </>
            ) : (
              "—"
            )}
          </div>
        </div>
      </div>
      <p className="text-xs text-muted-foreground">
        袋/管/盒/包/瓶不可直接互转，必须维护规格（如 10 袋 × 25 kg/袋 = 250 kg）。
      </p>
    </div>
  );
}
