"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { Loader2, Search, X } from "lucide-react";
import { accountingApi } from "@/src/modules/accounting/services/accounting-api";
import { useTenantId } from "@/hooks/useTenantId";
import { formatMoney } from "@/lib/utils";
import { cn } from "@/lib/utils";
import { Button } from "@/src/shared/ui";

export type ComboboxOption = {
  id: string;
  label: string;
  subLabel?: string;
  meta?: Record<string, string>;
};

function useDebounced(value: string, ms = 250) {
  const [v, setV] = useState(value);
  useEffect(() => {
    const t = setTimeout(() => setV(value), ms);
    return () => clearTimeout(t);
  }, [value, ms]);
  return v;
}

export function EntityCombobox({
  valueLabel,
  placeholder,
  options,
  loading,
  onQueryChange,
  onSelect,
  onClear,
  emptyText = "موردی یافت نشد",
  className,
}: {
  valueLabel?: string;
  placeholder: string;
  options: ComboboxOption[];
  loading?: boolean;
  onQueryChange: (q: string) => void;
  onSelect: (opt: ComboboxOption) => void;
  onClear?: () => void;
  emptyText?: string;
  className?: string;
}) {
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState("");
  const rootRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const onDoc = (e: MouseEvent) => {
      if (!rootRef.current?.contains(e.target as Node)) setOpen(false);
    };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, []);

  return (
    <div ref={rootRef} className={cn("relative", className)}>
      <div className="flex h-10 items-center gap-1 rounded-xl border border-[var(--border)] bg-[var(--surface)] px-2">
        <Search className="h-4 w-4 shrink-0 text-[var(--muted)]" />
        <input
          className="h-full w-full bg-transparent text-sm text-secondary outline-none placeholder:text-[var(--muted)]"
          placeholder={valueLabel || placeholder}
          value={open ? q : valueLabel || q}
          onFocus={() => {
            setOpen(true);
            onQueryChange(q);
          }}
          onChange={(e) => {
            setQ(e.target.value);
            setOpen(true);
            onQueryChange(e.target.value);
          }}
        />
        {loading ? <Loader2 className="h-4 w-4 animate-spin text-[var(--muted)]" /> : null}
        {valueLabel && onClear ? (
          <Button
            type="button"
            size="icon"
            variant="ghost"
            className="h-7 w-7"
            onClick={() => {
              setQ("");
              onClear();
              onQueryChange("");
            }}
            aria-label="پاک کردن"
          >
            <X className="h-3.5 w-3.5" />
          </Button>
        ) : null}
      </div>
      {open ? (
        <div className="absolute z-[120] mt-1 max-h-56 w-full overflow-auto rounded-xl border border-[var(--border)] bg-[var(--surface)] shadow-[var(--shadow-lg)]">
          {options.length === 0 && !loading ? (
            <p className="px-3 py-3 text-sm text-[var(--muted)]">{emptyText}</p>
          ) : (
            options.map((opt) => (
              <button
                key={opt.id}
                type="button"
                className="flex w-full flex-col items-start gap-0.5 px-3 py-2 text-right hover:bg-[var(--surface-muted)]"
                onClick={() => {
                  onSelect(opt);
                  setQ("");
                  setOpen(false);
                }}
              >
                <span className="text-sm font-medium text-secondary">{opt.label}</span>
                {opt.subLabel ? <span className="text-xs text-[var(--muted)]">{opt.subLabel}</span> : null}
              </button>
            ))
          )}
        </div>
      ) : null}
    </div>
  );
}

