'use client';

import { useEffect, useMemo, useState } from 'react';
import {
  Plus,
  Trash2,
  ReceiptText,
  Search,
  AlertTriangle,
  CheckCircle2,
  Loader2,
} from 'lucide-react';
import { DenseCard, StatusPill } from '@sehat/ui';
import { api, ApiClientError } from '@/lib/api-client';
import type {
  EmrLookups,
  InteractionCheckResponse,
  PrescriptionItemInput,
} from '@/lib/api-types';
import { DrugCheckWarnings } from './drug-check-warnings';
import { MedicationSearch } from './medication-search';

const EMPTY_ITEM: PrescriptionItemInput = {
  medicationName: '',
  dose: '',
  frequency: '',
  duration: '',
  route: '',
  instructions: '',
};

interface PrescriptionWriterProps {
  appointmentId: string;
  /** Existing meds + allergies pre-loaded so the interaction check has
   *  the full context without an extra round-trip. */
  existingMedications?: string[];
  allergies?: string[];
  /** Patient user id — required for the F6 patient-aware safety check.
   *  When omitted, the safety check pane stays dormant. */
  patientUserId?: string;
  /** Appointment status drives the gating: the doctor can only author
   *  prescriptions once the consult is `in_progress` or `completed`. */
  appointmentStatus?: string;
}

/**
 * Inline prescription composer used on the appointment detail page so the
 * doctor doesn't have to navigate away mid-consult. Includes:
 *  • medication autocomplete from `/api/emr/lookups`
 *  • per-row dose / frequency / duration / route
 *  • on-demand interaction check (yellow/red verdict) before save
 *  • final POST to `/api/prescriptions`
 */
