import type {
  ProjectCustomerOptionDto,
  ProjectDocumentOptionDto,
  ProjectInput,
  ProjectOwnerOptionDto,
  ProjectShipmentOptionDto,
} from "@mrp/shared/dist/projects/types.js";
import { useEffect, useState } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";

import { useAuth } from "../../auth/AuthProvider";
import { api, ApiError } from "../../lib/api";
import { emptyProjectInput, projectPriorityOptions, projectStatusOptions } from "./config";

export function ProjectFormPage({ mode }: { mode: "create" | "edit" }) {
  const { token, user } = useAuth();
  const navigate = useNavigate();
  const { projectId } = useParams();
  const [form, setForm] = useState<ProjectInput>(() => ({ ...emptyProjectInput, ownerId: user?.id ?? null }));
  const [customerOptions, setCustomerOptions] = useState<ProjectCustomerOptionDto[]>([]);
  const [ownerOptions, setOwnerOptions] = useState<ProjectOwnerOptionDto[]>([]);
  const [quoteOptions, setQuoteOptions] = useState<ProjectDocumentOptionDto[]>([]);
  const [orderOptions, setOrderOptions] = useState<ProjectDocumentOptionDto[]>([]);
  const [shipmentOptions, setShipmentOptions] = useState<ProjectShipmentOptionDto[]>([]);
  const [customerSearchTerm, setCustomerSearchTerm] = useState("");
  const [ownerSearchTerm, setOwnerSearchTerm] = useState("");
  const [quoteSearchTerm, setQuoteSearchTerm] = useState("");
  const [orderSearchTerm, setOrderSearchTerm] = useState("");
  const [shipmentSearchTerm, setShipmentSearchTerm] = useState("");
  const [customerPickerOpen, setCustomerPickerOpen] = useState(false);
  const [ownerPickerOpen, setOwnerPickerOpen] = useState(false);
  const [quotePickerOpen, setQuotePickerOpen] = useState(false);
  const [orderPickerOpen, setOrderPickerOpen] = useState(false);
  const [shipmentPickerOpen, setShipmentPickerOpen] = useState(false);
  const [status, setStatus] = useState(mode === "create" ? "Create a new project." : "Loading project...");
  const [isSaving, setIsSaving] = useState(false);

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

    api.getProjectCustomerOptions(token).then(setCustomerOptions).catch(() => setCustomerOptions([]));
    api.getProjectOwnerOptions(token).then(setOwnerOptions).catch(() => setOwnerOptions([]));
  }, [token]);

  useEffect(() => {
    if (!token || !form.customerId) {
      setQuoteOptions([]);
      setOrderOptions([]);
      setShipmentOptions([]);
      return;
    }

    api.getProjectQuoteOptions(token, form.customerId).then(setQuoteOptions).catch(() => setQuoteOptions([]));
    api.getProjectOrderOptions(token, form.customerId).then(setOrderOptions).catch(() => setOrderOptions([]));
    api.getProjectShipmentOptions(token, form.customerId).then(setShipmentOptions).catch(() => setShipmentOptions([]));
  }, [form.customerId, token]);

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

    api.getProject(token, projectId)
      .then((project) => {
        setForm({
          name: project.name,
          status: project.status,
          priority: project.priority,
          customerId: project.customerId,
          salesQuoteId: project.salesQuoteId,
          salesOrderId: project.salesOrderId,
          shipmentId: project.shipmentId,
          ownerId: project.ownerId,
          dueDate: project.dueDate,
          notes: project.notes,
        });
        setCustomerSearchTerm(project.customerName);
        setOwnerSearchTerm(project.ownerName ?? "");
        setQuoteSearchTerm(project.salesQuoteNumber ?? "");
        setOrderSearchTerm(project.salesOrderNumber ?? "");
        setShipmentSearchTerm(project.shipmentNumber ?? "");
        setStatus("Project loaded.");
      })
      .catch((error: unknown) => {
        const message = error instanceof ApiError ? error.message : "Unable to load project.";
        setStatus(message);
      });
  }, [mode, projectId, token]);

  function updateField<Key extends keyof ProjectInput>(key: Key, value: ProjectInput[Key]) {
    setForm((current: ProjectInput) => ({
      ...current,
      [key]: value,
      ...(key === "customerId"
        ? {
            salesQuoteId: null,
            salesOrderId: null,
            shipmentId: null,
          }
        : {}),
    }));
  }

  function restoreSearchTerms() {
    const selectedCustomer = customerOptions.find((customer) => customer.id === form.customerId);
    const selectedOwner = ownerOptions.find((owner) => owner.id === form.ownerId);
    const selectedQuote = quoteOptions.find((quote) => quote.id === form.salesQuoteId);
    const selectedOrder = orderOptions.find((order) => order.id === form.salesOrderId);
    const selectedShipment = shipmentOptions.find((shipment) => shipment.id === form.shipmentId);

    setCustomerSearchTerm(selectedCustomer?.name ?? "");
    setOwnerSearchTerm(selectedOwner?.fullName ?? "");
    setQuoteSearchTerm(selectedQuote?.documentNumber ?? "");
    setOrderSearchTerm(selectedOrder?.documentNumber ?? "");
    setShipmentSearchTerm(selectedShipment?.shipmentNumber ?? "");
  }

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

    setIsSaving(true);
    setStatus("Saving project...");
    try {
      const saved = mode === "create" ? await api.createProject(token, form) : await api.updateProject(token, projectId ?? "", form);
      navigate(`/projects/${saved.id}`);
    } catch (error: unknown) {
      const message = error instanceof ApiError ? error.message : "Unable to save project.";
      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">Projects Editor</p>
            <h3 className="mt-2 text-xl font-bold text-text">{mode === "create" ? "New Project" : "Edit Project"}</h3>
            <p className="mt-2 max-w-2xl text-sm text-muted">Create a customer-linked program record that can anchor commercial documents, delivery work, and project files.</p>
          </div>
          <Link to={mode === "create" ? "/projects" : `/projects/${projectId}`} 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">Project name</span>
            <input value={form.name} onChange={(event) => updateField("name", 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" />
          </label>
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Customer</span>
            <div className="relative">
              <input
                value={customerSearchTerm}
                onChange={(event) => {
                  setCustomerSearchTerm(event.target.value);
                  updateField("customerId", "");
                  setCustomerPickerOpen(true);
                }}
                onFocus={() => setCustomerPickerOpen(true)}
                onBlur={() => window.setTimeout(() => {
                  setCustomerPickerOpen(false);
                  restoreSearchTerms();
                }, 120)}
                placeholder="Search customer"
                className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand"
              />
              {customerPickerOpen ? (
                <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">
                  {customerOptions
                    .filter((customer) => {
                      const query = customerSearchTerm.trim().toLowerCase();
                      if (!query) {
                        return true;
                      }
                      return customer.name.toLowerCase().includes(query) || customer.email.toLowerCase().includes(query);
                    })
                    .slice(0, 12)
                    .map((customer) => (
                      <button key={customer.id} type="button" onMouseDown={(event) => {
                        event.preventDefault();
                        updateField("customerId", customer.id);
                        setCustomerSearchTerm(customer.name);
                        setCustomerPickerOpen(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">{customer.name}</div>
                        <div className="mt-1 text-xs text-muted">{customer.email}</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 ProjectInput["status"])} className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand">
              {projectStatusOptions.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">Priority</span>
            <select value={form.priority} onChange={(event) => updateField("priority", event.target.value as ProjectInput["priority"])} className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand">
              {projectPriorityOptions.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">Owner</span>
            <div className="relative">
              <input
                value={ownerSearchTerm}
                onChange={(event) => {
                  setOwnerSearchTerm(event.target.value);
                  updateField("ownerId", null);
                  setOwnerPickerOpen(true);
                }}
                onFocus={() => setOwnerPickerOpen(true)}
                onBlur={() => window.setTimeout(() => {
                  setOwnerPickerOpen(false);
                  restoreSearchTerms();
                }, 120)}
                placeholder="Search owner"
                className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand"
              />
              {ownerPickerOpen ? (
                <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("ownerId", null);
                    setOwnerSearchTerm("");
                    setOwnerPickerOpen(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">Unassigned</div>
                  </button>
                  {ownerOptions
                    .filter((owner) => {
                      const query = ownerSearchTerm.trim().toLowerCase();
                      if (!query) {
                        return true;
                      }
                      return owner.fullName.toLowerCase().includes(query) || owner.email.toLowerCase().includes(query);
                    })
                    .slice(0, 12)
                    .map((owner) => (
                      <button key={owner.id} type="button" onMouseDown={(event) => {
                        event.preventDefault();
                        updateField("ownerId", owner.id);
                        setOwnerSearchTerm(owner.fullName);
                        setOwnerPickerOpen(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">{owner.fullName}</div>
                        <div className="mt-1 text-xs text-muted">{owner.email}</div>
                      </button>
                    ))}
                </div>
              ) : null}
            </div>
          </label>
          <label className="block">
            <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>
        </div>
        <div className="grid gap-3 xl:grid-cols-3">
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Quote</span>
            <div className="relative">
              <input
                value={quoteSearchTerm}
                onChange={(event) => {
                  setQuoteSearchTerm(event.target.value);
                  updateField("salesQuoteId", null);
                  setQuotePickerOpen(true);
                }}
                onFocus={() => setQuotePickerOpen(true)}
                onBlur={() => window.setTimeout(() => {
                  setQuotePickerOpen(false);
                  restoreSearchTerms();
                }, 120)}
                placeholder="Search quote"
                className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand"
              />
              {quotePickerOpen ? (
                <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("salesQuoteId", null);
                    setQuoteSearchTerm("");
                    setQuotePickerOpen(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 quote</div>
                  </button>
                  {quoteOptions
                    .filter((quote) => {
                      const query = quoteSearchTerm.trim().toLowerCase();
                      if (!query) {
                        return true;
                      }
                      return quote.documentNumber.toLowerCase().includes(query) || quote.customerName.toLowerCase().includes(query) || quote.status.toLowerCase().includes(query);
                    })
                    .slice(0, 12)
                    .map((quote) => (
                      <button key={quote.id} type="button" onMouseDown={(event) => {
                        event.preventDefault();
                        updateField("salesQuoteId", quote.id);
                        setQuoteSearchTerm(quote.documentNumber);
                        setQuotePickerOpen(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">{quote.documentNumber}</div>
                        <div className="mt-1 text-xs text-muted">{quote.customerName} · {quote.status}</div>
                      </button>
                    ))}
                </div>
              ) : null}
            </div>
          </label>
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Sales order</span>
            <div className="relative">
              <input
                value={orderSearchTerm}
                onChange={(event) => {
                  setOrderSearchTerm(event.target.value);
                  updateField("salesOrderId", null);
                  setOrderPickerOpen(true);
                }}
                onFocus={() => setOrderPickerOpen(true)}
                onBlur={() => window.setTimeout(() => {
                  setOrderPickerOpen(false);
                  restoreSearchTerms();
                }, 120)}
                placeholder="Search sales order"
                className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand"
              />
              {orderPickerOpen ? (
                <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("salesOrderId", null);
                    setOrderSearchTerm("");
                    setOrderPickerOpen(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 sales order</div>
                  </button>
                  {orderOptions
                    .filter((order) => {
                      const query = orderSearchTerm.trim().toLowerCase();
                      if (!query) {
                        return true;
                      }
                      return order.documentNumber.toLowerCase().includes(query) || order.customerName.toLowerCase().includes(query) || order.status.toLowerCase().includes(query);
                    })
                    .slice(0, 12)
                    .map((order) => (
                      <button key={order.id} type="button" onMouseDown={(event) => {
                        event.preventDefault();
                        updateField("salesOrderId", order.id);
                        setOrderSearchTerm(order.documentNumber);
                        setOrderPickerOpen(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">{order.documentNumber}</div>
                        <div className="mt-1 text-xs text-muted">{order.customerName} · {order.status}</div>
                      </button>
                    ))}
                </div>
              ) : null}
            </div>
          </label>
          <label className="block">
            <span className="mb-2 block text-sm font-semibold text-text">Shipment</span>
            <div className="relative">
              <input
                value={shipmentSearchTerm}
                onChange={(event) => {
                  setShipmentSearchTerm(event.target.value);
                  updateField("shipmentId", null);
                  setShipmentPickerOpen(true);
                }}
                onFocus={() => setShipmentPickerOpen(true)}
                onBlur={() => window.setTimeout(() => {
                  setShipmentPickerOpen(false);
                  restoreSearchTerms();
                }, 120)}
                placeholder="Search shipment"
                className="w-full rounded-2xl border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand"
              />
              {shipmentPickerOpen ? (
                <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("shipmentId", null);
                    setShipmentSearchTerm("");
                    setShipmentPickerOpen(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 shipment</div>
                  </button>
                  {shipmentOptions
                    .filter((shipment) => {
                      const query = shipmentSearchTerm.trim().toLowerCase();
                      if (!query) {
                        return true;
                      }
                      return shipment.shipmentNumber.toLowerCase().includes(query) || shipment.salesOrderNumber.toLowerCase().includes(query) || shipment.customerName.toLowerCase().includes(query) || shipment.status.toLowerCase().includes(query);
                    })
                    .slice(0, 12)
                    .map((shipment) => (
                      <button key={shipment.id} type="button" onMouseDown={(event) => {
                        event.preventDefault();
                        updateField("shipmentId", shipment.id);
                        setShipmentSearchTerm(shipment.shipmentNumber);
                        setShipmentPickerOpen(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">{shipment.shipmentNumber}</div>
                        <div className="mt-1 text-xs text-muted">{shipment.salesOrderNumber} · {shipment.status}</div>
                      </button>
                    ))}
                </div>
              ) : null}
            </div>
          </label>
        </div>
        <label className="block">
          <span className="mb-2 block text-sm font-semibold text-text">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 project" : "Save changes"}
          </button>
        </div>
      </section>
    </form>
  );
}
