import { permissions } from "@mrp/shared";
import type { InventorySkuCatalogTreeDto, InventorySkuFamilyInput, InventorySkuNodeDto, InventorySkuNodeInput } from "@mrp/shared/dist/inventory/types.js";
import type { ReactNode } from "react";
import { useEffect, useMemo, useState } from "react";
import { Link } from "react-router-dom";

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

const emptyFamilyForm: InventorySkuFamilyInput = {
  code: "",
  sequenceCode: "",
  name: "",
  description: "",
  isActive: true,
};

const emptyNodeForm: InventorySkuNodeInput = {
  familyId: "",
  parentNodeId: null,
  code: "",
  label: "",
  description: "",
  sortOrder: 10,
  isActive: true,
};

export function InventorySkuMasterPage() {
  const { token, user } = useAuth();
  const [catalog, setCatalog] = useState<InventorySkuCatalogTreeDto>({ families: [], nodes: [] });
  const [familyForm, setFamilyForm] = useState<InventorySkuFamilyInput>(emptyFamilyForm);
  const [nodeForm, setNodeForm] = useState<InventorySkuNodeInput>(emptyNodeForm);
  const [selectedFamilyId, setSelectedFamilyId] = useState("");
  const [status, setStatus] = useState("Loading SKU master...");

  const canManage = user?.permissions.includes(permissions.inventoryWrite) ?? false;

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

    api
      .getInventorySkuCatalog(token)
      .then((nextCatalog) => {
        setCatalog(nextCatalog);
        const firstFamilyId = nextCatalog.families[0]?.id ?? "";
        setSelectedFamilyId((current) => current || firstFamilyId);
        setNodeForm((current) => ({
          ...current,
          familyId: current.familyId || firstFamilyId,
        }));
        setStatus(`${nextCatalog.families.length} family branch(es) loaded.`);
      })
      .catch((error: unknown) => {
        setStatus(error instanceof ApiError ? error.message : "Unable to load SKU master.");
      });
  }, [token]);

  const familyNodes = useMemo(
    () =>
      catalog.nodes
        .filter((node) => node.familyId === selectedFamilyId)
        .sort((left, right) => left.level - right.level || left.sortOrder - right.sortOrder || left.code.localeCompare(right.code)),
    [catalog.nodes, selectedFamilyId]
  );

  const parentOptions = useMemo(
    () => familyNodes.filter((node) => node.level < 6),
    [familyNodes]
  );

  function renderNodes(parentNodeId: string | null, depth = 0): ReactNode {
    const branchNodes = familyNodes.filter((node) => node.parentNodeId === parentNodeId);
    if (!branchNodes.length) {
      return null;
    }

    return branchNodes.map((node) => (
      <div key={node.id} className="space-y-2">
        <div className="rounded-[18px] border border-line/70 bg-page/60 px-3 py-3" style={{ marginLeft: `${depth * 16}px` }}>
          <div className="flex flex-wrap items-center justify-between gap-2">
            <div>
              <div className="text-sm font-semibold text-text">{node.code} <span className="text-muted">- {node.label}</span></div>
              <div className="mt-1 text-xs text-muted">Level {node.level} • {node.childCount} child branch(es)</div>
            </div>
            <button
              type="button"
              onClick={() =>
                setNodeForm((current) => ({
                  ...current,
                  familyId: selectedFamilyId,
                  parentNodeId: node.id,
                }))
              }
              className="rounded-2xl border border-line/70 px-2 py-2 text-xs font-semibold text-text"
            >
              Add child
            </button>
          </div>
          {node.description ? <div className="mt-2 text-xs text-muted">{node.description}</div> : null}
        </div>
        {renderNodes(node.id, depth + 1)}
      </div>
    ));
  }

  async function reloadCatalog() {
    if (!token) {
      return;
    }

    const nextCatalog = await api.getInventorySkuCatalog(token);
    setCatalog(nextCatalog);
    if (!selectedFamilyId && nextCatalog.families[0]) {
      setSelectedFamilyId(nextCatalog.families[0].id);
    }
  }

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

    try {
      const created = await api.createInventorySkuFamily(token, familyForm);
      setFamilyForm(emptyFamilyForm);
      setSelectedFamilyId(created.id);
      setNodeForm((current) => ({ ...current, familyId: created.id, parentNodeId: null }));
      await reloadCatalog();
      setStatus(`Created SKU family ${created.code}.`);
    } catch (error: unknown) {
      setStatus(error instanceof ApiError ? error.message : "Unable to create SKU family.");
    }
  }

  async function handleCreateNode(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!token || !canManage || !nodeForm.familyId) {
      return;
    }

    try {
      const created = await api.createInventorySkuNode(token, nodeForm);
      setNodeForm((current) => ({
        ...emptyNodeForm,
        familyId: current.familyId,
        parentNodeId: created.parentNodeId,
      }));
      await reloadCatalog();
      setStatus(`Created SKU branch ${created.code}.`);
    } catch (error: unknown) {
      setStatus(error instanceof ApiError ? error.message : "Unable to create SKU branch.");
    }
  }

  return (
    <section className="space-y-6">
      <div className="rounded-[20px] 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">Inventory Master Data</p>
            <h3 className="mt-2 text-xl font-bold text-text">SKU Master Builder</h3>
            <p className="mt-2 max-w-3xl text-sm text-muted">Define family roots, branch-specific child codes, and the family-scoped short-code suffix that finishes each generated SKU.</p>
          </div>
          <Link to="/inventory/items" className="inline-flex items-center justify-center rounded-2xl border border-line/70 px-2 py-2 text-sm font-semibold text-text">
            Back to items
          </Link>
        </div>
      </div>

      <div className="grid gap-6 xl:grid-cols-[0.9fr_1.5fr]">
        <div className="space-y-6">
          <section className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
            <div className="text-sm font-semibold text-text">Families</div>
            <div className="mt-4 space-y-2">
              {catalog.families.length === 0 ? (
                <div className="rounded-[18px] border border-dashed border-line/70 bg-page/60 px-4 py-6 text-sm text-muted">No SKU families defined yet.</div>
              ) : (
                catalog.families.map((family) => (
                  <button
                    key={family.id}
                    type="button"
                    onClick={() => {
                      setSelectedFamilyId(family.id);
                      setNodeForm((current) => ({ ...current, familyId: family.id, parentNodeId: null }));
                    }}
                    className={`block w-full rounded-[18px] border px-3 py-3 text-left transition ${
                      selectedFamilyId === family.id ? "border-brand bg-brand/8" : "border-line/70 bg-page/60 hover:bg-page/80"
                    }`}
                  >
                    <div className="text-sm font-semibold text-text">{family.code} <span className="text-muted">({family.sequenceCode})</span></div>
                    <div className="mt-1 text-xs text-muted">{family.name}</div>
                    <div className="mt-2 text-xs text-muted">{family.childNodeCount} branch nodes • next {family.sequenceCode}{String(family.nextSequenceNumber).padStart(4, "0")}</div>
                  </button>
                ))
              )}
            </div>
          </section>

          {canManage ? (
            <section className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
              <div className="text-sm font-semibold text-text">Add family</div>
              <form className="mt-4 space-y-3" onSubmit={handleCreateFamily}>
                <div className="grid gap-3 sm:grid-cols-2">
                  <label className="block">
                    <span className="mb-2 block text-xs font-semibold uppercase tracking-[0.16em] text-muted">Family code</span>
                    <input value={familyForm.code} onChange={(event) => setFamilyForm((current) => ({ ...current, code: 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-xs font-semibold uppercase tracking-[0.16em] text-muted">Suffix code</span>
                    <input value={familyForm.sequenceCode} onChange={(event) => setFamilyForm((current) => ({ ...current, sequenceCode: 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>
                </div>
                <label className="block">
                  <span className="mb-2 block text-xs font-semibold uppercase tracking-[0.16em] text-muted">Name</span>
                  <input value={familyForm.name} onChange={(event) => setFamilyForm((current) => ({ ...current, 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-xs font-semibold uppercase tracking-[0.16em] text-muted">Description</span>
                  <textarea value={familyForm.description} onChange={(event) => setFamilyForm((current) => ({ ...current, description: event.target.value }))} rows={3} className="w-full rounded-[18px] border border-line/70 bg-page px-2 py-2 text-text outline-none transition focus:border-brand" />
                </label>
                <button type="submit" className="rounded-2xl bg-brand px-3 py-2 text-sm font-semibold text-white">Create family</button>
              </form>
            </section>
          ) : null}
        </div>

        <div className="space-y-6">
          <section className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
            <div className="flex flex-col gap-2 lg:flex-row lg:items-center lg:justify-between">
              <div>
                <div className="text-sm font-semibold text-text">Branch tree</div>
                <div className="mt-1 text-xs text-muted">{status}</div>
              </div>
              {selectedFamilyId ? (
                <div className="text-xs text-muted">Up to 6 total SKU levels including family root.</div>
              ) : null}
            </div>
            <div className="mt-4 space-y-3">
              {selectedFamilyId ? renderNodes(null) : <div className="rounded-[18px] border border-dashed border-line/70 bg-page/60 px-4 py-6 text-sm text-muted">Select a family to inspect or extend its branch tree.</div>}
            </div>
          </section>

          {canManage ? (
            <section className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
              <div className="text-sm font-semibold text-text">Add branch node</div>
              <form className="mt-4 space-y-3" onSubmit={handleCreateNode}>
                <div className="grid gap-3 sm:grid-cols-2">
                  <label className="block">
                    <span className="mb-2 block text-xs font-semibold uppercase tracking-[0.16em] text-muted">Family</span>
                    <select value={nodeForm.familyId} onChange={(event) => setNodeForm((current) => ({ ...current, familyId: event.target.value, parentNodeId: null }))} 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 family</option>
                      {catalog.families.map((family) => (
                        <option key={family.id} value={family.id}>{family.code} - {family.name}</option>
                      ))}
                    </select>
                  </label>
                  <label className="block">
                    <span className="mb-2 block text-xs font-semibold uppercase tracking-[0.16em] text-muted">Parent branch</span>
                    <select value={nodeForm.parentNodeId ?? ""} onChange={(event) => setNodeForm((current) => ({ ...current, parentNodeId: event.target.value || null }))} 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="">Family root</option>
                      {parentOptions.map((node) => (
                        <option key={node.id} value={node.id}>L{node.level} - {node.code} - {node.label}</option>
                      ))}
                    </select>
                  </label>
                </div>
                <div className="grid gap-3 sm:grid-cols-2">
                  <label className="block">
                    <span className="mb-2 block text-xs font-semibold uppercase tracking-[0.16em] text-muted">Code</span>
                    <input value={nodeForm.code} onChange={(event) => setNodeForm((current) => ({ ...current, code: 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-xs font-semibold uppercase tracking-[0.16em] text-muted">Label</span>
                    <input value={nodeForm.label} onChange={(event) => setNodeForm((current) => ({ ...current, label: 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>
                </div>
                <div className="grid gap-3 sm:grid-cols-[1fr_140px]">
                  <label className="block">
                    <span className="mb-2 block text-xs font-semibold uppercase tracking-[0.16em] text-muted">Description</span>
                    <textarea value={nodeForm.description} onChange={(event) => setNodeForm((current) => ({ ...current, description: event.target.value }))} rows={3} className="w-full rounded-[18px] 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-xs font-semibold uppercase tracking-[0.16em] text-muted">Sort</span>
                    <input type="number" min={0} step={10} value={nodeForm.sortOrder} onChange={(event) => setNodeForm((current) => ({ ...current, sortOrder: Number(event.target.value) || 0 }))} 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>
                <button type="submit" className="rounded-2xl bg-brand px-3 py-2 text-sm font-semibold text-white" disabled={!nodeForm.familyId}>Create branch</button>
              </form>
            </section>
          ) : null}
        </div>
      </div>
    </section>
  );
}