export function PrescriptionWriter({
  appointmentId,
  existingMedications = [],
  allergies = [],
  patientUserId,
  appointmentStatus,
}: PrescriptionWriterProps) {
  const consultStarted =
    appointmentStatus === 'in_progress' || appointmentStatus === 'completed';
  const [lookups, setLookups] = useState<EmrLookups | null>(null);
  const [items, setItems] = useState<PrescriptionItemInput[]>([{ ...EMPTY_ITEM }]);
  const [interaction, setInteraction] =
    useState<InteractionCheckResponse | null>(null);
  const [checking, setChecking] = useState(false);
  const [saving, setSaving] = useState(false);
  const [savedId, setSavedId] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  // F6 — true when there are no high-severity safety warnings OR when each
  // high-severity warning has been explicitly overridden. Defaults to true so
  // the save button stays usable before any check has run.
  const [safetyOverridesOk, setSafetyOverridesOk] = useState<boolean>(true);

  useEffect(() => {
    let cancelled = false;
    void (async () => {
      try {
        const l = await api.getLookups();
        if (!cancelled) setLookups(l);
      } catch {
        // Non-fatal — the writer still works with free-text inputs.
      }
    })();
    return () => {
      cancelled = true;
    };
  }, []);

  const cleanedItems = useMemo(
    () =>
      items.filter(
        (i) =>
          i.medicationName.trim() &&
          i.dose.trim() &&
          i.frequency.trim() &&
          i.duration.trim() &&
          i.route.trim(),
      ),
    [items],
  );

  function updateItem(idx: number, patch: Partial<PrescriptionItemInput>) {
    setItems((arr) => arr.map((it, i) => (i === idx ? { ...it, ...patch } : it)));
    // Invalidate any prior interaction verdict — the doctor must re-check.
    setInteraction(null);
    setSavedId(null);
  }

  function removeItem(idx: number) {
    setItems((arr) =>
      arr.length === 1 ? [{ ...EMPTY_ITEM }] : arr.filter((_, i) => i !== idx),
    );
    setInteraction(null);
  }

  function addItem() {
    setItems((arr) => [...arr, { ...EMPTY_ITEM }]);
  }

  async function runInteractionCheck() {
    if (cleanedItems.length === 0) return;
    setChecking(true);
    setError(null);
    try {
      const res = await api.checkInteractions(
        cleanedItems,
        existingMedications,
        allergies,
      );
      setInteraction(res);
    } catch (e) {
      setError(
        e instanceof ApiClientError ? e.message : 'Interaction check failed',
      );
    } finally {
      setChecking(false);
    }
  }

  async function savePrescription() {
    if (cleanedItems.length === 0) return;
    setSaving(true);
    setError(null);
    try {
      const p = await api.createPrescription({
        appointmentId,
        items: cleanedItems,
      });
      setSavedId(p.id);
    } catch (e) {
      setError(
        e instanceof ApiClientError ? e.message : 'Failed to save prescription',
      );
    } finally {
      setSaving(false);
    }
  }

  return (
    <DenseCard
      title={
        <span className="flex items-center gap-1.5">
          <ReceiptText className="h-4 w-4 text-brand-500" />
          Prescription
        </span>
      }
      actions={
        interaction ? (
          <VerdictPill verdict={interaction.verdict} />
        ) : null
      }
    >
      {!consultStarted ? (
        <div className="mb-3 flex items-start gap-2 rounded-md border border-warning-500/40 bg-warning-500/10 px-3 py-2 text-xs text-warning-500">
          <AlertTriangle className="mt-0.5 h-3.5 w-3.5 flex-shrink-0" />
          <div>
            <p className="font-semibold">Locked until the consult starts</p>
            <p className="opacity-90">
              Prescriptions can only be added once the video call has begun.
              Tap “Join call” to start the consultation, then come back here.
            </p>
          </div>
        </div>
      ) : null}

      <div className={`space-y-3 ${consultStarted ? '' : 'pointer-events-none opacity-60'}`}>
        {items.map((it, idx) => (
          <div
            key={idx}
            className="rounded-md border border-denseSurface-border bg-white p-2.5"
          >
            <div className="flex items-center justify-between gap-2">
              <span className="font-mono text-[10px] font-semibold uppercase text-ink-3">
                Rx #{idx + 1}
              </span>
              {items.length > 1 ? (
                <button
                  type="button"
                  onClick={() => removeItem(idx)}
                  className="rounded p-1 text-ink-3 transition-colors hover:bg-danger-500/10 hover:text-danger-500"
                  aria-label="Remove medication"
                >
                  <Trash2 className="h-3.5 w-3.5" />
                </button>
              ) : null}
            </div>
            <div className="mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2">
              <MedicationSearch
                value={it.medicationName}
                appointmentId={appointmentId}
                disabled={!consultStarted}
                onPick={(pick) =>
                  updateItem(idx, {
                    medicationName: pick.brandName,
                    genericName: pick.genericName ?? it.genericName,
                    // Use the catalog strength as the dose default — doctor can
                    // override per row.
                    dose: pick.strength ?? it.dose,
                  })
                }
              />
              <Field
                label="Dose"
                placeholder="500 mg"
                value={it.dose}
                onChange={(v) => updateItem(idx, { dose: v })}
              />
              <SelectOrInput
                label="Frequency"
                value={it.frequency}
                onChange={(v) => updateItem(idx, { frequency: v })}
                options={lookups?.medicationFrequencies ?? []}
              />
              <Field
                label="Duration"
                placeholder="7 days"
                value={it.duration}
                onChange={(v) => updateItem(idx, { duration: v })}
              />
              <SelectOrInput
                label="Route"
                value={it.route}
                onChange={(v) => updateItem(idx, { route: v })}
                options={lookups?.medicationRoutes ?? []}
              />
              <Field
                label="Instructions"
                placeholder="After meals"
                value={it.instructions ?? ''}
                onChange={(v) => updateItem(idx, { instructions: v })}
              />
            </div>
          </div>
        ))}

        <button
          type="button"
          onClick={addItem}
          className="inline-flex items-center gap-1 rounded-md border border-dashed border-denseSurface-border px-3 py-1.5 text-xs font-semibold text-ink-2 transition-colors hover:border-brand-500 hover:text-brand-700"
        >
          <Plus className="h-3.5 w-3.5" /> Add medication
        </button>

        {patientUserId ? (
          <DrugCheckWarnings
            patientUserId={patientUserId}
            proposedMedications={cleanedItems.map((i) => ({
              name: i.medicationName,
              genericName: i.genericName,
              dose: i.dose,
              frequency: i.frequency,
            }))}
            onOverrideChange={setSafetyOverridesOk}
          />
        ) : null}

        {interaction && interaction.warnings.length > 0 ? (
          <ul className="space-y-1.5">
            {interaction.warnings.map((w, i) => (
              <li
                key={i}
                className={[
                  'flex items-start gap-2 rounded border p-2 text-xs',
                  w.severity === 'high'
                    ? 'border-danger-500/40 bg-danger-500/5 text-danger-500'
                    : w.severity === 'moderate'
                      ? 'border-warning-500/30 bg-warning-500/5 text-warning-500'
                      : 'border-denseSurface-border bg-denseSurface-bg text-ink-2',
                ].join(' ')}
              >
                <AlertTriangle className="mt-0.5 h-3.5 w-3.5 flex-shrink-0" />
                <div>
                  <p className="font-semibold">
                    {w.drugs.join(' + ')}
                  </p>
                  <p className="opacity-90">{w.description}</p>
                  <p className="mt-0.5 italic opacity-80">{w.recommendation}</p>
                </div>
              </li>
            ))}
          </ul>
        ) : null}

        {error ? (
          <div className="flex items-start gap-2 rounded-md border border-danger-500/30 bg-danger-500/5 p-2 text-xs text-danger-500">
            <AlertTriangle className="mt-0.5 h-3.5 w-3.5 flex-shrink-0" />
            <span>{error}</span>
          </div>
        ) : null}

        <div className="flex flex-wrap items-center gap-2 border-t border-denseSurface-border pt-3">
          <button
            type="button"
            onClick={() => void runInteractionCheck()}
            disabled={checking || cleanedItems.length === 0}
            className="inline-flex items-center gap-1.5 rounded-md border border-denseSurface-border bg-white px-3 py-1.5 text-sm font-semibold text-ink-1 transition-colors hover:bg-denseSurface-bg disabled:cursor-not-allowed disabled:opacity-50"
          >
            {checking ? (
              <Loader2 className="h-3.5 w-3.5 animate-spin" />
            ) : (
              <Search className="h-3.5 w-3.5" />
            )}
            Check interactions
          </button>
          <button
            type="button"
            onClick={() => void savePrescription()}
            disabled={
              saving ||
              cleanedItems.length === 0 ||
              interaction?.verdict === 'red' ||
              !safetyOverridesOk ||
              !consultStarted
            }
            className="ml-auto inline-flex items-center gap-1.5 rounded-md bg-brand-500 px-3 py-1.5 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-brand-600 disabled:cursor-not-allowed disabled:opacity-50"
          >
            {saving ? (
              <Loader2 className="h-3.5 w-3.5 animate-spin" />
            ) : (
              <CheckCircle2 className="h-3.5 w-3.5" />
            )}
            Save prescription
          </button>
          {savedId ? (
            <span className="inline-flex items-center gap-1 text-xs font-semibold text-success-500">
              <CheckCircle2 className="h-3.5 w-3.5" /> Saved
            </span>
          ) : null}
        </div>
      </div>
    </DenseCard>
  );
}