export function PartyCombobox({
  module,
  valueName,
  onChange,
  placeholder,
}: {
  /** sales → customers, purchase → suppliers, else both */
  module?: string;
  valueName?: string;
  onChange: (party: { id: string; name: string; kind: "customer" | "supplier" } | null) => void;
  placeholder?: string;
}) {
  const { tenantId } = useTenantId();
  const [q, setQ] = useState("");
  const dq = useDebounced(q);

  const kind: "customer" | "supplier" | "both" =
    module === "sales" ? "customer" : module === "purchase" ? "supplier" : "both";

  const customersQ = useQuery({
    queryKey: ["accounting", tenantId, "parties", "customers"],
    queryFn: () => accountingApi.customers.list(tenantId!),
    enabled: !!tenantId && (kind === "customer" || kind === "both"),
    staleTime: 30_000,
  });
  const suppliersQ = useQuery({
    queryKey: ["accounting", tenantId, "parties", "suppliers"],
    queryFn: () => accountingApi.suppliers.list(tenantId!),
    enabled: !!tenantId && (kind === "supplier" || kind === "both"),
    staleTime: 30_000,
  });

  const options = useMemo(() => {
    const needle = dq.trim().toLowerCase();
    const rows: ComboboxOption[] = [];
    if (kind === "customer" || kind === "both") {
      for (const c of customersQ.data ?? []) {
        const label = `${c.code} — ${c.name}`;
        if (!needle || label.toLowerCase().includes(needle) || c.name.toLowerCase().includes(needle)) {
          rows.push({
            id: `customer:${c.id}`,
            label: c.name,
            subLabel: `مشتری · ${c.code} · مانده ${formatMoney(c.outstanding_balance)}`,
            meta: { kind: "customer", id: c.id, name: c.name },
          });
        }
      }
    }
    if (kind === "supplier" || kind === "both") {
      for (const s of suppliersQ.data ?? []) {
        const label = `${s.code} — ${s.name}`;
        if (!needle || label.toLowerCase().includes(needle) || s.name.toLowerCase().includes(needle)) {
          rows.push({
            id: `supplier:${s.id}`,
            label: s.name,
            subLabel: `تأمین‌کننده · ${s.code} · مانده ${formatMoney(s.outstanding_balance)}`,
            meta: { kind: "supplier", id: s.id, name: s.name },
          });
        }
      }
    }
    return rows.slice(0, 40);
  }, [customersQ.data, suppliersQ.data, dq, kind]);

  const loading = customersQ.isFetching || suppliersQ.isFetching;

  return (
    <EntityCombobox
      valueLabel={valueName}
      placeholder={placeholder || "جستجوی طرف حساب…"}
      options={options}
      loading={loading}
      onQueryChange={setQ}
      emptyText="طرف حسابی یافت نشد — ابتدا در مشتریان/تأمین‌کنندگان ثبت کنید"
      onSelect={(opt) => {
        const kind = (opt.meta?.kind || "customer") as "customer" | "supplier";
        onChange({ id: opt.meta!.id, name: opt.meta!.name, kind });
      }}
      onClear={() => onChange(null)}
    />
  );
}

export function ItemCombobox({
  valueLabel,
  onSelect,
  onClear,
}: {
  valueLabel?: string;
  onSelect: (item: {
    id: string;
    code: string;
    name: string;
    unit: string;
    unit_cost: string;
  }) => void;
  onClear?: () => void;
}) {
  const { tenantId } = useTenantId();
  const [q, setQ] = useState("");
  const dq = useDebounced(q);

  const itemsQ = useQuery({
    queryKey: ["accounting", tenantId, "ops-items"],
    queryFn: () => accountingApi.ops.listItems(tenantId!),
    enabled: !!tenantId,
    staleTime: 30_000,
  });

  const options = useMemo(() => {
    const needle = dq.trim().toLowerCase();
    return (itemsQ.data ?? [])
      .filter((i) => i.is_active !== false)
      .filter((i) => {
        if (!needle) return true;
        return (
          i.name.toLowerCase().includes(needle) ||
          i.code.toLowerCase().includes(needle)
        );
      })
      .slice(0, 40)
      .map((i) => ({
        id: i.id,
        label: `${i.code} — ${i.name}`,
        subLabel: `${i.unit} · موجودی ${i.quantity_on_hand} · فی ${formatMoney(i.unit_cost)}`,
        meta: {
          id: i.id,
          code: i.code,
          name: i.name,
          unit: i.unit,
          unit_cost: String(i.unit_cost ?? "0"),
        },
      }));
  }, [itemsQ.data, dq]);

  return (
    <EntityCombobox
      valueLabel={valueLabel}
      placeholder="جستجوی کالا / خدمت…"
      options={options}
      loading={itemsQ.isFetching}
      onQueryChange={setQ}
      emptyText="کالایی یافت نشد — از کارت کالا ثبت کنید"
      onSelect={(opt) =>
        onSelect({
          id: opt.meta!.id,
          code: opt.meta!.code,
          name: opt.meta!.name,
          unit: opt.meta!.unit,
          unit_cost: opt.meta!.unit_cost,
        })
      }
      onClear={onClear}
    />
  );
}
