import type {
  ManufacturingItemOptionDto,
  ManufacturingProjectOptionDto,
  WorkOrderInput,
} from "@mrp/shared";
import type { WarehouseLocationOptionDto } from "@mrp/shared/dist/inventory/types.js";
import { useEffect, useMemo, useState } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";

import { useAuth } from "../../auth/AuthProvider";
import { api, ApiError } from "../../lib/api";
import { emptyWorkOrderInput, workOrderStatusOptions } from "./config";

export function WorkOrderFormPage({ mode }: { mode: "create" | "edit" }) {
  const { token } = useAuth();
  const navigate = useNavigate();
  const { workOrderId } = useParams();
  const [form, setForm] = useState<WorkOrderInput>(emptyWorkOrderInput);
  const [itemOptions, setItemOptions] = useState<ManufacturingItemOptionDto[]>([]);
  const [projectOptions, setProjectOptions] = useState<ManufacturingProjectOptionDto[]>([]);
  const [locationOptions, setLocationOptions] = useState<WarehouseLocationOptionDto[]>([]);
  const [itemSearchTerm, setItemSearchTerm] = useState("");
  const [projectSearchTerm, setProjectSearchTerm] = useState("");
  const [itemPickerOpen, setItemPickerOpen] = useState(false);
  const [projectPickerOpen, setProjectPickerOpen] = useState(false);
  const [status, setStatus] = useState(mode === "create" ? "Create a new work order." : "Loading work order...");
  const [isSaving, setIsSaving] = useState(false);

  useEffect(() => {
    if (!token) {
      return;
    }

    api.getManufacturingItemOptions(token).then(setItemOptions).catch(() => setItemOptions([]));
    api.getManufacturingProjectOptions(token).then(setProjectOptions).catch(() => setProjectOptions([]));
    api.getWarehouseLocationOptions(token).then(setLocationOptions).catch(() => setLocationOptions([]));
  }, [token]);

  useEffect(() => {
    if (!token || mode !== "edit" || !workOrderId) {
      return;
    }

    api.getWorkOrder(token, workOrderId)
      .then((workOrder) => {
        setForm({
          itemId: workOrder.itemId,
          projectId: workOrder.projectId,
          status: workOrder.status,
          quantity: workOrder.quantity,
          warehouseId: workOrder.warehouseId,
          locationId: workOrder.locationId,
          dueDate: workOrder.dueDate,
          notes: workOrder.notes,
        });
        setItemSearchTerm(`${workOrder.itemSku} - ${workOrder.itemName}`);
        setProjectSearchTerm(workOrder.projectNumber ? `${workOrder.projectNumber} - ${workOrder.projectName}` : "");
        setStatus("Work order loaded.");
      })
      .catch((error: unknown) => {
        const message = error instanceof ApiError ? error.message : "Unable to load work order.";
        setStatus(message);
      });
  }, [mode, token, workOrderId]);

  const warehouseOptions = useMemo(
    () => [...new Map(locationOptions.map((option) => [option.warehouseId, option])).values()],
    [locationOptions]
  );

  const filteredLocationOptions = useMemo(
    () => locationOptions.filter((option) => option.warehouseId === form.warehouseId),
    [form.warehouseId, locationOptions]
  );

  function updateField<Key extends keyof WorkOrderInput>(key: Key, value: WorkOrderInput[Key]) {
    setForm((current) => ({
      ...current,
      [key]: value,
      ...(key === "warehouseId" ? { locationId: "" } : {}),
    }));
  }

  async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!token) {
      return;
    }

    setIsSaving(true);
    setStatus("Saving work order...");
    try {
      const saved = mode === "create" ? await api.createWorkOrder(token, form) : await api.updateWorkOrder(token, workOrderId ?? "", form);
      navigate(`/manufacturing/work-orders/${saved.id}`);
    } catch (error: unknown) {
      const message = error instanceof ApiError ? error.message : "Unable to save work order.";
      setStatus(message);
      setIsSaving(false);
    }
  }

  return (
    <form className="space-y-6" onSubmit={handleSubmit}>
      <section className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
        <div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
          <div>
            <p className="text-xs font-semibold uppercase tracking-[0.24em] text-muted">Manufacturing Editor</p>
            <h3 className="mt-2 text-xl font-bold text-text">{mode === "create" ? "New Work Order" : "Edit Work Order"}</h3>
            <p className="mt-2 max-w-2xl text-sm text-muted">Create a build record for a manufactured item, assign it to a project when needed, and define where completed output should post.</p>
          </div>
          <Link to={mode === "create" ? "/manufacturing/work-orders" : `/manufacturing/work-orders/${workOrderId}`} className="inline-flex items-center justify-center rounded-2xl border border-line/70 px-2 py-2 text-sm font-semibold text-text">
            Cancel
          </Link>
        </div>
      </section>
      <section className="space-y-4 rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
        <div className="grid gap-3 xl:grid-cols-2">
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Build Item</span>
            <div className="relative">
              <input
                value={itemSearchTerm}
                onChange={(event) => {
                  setItemSearchTerm(event.target.value);
                  updateField("itemId", "");
                  setItemPickerOpen(true);
                }}
                onFocus={() => setItemPickerOpen(true)}
                onBlur={() => {
                  window.setTimeout(() => {
                    setItemPickerOpen(false);
                    const selected = itemOptions.find((option) => option.id === form.itemId);
                    if (selected) {
                      setItemSearchTerm(`${selected.sku} - ${selected.name}`);
                    }
                  }, 120);
                }}
                placeholder="Search manufactured item"
                className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand"
              />
              {itemPickerOpen ? (
                <div className="absolute z-20 mt-2 max-h-64 w-full overflow-y-auto rounded-2xl border border-line/70 bg-surface shadow-panel">
                  {itemOptions
                    .filter((option) => {
                      const query = itemSearchTerm.trim().toLowerCase();
                      if (!query) {
                        return true;
                      }
                      return option.sku.toLowerCase().includes(query) || option.name.toLowerCase().includes(query);
                    })
                    .slice(0, 12)
                    .map((option) => (
                      <button key={option.id} type="button" onMouseDown={(event) => {
                        event.preventDefault();
                        updateField("itemId", option.id);
                        setItemSearchTerm(`${option.sku} - ${option.name}`);
                        setItemPickerOpen(false);
                      }} className="block w-full border-b border-line/50 px-2 py-2 text-left text-sm transition last:border-b-0 hover:bg-page/70">
                        <div className="font-semibold text-text">{option.sku}</div>
                        <div className="mt-1 text-xs text-muted">{option.name} · {option.type}</div>
                      </button>
                    ))}
                </div>
              ) : null}
            </div>
          </label>
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Project</span>
            <div className="relative">
              <input
                value={projectSearchTerm}
                onChange={(event) => {
                  setProjectSearchTerm(event.target.value);
                  updateField("projectId", null);
                  setProjectPickerOpen(true);
                }}
                onFocus={() => setProjectPickerOpen(true)}
                onBlur={() => {
                  window.setTimeout(() => {
                    setProjectPickerOpen(false);
                    const selected = projectOptions.find((option) => option.id === form.projectId);
                    if (selected) {
                      setProjectSearchTerm(`${selected.projectNumber} - ${selected.name}`);
                    }
                  }, 120);
                }}
                placeholder="Search linked project (optional)"
                className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand"
              />
              {projectPickerOpen ? (
                <div className="absolute z-20 mt-2 max-h-64 w-full overflow-y-auto rounded-2xl border border-line/70 bg-surface shadow-panel">
                  <button type="button" onMouseDown={(event) => {
                    event.preventDefault();
                    updateField("projectId", null);
                    setProjectSearchTerm("");
                    setProjectPickerOpen(false);
                  }} className="block w-full border-b border-line/50 px-2 py-2 text-left text-sm transition hover:bg-page/70">
                    <div className="font-semibold text-text">No linked project</div>
                  </button>
                  {projectOptions
                    .filter((option) => {
                      const query = projectSearchTerm.trim().toLowerCase();
                      if (!query) {
                        return true;
                      }
                      return option.projectNumber.toLowerCase().includes(query) || option.name.toLowerCase().includes(query) || option.customerName.toLowerCase().includes(query);
                    })
                    .slice(0, 12)
                    .map((option) => (
                      <button key={option.id} type="button" onMouseDown={(event) => {
                        event.preventDefault();
                        updateField("projectId", option.id);
                        setProjectSearchTerm(`${option.projectNumber} - ${option.name}`);
                        setProjectPickerOpen(false);
                      }} className="block w-full border-b border-line/50 px-2 py-2 text-left text-sm transition last:border-b-0 hover:bg-page/70">
                        <div className="font-semibold text-text">{option.projectNumber}</div>
                        <div className="mt-1 text-xs text-muted">{option.name} · {option.customerName}</div>
                      </button>
                    ))}
                </div>
              ) : null}
            </div>
          </label>
        </div>
        <div className="grid gap-3 xl:grid-cols-4">
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Status</span>
            <select value={form.status} onChange={(event) => updateField("status", event.target.value as WorkOrderInput["status"])} className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand">
              {workOrderStatusOptions.map((option) => <option key={option.value} value={option.value}>{option.label}</option>)}
            </select>
          </label>
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Quantity</span>
            <input type="number" min={1} step={1} value={form.quantity} onChange={(event) => updateField("quantity", Number.parseInt(event.target.value, 10) || 1)} className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand" />
          </label>
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Warehouse</span>
            <select value={form.warehouseId} onChange={(event) => updateField("warehouseId", event.target.value)} className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand">
              <option value="">Select warehouse</option>
              {warehouseOptions.map((option) => <option key={option.warehouseId} value={option.warehouseId}>{option.warehouseCode} - {option.warehouseName}</option>)}
            </select>
          </label>
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Location</span>
            <select value={form.locationId} onChange={(event) => updateField("locationId", event.target.value)} className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand">
              <option value="">Select location</option>
              {filteredLocationOptions.map((option) => <option key={option.locationId} value={option.locationId}>{option.locationCode} - {option.locationName}</option>)}
            </select>
          </label>
        </div>
        <label className="block max-w-sm">
          <span className="mb-2 block text-sm font-semibold text-text">Due date</span>
          <input type="date" value={form.dueDate ? form.dueDate.slice(0, 10) : ""} onChange={(event) => updateField("dueDate", event.target.value ? new Date(event.target.value).toISOString() : null)} className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand" />
        </label>
        <label className="block">
          <span className="mb-2 block text-sm font-semibold text-text">Work instructions / notes</span>
          <textarea value={form.notes} onChange={(event) => updateField("notes", event.target.value)} rows={5} className="w-full rounded-3xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand" />
        </label>
        <div className="flex flex-col gap-3 rounded-2xl border border-line/70 bg-page/70 px-2 py-2 sm:flex-row sm:items-center sm:justify-between">
          <span className="min-w-0 text-sm text-muted">{status}</span>
          <button type="submit" disabled={isSaving} className="rounded-2xl bg-brand px-2 py-2 text-sm font-semibold text-white disabled:cursor-not-allowed disabled:opacity-60">
            {isSaving ? "Saving..." : mode === "create" ? "Create work order" : "Save changes"}
          </button>
        </div>
      </section>
    </form>
  );
}