function VerdictPill({
  verdict,
}: {
  verdict: InteractionCheckResponse['verdict'];
}) {
  if (verdict === 'green') {
    return <StatusPill tone="success" dot>No interactions</StatusPill>;
  }
  if (verdict === 'yellow') {
    return <StatusPill tone="warning" dot>Review interactions</StatusPill>;
  }
  return <StatusPill tone="danger" dot>Stop — high risk</StatusPill>;
}

function Field({
  label,
  value,
  onChange,
  placeholder,
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
}) {
  return (
    <div>
      <label className="block text-[10px] font-semibold uppercase tracking-wide text-ink-2">
        {label}
      </label>
      <input
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        className="mt-1 h-9 w-full rounded-md border border-denseSurface-border bg-white px-2 text-sm text-ink-1 focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-500/30"
      />
    </div>
  );
}

function SelectOrInput({
  label,
  value,
  onChange,
  options,
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
  options: string[];
}) {
  // Render a datalist-backed input so the doctor can either pick from the
  // canonical set or type free-text (PO once-daily-on-Tuesdays etc).
  const listId = `dl-${label.toLowerCase().replace(/\s+/g, '-')}`;
  return (
    <div>
      <label className="block text-[10px] font-semibold uppercase tracking-wide text-ink-2">
        {label}
      </label>
      <input
        list={listId}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className="mt-1 h-9 w-full rounded-md border border-denseSurface-border bg-white px-2 text-sm text-ink-1 focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-500/30"
      />
      <datalist id={listId}>
        {options.map((o) => (
          <option key={o} value={o} />
        ))}
      </datalist>
    </div>
  );
}

function MedicationField({
  value,
  onChange,
  lookups,
}: {
  value: string;
  onChange: (v: { name: string; generic?: string }) => void;
  lookups: EmrLookups | null;
}) {
  const meds = lookups?.commonMedications ?? [];
  const listId = 'dl-medication';
  return (
    <div className="sm:col-span-2">
      <label className="block text-[10px] font-semibold uppercase tracking-wide text-ink-2">
        Medication
      </label>
      <input
        list={listId}
        value={value}
        onChange={(e) => {
          const name = e.target.value;
          const match = meds.find(
            (m) => m.name.toLowerCase() === name.toLowerCase(),
          );
          onChange({ name, generic: match?.generic });
        }}
        placeholder="Search medication name"
        className="mt-1 h-9 w-full rounded-md border border-denseSurface-border bg-white px-2 text-sm text-ink-1 focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-500/30"
      />
      <datalist id={listId}>
        {meds.map((m) => (
          <option key={m.name} value={m.name}>
            {m.generic}
          </option>
        ))}
      </datalist>
    </div>
  );
}
