import { useEffect, useState, type ReactNode } from "react";
import type { DynamicField, PrRow } from "../api/form";
import type { PurchaseFormSnapshot } from "../types/purchasePayload";
import { buildPrLines, fetchFormSchema } from "../api/form";
import { Icon } from "./Icon";

const FALLBACK_INTERVALS = [
  "Daily",
  "Weekly",
  "Monthly",
  "Bi-Monthly",
  "Quarterly",
  "Bi-Annual",
  "Annual",
];

/** Aligns label baselines for side-by-side fields; controls share one height. */
const CTRL =
  "h-11 w-full box-border rounded border border-outline-variant bg-surface-container-low px-2.5 text-body-sm";
const LABEL_CLASS =
  "min-h-[3rem] flex items-end text-[11px] font-bold text-secondary leading-snug";

/** Unit suffix for number fields when schema omits `unit` (cached / legacy schemas). */
function inferredNumberUnit(label: string): string | undefined {
  const L = label.toLowerCase();
  if (/\b(kilograms?|kg)\b/i.test(label)) return "kg";
  if (/\b(weight|mass|load capacity|weight capacity)\b/.test(L)) return "kg";
  if (/\b(pounds?|lbs?)\b/i.test(L)) return "lb";
  if (
    /\b(millimeters?|millimetres?|mm)\b/i.test(L) ||
    /\b(seat depth|seat width|seat height)\b/.test(L)
  )
    return "mm";
  if (/\b(centimeters?|centimetres?|cm)\b/i.test(L)) return "cm";
  if (/\b(inches|inch)\b|\bin\.\b/i.test(L)) return "in";
  if (/\b(meters?|metres?)\b/i.test(L)) return "m";
  if (/\bpercent\b|%/i.test(L)) return "%";
  return undefined;
}

function unitBadgeText(unit: string): string {
  const u = unit.trim();
  if (!u) return u;
  // Short measurement tokens: show uppercase (kg → KG); leave longer symbols alone.
  return u.length <= 6 ? u.toUpperCase() : u;
}

type Props = {
  commodityCode: number;
  intro: string;
  catalogPath?: string;
  codeSummary?: string;
  onCommitPurchase: (payload: {
    rows: PrRow[];
    snapshot: PurchaseFormSnapshot;
  }) => void;
  onAddNew: () => void;
};

function FieldCell({
  label,
  children,
  className = "col-span-12 md:col-span-6",
}: {
  label: string;
  children: ReactNode;
  className?: string;
}) {
  return (
    <div
      className={`flex flex-col gap-1.5 ${className}`}
    >
      <span className={LABEL_CLASS}>{label}</span>
      {children}
    </div>
  );
}

