'use client';

import { useEffect, useRef, useState } from 'react';
import { AlertTriangle, Info, ShieldAlert, Loader2 } from 'lucide-react';

/**
 * F6 — Patient-aware safety warnings displayed inline above the Rx form.
 *
 * The doctor edits medication rows; this component debounces 500ms after the
 * last edit, calls `/api/doctors/me/drug-check`, and renders a coloured strip
 * of warnings. High-severity warnings expose an "Override" checkbox; the
 * parent (the Rx form) reads `allHighOverridden` via the `onOverrideChange`
 * callback to gate submission.
 *
 * If the endpoint 404s the component hides itself entirely (no toast) and
 * reports `allHighOverridden=true` so it never blocks the Rx form.
 */

export interface DrugCheckWarning {
  severity: 'low' | 'medium' | 'high';
  kind: 'allergy' | 'interaction' | 'duplicate' | 'condition';
  proposedMedication: string;
  conflictsWith: string;
  explanation: string;
}

interface DrugCheckProposedMed {
  name: string;
  genericName?: string;
  dose?: string;
  frequency?: string;
}

interface DrugCheckWarningsProps {
  patientUserId: string;
  proposedMedications: DrugCheckProposedMed[];
  /**
   * Called with `true` when there are zero high-severity warnings OR when all
   * high warnings have been acknowledged via the override checkbox. The Rx
   * form must gate its submit button on this.
   */
  onOverrideChange?: (allHighOverridden: boolean) => void;
}

const DEBOUNCE_MS = 500;

export function DrugCheckWarnings({
  patientUserId,
  proposedMedications,
  onOverrideChange,
}: DrugCheckWarningsProps) {
  const [warnings, setWarnings] = useState<DrugCheckWarning[]>([]);
  const [overrides, setOverrides] = useState<Record<number, boolean>>({});
  const [loading, setLoading] = useState(false);
  const [hidden, setHidden] = useState(false); // true after a 404 → endpoint unavailable
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const requestId = useRef(0);

  // Stable string-key digest so we only re-fire when meds actually change.
  const cleanedMeds = proposedMedications.filter((m) => m.name.trim());
  const digest = JSON.stringify(
    cleanedMeds.map((m) => ({
      name: m.name.trim().toLowerCase(),
      generic: m.genericName?.trim().toLowerCase() ?? null,
      dose: m.dose?.trim() ?? null,
      freq: m.frequency?.trim() ?? null,
    })),
  );

  useEffect(() => {
    if (hidden) return;
    if (cleanedMeds.length === 0) {
      setWarnings([]);
      setOverrides({});
      return;
    }
    if (debounceRef.current) clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(() => {
      const myId = ++requestId.current;
      setLoading(true);
      void (async () => {
        try {
          const res = await fetch('/api/doctors/me/drug-check', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
              patientUserId,
              proposedMedications: cleanedMeds,
            }),
          });
          if (myId !== requestId.current) return; // a newer request superseded us
          if (res.status === 404) {
            // Endpoint not yet shipped — hide for the rest of the session.
            setHidden(true);
            setWarnings([]);
            return;
          }
          if (!res.ok) {
            // Soft-fail: don't surface an error toast, just clear warnings.
            setWarnings([]);
            return;
          }
          const data = (await res.json()) as { warnings?: DrugCheckWarning[] };
          setWarnings(Array.isArray(data.warnings) ? data.warnings : []);
          // Reset overrides — the warning set changed.
          setOverrides({});
        } catch {
          // Network blip — leave previous state.
        } finally {
          if (myId === requestId.current) setLoading(false);
        }
      })();
    }, DEBOUNCE_MS);
    return () => {
      if (debounceRef.current) clearTimeout(debounceRef.current);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [digest, patientUserId, hidden]);

  // Report override status upward.
  useEffect(() => {
    if (hidden) {
      onOverrideChange?.(true);
      return;
    }
    const highs = warnings
      .map((w, i) => ({ w, i }))
      .filter((x) => x.w.severity === 'high');
    const allOk = highs.every((x) => overrides[x.i]);
    onOverrideChange?.(allOk);
  }, [warnings, overrides, hidden, onOverrideChange]);

  if (hidden) return null;
  if (cleanedMeds.length === 0) return null;
  if (warnings.length === 0 && !loading) return null;

  return (
    <div className="space-y-1.5">
      {loading ? (
        <div className="flex items-center gap-1.5 text-[11px] text-ink-3">
          <Loader2 className="h-3 w-3 animate-spin" /> Checking patient safety…
        </div>
      ) : null}
      {warnings.map((w, i) => (
        <WarningRow
          key={`${w.proposedMedication}-${w.conflictsWith}-${i}`}
          warning={w}
          overridden={!!overrides[i]}
          onOverride={(v) =>
            setOverrides((prev) => ({ ...prev, [i]: v }))
          }
        />
      ))}
    </div>
  );
}

function WarningRow({
  warning,
  overridden,
  onOverride,
}: {
  warning: DrugCheckWarning;
  overridden: boolean;
  onOverride: (v: boolean) => void;
}) {
  const palette =
    warning.severity === 'high'
      ? 'border-danger-500/40 bg-danger-500/5 text-danger-500'
      : warning.severity === 'medium'
        ? 'border-warning-500/40 bg-warning-500/10 text-warning-500'
        : 'border-brand-500/30 bg-brand-500/5 text-brand-700';
  const Icon =
    warning.severity === 'high'
      ? ShieldAlert
      : warning.severity === 'medium'
        ? AlertTriangle
        : Info;
  return (
    <div className={['rounded-md border p-2', palette].join(' ')}>
      <div className="flex items-start gap-2">
        <Icon className="mt-0.5 h-3.5 w-3.5 flex-shrink-0" />
        <div className="min-w-0 flex-1 text-xs">
          <p className="font-semibold">
            {warning.proposedMedication}
            {warning.conflictsWith ? (
              <>
                {' '}
                <span className="opacity-60">×</span>{' '}
                <span>{warning.conflictsWith}</span>
              </>
            ) : null}
            <span className="ml-1 rounded bg-white/40 px-1 py-0.5 font-mono text-[10px] uppercase opacity-80">
              {warning.kind}
            </span>
          </p>
          <p className="mt-0.5 opacity-90">{warning.explanation}</p>
          {warning.severity === 'high' ? (
            <label className="mt-1.5 inline-flex items-center gap-1.5 text-[11px] font-semibold">
              <input
                type="checkbox"
                checked={overridden}
                onChange={(e) => onOverride(e.target.checked)}
                className="h-3.5 w-3.5 rounded border-danger-500 text-danger-500 focus:ring-danger-500"
              />
              Override — I have reviewed and accept the risk
            </label>
          ) : null}
        </div>
      </div>
    </div>
  );
}
