'use client';

import {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import { ChevronDown, Loader2, Plus, Search } from 'lucide-react';
import { api, ApiClientError } from '@/lib/api-client';
import type { MedicineCatalogItem } from '@/lib/api-types';

export interface MedicationPick {
  /** Brand / trade name as it will appear on the prescription */
  brandName: string;
  /** Salt / generic name */
  genericName?: string;
  /** Default strength carried over from the catalog */
  strength?: string;
  /** Pharmaceutical form (Tablet, Syrup, Inhaler …) */
  dosageForm?: string;
  /** When true, this is a brand the doctor typed in by hand — it's been
   *  queued for admin approval but is also usable on this prescription now. */
  isPending?: boolean;
}

interface MedicationSearchProps {
  value: string;
  onPick: (pick: MedicationPick) => void;
  /** Optional appointment id so submissions of new medicines can be traced. */
  appointmentId?: string;
  disabled?: boolean;
}

/**
 * Searchable medication picker. Hits `/api/medicines?q=` to pull live results
 * from the catalog. The user can also type a name that isn't in the list and
 * tap the inline "Add as new medicine" affordance — that submits a
 * pending-medicine approval request for the admin to review later.
 */
export function MedicationSearch({
  value,
  onPick,
  appointmentId,
  disabled,
}: MedicationSearchProps) {
  const [query, setQuery] = useState(value);
  const [items, setItems] = useState<MedicineCatalogItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [open, setOpen] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [submitted, setSubmitted] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const wrapRef = useRef<HTMLDivElement | null>(null);

  // Keep external value in sync (e.g. parent reset).
  useEffect(() => {
    setQuery(value);
  }, [value]);

  // Debounced search.
  useEffect(() => {
    if (disabled) return;
    const trimmed = query.trim();
    let cancelled = false;
    const t = window.setTimeout(async () => {
      setLoading(true);
      try {
        const res = await api.searchMedicines(trimmed || undefined, 25);
        if (!cancelled) setItems(res.items);
      } catch {
        if (!cancelled) setItems([]);
      } finally {
        if (!cancelled) setLoading(false);
      }
    }, 200);
    return () => {
      cancelled = true;
      window.clearTimeout(t);
    };
  }, [query, disabled]);

  // Close on outside click.
  useEffect(() => {
    function onDocClick(e: MouseEvent) {
      if (!wrapRef.current) return;
      if (!wrapRef.current.contains(e.target as Node)) setOpen(false);
    }
    document.addEventListener('mousedown', onDocClick);
    return () => document.removeEventListener('mousedown', onDocClick);
  }, []);

  const trimmed = query.trim();
  const exactMatch = useMemo(
    () =>
      items.find(
        (m) => m.brandName.toLowerCase() === trimmed.toLowerCase(),
      ),
    [items, trimmed],
  );
  const showAddOther = trimmed.length >= 2 && !exactMatch;

  const handlePick = useCallback(
    (m: MedicineCatalogItem) => {
      setQuery(m.brandName);
      setOpen(false);
      onPick({
        brandName: m.brandName,
        genericName: m.genericName,
        strength: m.strength ?? undefined,
        dosageForm: m.dosageForm,
      });
    },
    [onPick],
  );

  const handleAddOther = useCallback(async () => {
    if (!trimmed) return;
    setError(null);
    setSubmitting(true);
    try {
      await api.submitPendingMedicine({
        brandName: trimmed,
        appointmentId,
      });
      setSubmitted(trimmed);
      onPick({ brandName: trimmed, isPending: true });
      setOpen(false);
    } catch (e) {
      setError(
        e instanceof ApiClientError
          ? e.message
          : 'Could not submit medicine for approval',
      );
    } finally {
      setSubmitting(false);
    }
  }, [trimmed, appointmentId, onPick]);

  return (
    <div className="relative sm:col-span-2" ref={wrapRef}>
      <label className="block text-[10px] font-semibold uppercase tracking-wide text-ink-2">
        Medication
      </label>
      <div className="relative mt-1">
        <Search className="pointer-events-none absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-ink-3" />
        <input
          value={query}
          onChange={(e) => {
            setQuery(e.target.value);
            setOpen(true);
            setSubmitted(null);
            onPick({ brandName: e.target.value });
          }}
          onFocus={() => setOpen(true)}
          placeholder="Search by brand or salt (e.g. Panadol or Paracetamol)"
          disabled={disabled}
          className="h-9 w-full rounded-md border border-denseSurface-border bg-white pl-7 pr-7 text-sm text-ink-1 focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-500/30 disabled:opacity-60"
        />
        <button
          type="button"
          onClick={() => setOpen((v) => !v)}
          disabled={disabled}
          className="absolute right-1 top-1/2 -translate-y-1/2 rounded p-1 text-ink-3 hover:bg-denseSurface-bg disabled:opacity-50"
          aria-label="Toggle medication list"
        >
          <ChevronDown className="h-3.5 w-3.5" />
        </button>
      </div>

      {submitted ? (
        <p className="mt-1 text-[11px] text-success-500">
          Submitted “{submitted}” for admin approval — using as free-text on this
          prescription.
        </p>
      ) : null}
      {error ? (
        <p className="mt-1 text-[11px] text-danger-500">{error}</p>
      ) : null}

      {open && !disabled ? (
        <div className="absolute left-0 right-0 z-20 mt-1 max-h-72 overflow-auto rounded-md border border-denseSurface-border bg-white shadow-lg">
          {loading ? (
            <div className="flex items-center gap-2 px-3 py-2 text-xs text-ink-2">
              <Loader2 className="h-3.5 w-3.5 animate-spin" /> Searching…
            </div>
          ) : items.length === 0 && !showAddOther ? (
            <div className="px-3 py-3 text-xs text-ink-3">
              Start typing to search the catalog.
            </div>
          ) : (
            <ul className="divide-y divide-denseSurface-border">
              {items.map((m) => (
                <li key={m.id}>
                  <button
                    type="button"
                    onClick={() => handlePick(m)}
                    className="flex w-full items-start justify-between gap-2 px-3 py-2 text-left hover:bg-denseSurface-bg"
                  >
                    <div className="min-w-0">
                      <p className="truncate text-sm font-semibold text-ink-1">
                        {m.brandName}
                        {m.strength ? (
                          <span className="ml-1 font-normal text-ink-2">
                            · {m.strength}
                          </span>
                        ) : null}
                      </p>
                      <p className="truncate text-[11px] text-ink-2">
                        {m.genericName}
                        {m.dosageForm ? (
                          <span className="ml-1 text-ink-3">
                            · {m.dosageForm}
                          </span>
                        ) : null}
                      </p>
                    </div>
                    {m.isControlled ? (
                      <span className="rounded bg-warning-500/15 px-1.5 py-0.5 text-[10px] font-bold uppercase text-warning-500">
                        Controlled
                      </span>
                    ) : null}
                  </button>
                </li>
              ))}
              {showAddOther ? (
                <li className="bg-denseSurface-bg/40">
                  <button
                    type="button"
                    onClick={() => void handleAddOther()}
                    disabled={submitting}
                    className="flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-brand-700 hover:bg-brand-500/10 disabled:opacity-60"
                  >
                    {submitting ? (
                      <Loader2 className="h-3.5 w-3.5 animate-spin" />
                    ) : (
                      <Plus className="h-3.5 w-3.5" />
                    )}
                    Add “{trimmed}” as a new medicine (sends for admin approval)
                  </button>
                </li>
              ) : null}
            </ul>
          )}
        </div>
      ) : null}
    </div>
  );
}