export function ProcurementFormBlock({
  commodityCode,
  intro,
  catalogPath,
  codeSummary,
  onCommitPurchase,
  onAddNew,
}: Props) {
  const [schemaLoading, setSchemaLoading] = useState(true);
  const [schemaError, setSchemaError] = useState<string | null>(null);
  const [fields, setFields] = useState<DynamicField[]>([]);
  const [intervalChoices, setIntervalChoices] = useState<string[]>(FALLBACK_INTERVALS);

  const [deliveries, setDeliveries] = useState(4);
  const [interval, setInterval] = useState("Quarterly");
  const [year, setYear] = useState(2026);
  const [otherSpec, setOtherSpec] = useState("");
  const [dynamicValues, setDynamicValues] = useState<Record<string, string>>({});

  const [confirmBusy, setConfirmBusy] = useState(false);
  const [buildError, setBuildError] = useState<string | null>(null);
  const [justAdded, setJustAdded] = useState(false);
  /** Enables "Add new" only after this block has successfully committed lines to the PR table. */
  const [hasCommittedLines, setHasCommittedLines] = useState(false);

  useEffect(() => {
    if (!intervalChoices.length) return;
    if (!intervalChoices.includes(interval)) {
      setInterval(intervalChoices[0] ?? "Quarterly");
    }
  }, [intervalChoices, interval]);

  useEffect(() => {
    let cancelled = false;
    setSchemaLoading(true);
    setSchemaError(null);
    fetchFormSchema(commodityCode)
      .then((s) => {
        if (cancelled) return;
        if (s.error) setSchemaError(s.error);
        setFields(s.fields ?? []);
        if (s.interval_options?.length) setIntervalChoices(s.interval_options);
        const init: Record<string, string> = {};
        for (const f of s.fields ?? []) init[f.id] = "";
        setDynamicValues(init);
      })
      .catch((e) =>
        setSchemaError(e instanceof Error ? e.message : String(e))
      )
      .finally(() => {
        if (!cancelled) setSchemaLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [commodityCode]);

  const setDyn = (id: string, v: string) => {
    setDynamicValues((prev) => ({ ...prev, [id]: v }));
  };

  const renderDynamicField = (f: DynamicField) => {
    const v = dynamicValues[f.id] ?? "";

    if (f.type === "select" && f.options?.length) {
      return (
        <FieldCell key={f.id} label={f.label}>
          <select
            className={`${CTRL} font-semibold focus:border-primary focus:ring-1 focus:ring-primary`}
            value={v}
            onChange={(e) => setDyn(f.id, e.target.value)}
          >
            <option value="">Select…</option>
            {f.options.map((o) => (
              <option key={o} value={o}>
                {o}
              </option>
            ))}
          </select>
        </FieldCell>
      );
    }

    if (f.type === "chips" && f.options?.length) {
      return (
        <FieldCell key={f.id} label={f.label} className="col-span-12">
          <div className="flex min-h-11 flex-wrap items-center gap-2">
            {f.options.map((o) => (
              <button
                key={o}
                type="button"
                onClick={() => setDyn(f.id, o)}
                className={`min-h-11 rounded px-3 py-2 text-xs font-semibold transition-colors ${
                  v === o
                    ? "bg-primary text-on-primary"
                    : "border border-outline-variant bg-surface-container-low text-secondary hover:bg-surface-container-high"
                }`}
              >
                {o}
              </button>
            ))}
          </div>
        </FieldCell>
      );
    }

    if (f.type === "number") {
      const unit = (f.unit?.trim() || inferredNumberUnit(f.label)) ?? "";
      return (
        <FieldCell key={f.id} label={f.label}>
          <div className="flex min-h-11 items-stretch gap-2">
            <input
              type="number"
              className={`${CTRL} min-w-0 flex-1 font-bold`}
              value={v}
              onChange={(e) => setDyn(f.id, e.target.value)}
              aria-describedby={unit ? `${f.id}-unit-hint` : undefined}
            />
            {unit ? (
              <>
                <span id={`${f.id}-unit-hint`} className="sr-only">
                  Enter value in {unitBadgeText(unit)}
                </span>
                <span
                  className="flex shrink-0 items-center rounded border border-outline-variant bg-surface-container-high px-3 text-xs font-bold uppercase tracking-wide text-secondary"
                  aria-hidden
                >
                  {unitBadgeText(unit)}
                </span>
              </>
            ) : null}
          </div>
        </FieldCell>
      );
    }

    if (f.type === "textarea") {
      return (
        <FieldCell
          key={f.id}
          label={f.label}
          className="col-span-12"
        >
          <textarea
            className="min-h-[5.5rem] w-full box-border rounded border border-outline-variant bg-surface-container-low p-2.5 text-body-sm font-semibold"
            value={v}
            onChange={(e) => setDyn(f.id, e.target.value)}
          />
        </FieldCell>
      );
    }

    return (
      <FieldCell key={f.id} label={f.label}>
        <input
          type="text"
          className={`${CTRL} font-semibold`}
          value={v}
          onChange={(e) => setDyn(f.id, e.target.value)}
        />
      </FieldCell>
    );
  };

  const onConfirm = async () => {
    setBuildError(null);
    setJustAdded(false);
    setConfirmBusy(true);
    try {
      const nums: Record<string, string | number> = { ...dynamicValues };
      for (const f of fields) {
        if (f.type === "number" && nums[f.id] !== "") {
          const n = Number(nums[f.id]);
          nums[f.id] = Number.isFinite(n) ? n : nums[f.id];
        }
      }
      const { rows } = await buildPrLines({
        commodity_code: commodityCode,
        dynamic_values: nums,
        deliveries,
        interval,
        other_spec: otherSpec,
        year,
      });
      if (!rows?.length) {
        setBuildError("No line items were generated. Check deliveries and try again.");
        return;
      }

      const snapshot: PurchaseFormSnapshot = {
        commodityCode,
        intro,
        catalogPath,
        codeSummary,
        schedule: {
          numberOfDeliveries: deliveries,
          intervalOfDeliveries: interval,
          yearForDeliverySchedule: year,
        },
        fields: fields.map((f) => {
          const raw = nums[f.id];
          const answer: string | number =
            raw === "" || raw === undefined
              ? ""
              : typeof raw === "number"
                ? raw
                : String(raw);
          const u = f.type === "number" ? f.unit?.trim() || inferredNumberUnit(f.label) : undefined;
          return {
            id: f.id,
            label: f.label,
            type: f.type,
            answer,
            ...(u ? { unit: u } : {}),
          };
        }),
        otherSpecification: otherSpec,
      };

      onCommitPurchase({ rows, snapshot });
      setHasCommittedLines(true);
      setJustAdded(true);
      window.setTimeout(() => setJustAdded(false), 5000);
    } catch (e) {
      setBuildError(e instanceof Error ? e.message : String(e));
    } finally {
      setConfirmBusy(false);
    }
  };

  return (
    <div className="flex justify-start">
      <div className="flex items-start gap-3 w-full">
        <div className="w-8 h-8 rounded-full bg-secondary-container flex items-center justify-center shrink-0">
          <Icon
            name="smart_toy"
            className="text-on-secondary-container text-sm"
          />
        </div>
        <div className="min-w-0 flex-1">
          <div className="bg-surface-container-low p-6 rounded-2xl border border-outline-variant">
            <p className="font-body-md text-body-md text-primary mb-4">{intro}</p>
            {(catalogPath || codeSummary) && (
              <div className="mb-6 rounded-xl border border-outline-variant bg-surface-container-high/80 px-4 py-3">
                {codeSummary ? (
                  <p className="font-data-mono text-data-mono text-xs font-semibold text-primary break-all">
                    {codeSummary}
                  </p>
                ) : null}
                {catalogPath ? (
                  <p className="mt-2 font-body-sm text-body-sm text-secondary break-words">
                    {catalogPath}
                  </p>
                ) : null}
              </div>
            )}

            {schemaLoading ? (
              <p className="font-body-sm text-secondary mb-4">
                Loading catalogue-specific questions…
              </p>
            ) : null}
            {schemaError ? (
              <p className="font-body-sm text-error mb-4">{schemaError}</p>
            ) : null}

            <div className="bg-white rounded-xl border border-outline-variant overflow-hidden mb-6">
              <div className="bg-surface-container-high px-4 py-2 border-b border-outline-variant">
                <span className="font-label-caps text-[10px] text-secondary uppercase font-bold">
                  Line Item Details
                </span>
              </div>
              <div className="grid grid-cols-12 gap-x-6 gap-y-5 p-4">
                <FieldCell label="Number of deliveries" className="col-span-12 md:col-span-4">
                  <input
                    type="number"
                    min={1}
                    max={52}
                    className={`${CTRL} font-bold`}
                    value={deliveries}
                    onChange={(e) =>
                      setDeliveries(Math.max(1, Number(e.target.value) || 1))
                    }
                  />
                </FieldCell>
                <FieldCell label="Interval of deliveries" className="col-span-12 md:col-span-4">
                  <select
                    className={`${CTRL} font-semibold focus:border-primary focus:ring-1 focus:ring-primary`}
                    value={interval}
                    onChange={(e) => setInterval(e.target.value)}
                  >
                    {intervalChoices.map((opt) => (
                      <option key={opt} value={opt}>
                        {opt}
                      </option>
                    ))}
                  </select>
                </FieldCell>
                <FieldCell
                  label="Year (for delivery schedule)"
                  className="col-span-12 md:col-span-4"
                >
                  <input
                    type="number"
                    className={`${CTRL} font-bold`}
                    value={year}
                    onChange={(e) =>
                      setYear(Number(e.target.value) || new Date().getFullYear())
                    }
                  />
                </FieldCell>

                {fields.map((f) => renderDynamicField(f))}

                <FieldCell label="Other specification (free text)" className="col-span-12">
                  <textarea
                    className="min-h-[5.5rem] w-full box-border rounded border border-outline-variant bg-surface-container-low p-2.5 text-body-sm font-semibold"
                    placeholder="e.g. Age 18+"
                    value={otherSpec}
                    onChange={(e) => setOtherSpec(e.target.value)}
                  />
                </FieldCell>

                <div className="col-span-12 flex flex-col gap-2 rounded-lg border border-[#10B981]/20 bg-[#10B981]/10 p-3 sm:flex-row sm:items-center sm:justify-between">
                  <div className="flex items-center gap-2">
                    <Icon name="check_circle" className="text-[#10B981]" />
                    <span className="text-body-sm font-semibold text-[#10B981]">
                      Budget Impact: Within Allocation
                    </span>
                  </div>
                  <span className="text-xs font-bold text-[#10B981]">
                    AVAILABLE
                  </span>
                </div>
              </div>
            </div>

            {buildError ? (
              <p className="mb-3 text-body-sm text-error">{buildError}</p>
            ) : null}
            {justAdded ? (
              <p className="mb-3 text-body-sm font-semibold text-[#10B981]">
                Line items added to the table on the right.
              </p>
            ) : null}

            <div className="border-t border-outline-variant pt-4">
              <div className="flex flex-col gap-3 sm:flex-row">
                <button
                  type="button"
                  disabled={confirmBusy || schemaLoading}
                  onClick={onConfirm}
                  className="flex flex-1 items-center justify-center gap-2 rounded-xl bg-primary px-6 py-3 text-body-sm font-bold text-white shadow-sm transition-all hover:opacity-90 active:scale-[0.98] disabled:opacity-50"
                >
                  {confirmBusy ? "Building…" : "Confirm Selection"}
                  <Icon name="task_alt" className="text-sm" />
                </button>
                <button
                  type="button"
                  disabled={!hasCommittedLines || confirmBusy}
                  title={
                    hasCommittedLines
                      ? "Add another catalogue line to this request"
                      : "Confirm selection first to add another line"
                  }
                  onClick={onAddNew}
                  className="flex flex-1 items-center justify-center gap-2 rounded-xl border border-outline-variant bg-white px-6 py-3 text-body-sm font-semibold text-secondary transition-colors hover:bg-surface-container-high disabled:cursor-not-allowed disabled:opacity-45"
                >
                  Add new
                  <Icon name="add" className="text-sm" />
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
