'use client';

import { useMemo, useState } from 'react';
import {
  Sparkles,
  FileText,
  Pill,
  Stethoscope,
  AlertTriangle,
  CheckCircle2,
  AlertCircle,
  Plus,
  Trash2,
  Flag,
  Mic,
} from 'lucide-react';
import { Button, GlassCard } from '@sehat/ui';
import { api, copilot, ApiClientError } from '@/lib/api-client';
import {
  formatTokenUsage,
  normalizeSoapDraftResponse,
} from '@/lib/copilot-normalize';
import type {
  CopilotInteractionSeverity,
  DifferentialResponse,
  DrugInteractionsResponse,
  SoapDraftResponse,
} from '@/lib/copilot-types';
import { ScribeRecorder } from './scribe-recorder';

type TabKey = 'soap' | 'interactions' | 'differential' | 'scribe';

interface CopilotPanelProps {
  appointmentId: string;
  patientId: string;
  /** Optional seed medications (e.g. from prescription form on the same page). */
  initialMedications?: string[];
}

export function CopilotPanel({
  appointmentId,
  patientId,
  initialMedications,
}: CopilotPanelProps) {
  const [tab, setTab] = useState<TabKey>('soap');

  return (
    <GlassCard tone="light" padding="lg" className="mt-6">
      <div className="flex items-center gap-2">
        <div className="flex h-9 w-9 items-center justify-center rounded-lg bg-gradient-accent">
          <Sparkles className="h-5 w-5 text-white" />
        </div>
        <div>
          <h2 className="text-lg font-bold text-ink">AI Co-Pilot</h2>
          <p className="text-xs text-ink-muted">
            Drafts and safety checks — clinician review required before saving.
          </p>
        </div>
      </div>

      <div
        role="tablist"
        aria-label="Co-Pilot tabs"
        className="mt-5 flex flex-wrap gap-2 border-b border-surface-border"
      >
        <TabButton
          active={tab === 'soap'}
          onClick={() => setTab('soap')}
          icon={FileText}
          label="SOAP draft"
        />
        <TabButton
          active={tab === 'interactions'}
          onClick={() => setTab('interactions')}
          icon={Pill}
          label="Drug interactions"
        />
        <TabButton
          active={tab === 'differential'}
          onClick={() => setTab('differential')}
          icon={Stethoscope}
          label="Differential"
        />
        <TabButton
          active={tab === 'scribe'}
          onClick={() => setTab('scribe')}
          icon={Mic}
          label="Scribe"
        />
      </div>

      <div className="mt-5">
        {tab === 'soap' ? <SoapTab appointmentId={appointmentId} /> : null}
        {tab === 'interactions' ? (
          <InteractionsTab
            patientId={patientId}
            initialMedications={initialMedications}
          />
        ) : null}
        {tab === 'differential' ? (
          <DifferentialTab appointmentId={appointmentId} />
        ) : null}
        {tab === 'scribe' ? (
          <ScribeRecorder appointmentId={appointmentId} />
        ) : null}
      </div>
    </GlassCard>
  );
}

function TabButton({
  active,
  onClick,
  icon: Icon,
  label,
}: {
  active: boolean;
  onClick: () => void;
  icon: typeof FileText;
  label: string;
}) {
  return (
    <button
      type="button"
      role="tab"
      aria-selected={active}
      onClick={onClick}
      className={[
        '-mb-px inline-flex items-center gap-2 border-b-2 px-3 py-2 text-sm font-semibold transition-colors',
        active
          ? 'border-brand text-brand'
          : 'border-transparent text-ink-muted hover:text-ink',
      ].join(' ')}
    >
      <Icon className="h-4 w-4" /> {label}
    </button>
  );
}

// ============================================================
// Tab 1 — SOAP draft
// ============================================================

function SoapTab({ appointmentId }: { appointmentId: string }) {
  const [doctorNotes, setDoctorNotes] = useState('');
  const [draft, setDraft] = useState<SoapDraftResponse | null>(null);
  const [subjective, setSubjective] = useState('');
  const [objective, setObjective] = useState('');
  const [assessment, setAssessment] = useState('');
  const [plan, setPlan] = useState('');
  const [followUpInWeeks, setFollowUpInWeeks] = useState<number | undefined>();

  const [generating, setGenerating] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [saved, setSaved] = useState(false);

  async function generate() {
    if (!doctorNotes.trim()) return;
    setGenerating(true);
    setError(null);
    setSaved(false);
    try {
      const res = await copilot.soapDraft({
        appointmentId,
        doctorNotes: doctorNotes.trim(),
      });
      const normalized = normalizeSoapDraftResponse(res);
      setDraft(normalized);
      setSubjective(normalized.subjective);
      setObjective(normalized.objective);
      setAssessment(normalized.assessment);
      setPlan(normalized.plan);
      setFollowUpInWeeks(normalized.followUpInWeeks ?? undefined);
    } catch (e) {
      setError(e instanceof ApiClientError ? e.message : 'Failed to generate draft');
    } finally {
      setGenerating(false);
    }
  }

  async function approveAndSave() {
    setSaving(true);
    setError(null);
    try {
      await api.saveAppointmentNotes(appointmentId, {
        subjective: subjective.trim() || undefined,
        objective: objective.trim() || undefined,
        assessment: assessment.trim() || undefined,
        plan: plan.trim() || undefined,
        followUpInWeeks,
      });
      setSaved(true);
    } catch (e) {
      setError(e instanceof ApiClientError ? e.message : 'Failed to save notes');
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="space-y-4">
      <div className="space-y-1.5">
        <label className="text-sm font-medium text-ink-muted">
          Your quick notes
        </label>
        <textarea
          value={doctorNotes}
          onChange={(e) => setDoctorNotes(e.target.value)}
          placeholder="e.g. patient reports persistent cough x3 weeks, no fever, mild SOB on exertion"
          rows={3}
          className="w-full rounded-lg border border-surface-border bg-white px-3 py-2 text-sm text-ink focus:border-brand focus:outline-none focus:ring-2 focus:ring-brand/30"
        />
      </div>

      <Button
        type="button"
        variant="primary"
        size="md"
        loading={generating}
        disabled={!doctorNotes.trim()}
        onClick={() => void generate()}
      >
        <Sparkles className="h-4 w-4" /> Generate draft
      </Button>

      {error ? <ErrorBanner message={error} /> : null}

      {draft ? (
        <div className="space-y-4">
          <SoapField label="Subjective" value={subjective} onChange={setSubjective} />
          <SoapField label="Objective" value={objective} onChange={setObjective} />
          <SoapField label="Assessment" value={assessment} onChange={setAssessment} />
          <SoapField label="Plan" value={plan} onChange={setPlan} />

          <div className="space-y-1.5">
            <label className="text-sm font-medium text-ink-muted">
              Follow-up (weeks)
            </label>
            <input
              type="number"
              min={0}
              value={followUpInWeeks ?? ''}
              onChange={(e) =>
                setFollowUpInWeeks(
                  e.target.value === '' ? undefined : Number(e.target.value),
                )
              }
              className="h-11 w-32 rounded-lg border border-surface-border bg-white px-3 text-sm text-ink focus:border-brand focus:outline-none focus:ring-2 focus:ring-brand/30"
            />
          </div>

          <div className="flex flex-wrap items-center gap-3">
            <Button
              type="button"
              variant="primary"
              size="md"
              loading={saving}
              onClick={() => void approveAndSave()}
            >
              <CheckCircle2 className="h-4 w-4" /> Approve &amp; save
            </Button>
            {saved ? (
              <span className="inline-flex items-center gap-1 text-sm font-semibold text-green-700">
                <CheckCircle2 className="h-4 w-4" /> Saved to consultation notes
              </span>
            ) : null}
          </div>

          <p className="text-[11px] text-ink-subtle">
            Model: <span className="font-mono">{draft.modelVersion}</span> · Tokens
            used:{' '}
            <span className="font-mono">{formatTokenUsage(draft.tokensUsed)}</span>
          </p>
        </div>
      ) : null}
    </div>
  );
}

function SoapField({
  label,
  value,
  onChange,
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
}) {
  return (
    <div className="space-y-1.5">
      <label className="text-sm font-semibold text-ink">{label}</label>
      <textarea
        value={value}
        onChange={(e) => onChange(e.target.value)}
        rows={3}
        className="w-full rounded-lg border border-surface-border bg-white px-3 py-2 text-sm text-ink focus:border-brand focus:outline-none focus:ring-2 focus:ring-brand/30"
      />
    </div>
  );
}

// ============================================================
// Tab 2 — Drug interactions
// ============================================================

const SEVERITY_ORDER: Record<CopilotInteractionSeverity, number> = {
  severe: 0,
  moderate: 1,
  minor: 2,
};

const SEVERITY_STYLE: Record<
  CopilotInteractionSeverity,
  { card: string; pill: string; label: string }
> = {
  severe: {
    card: 'border-error/40 bg-error/5',
    pill: 'bg-error/15 text-error',
    label: 'Severe',
  },
  moderate: {
    card: 'border-accent/40 bg-accent/5',
    pill: 'bg-accent/15 text-accent-dark',
    label: 'Moderate',
  },
  minor: {
    card: 'border-brand/30 bg-brand/5',
    pill: 'bg-brand/15 text-brand',
    label: 'Minor',
  },
};

function InteractionsTab({
  patientId,
  initialMedications,
}: {
  patientId: string;
  initialMedications?: string[];
}) {
  const [meds, setMeds] = useState<string[]>(
    initialMedications && initialMedications.length > 0
      ? initialMedications
      : [''],
  );
  const [result, setResult] = useState<DrugInteractionsResponse | null>(null);
  const [checking, setChecking] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const cleaned = useMemo(
    () => meds.map((m) => m.trim()).filter((m) => m.length > 0),
    [meds],
  );

  async function runCheck() {
    if (cleaned.length === 0) return;
    setChecking(true);
    setError(null);
    try {
      const res = await copilot.drugInteractions({
        patientId,
        proposedMedications: cleaned,
      });
      setResult(res);
    } catch (e) {
      setError(e instanceof ApiClientError ? e.message : 'Interaction check failed');
    } finally {
      setChecking(false);
    }
  }

  const sortedFindings = useMemo(() => {
    if (!result) return [];
    return [...result.findings].sort(
      (a, b) => SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity],
    );
  }, [result]);

  return (
    <div className="space-y-4">
      <div className="space-y-1.5">
        <label className="text-sm font-medium text-ink-muted">
          Proposed medications
        </label>
        <div className="space-y-2">
          {meds.map((m, idx) => (
            <div key={idx} className="flex items-center gap-2">
              <input
                value={m}
                onChange={(e) =>
                  setMeds((arr) => arr.map((x, i) => (i === idx ? e.target.value : x)))
                }
                placeholder="e.g. Warfarin 5mg"
                className="h-11 flex-1 rounded-lg border border-surface-border bg-white px-3 text-sm text-ink focus:border-brand focus:outline-none focus:ring-2 focus:ring-brand/30"
              />
              {meds.length > 1 ? (
                <button
                  type="button"
                  onClick={() =>
                    setMeds((arr) => arr.filter((_, i) => i !== idx))
                  }
                  className="rounded p-2 text-ink-subtle hover:bg-error/10 hover:text-error"
                  aria-label="Remove medication"
                >
                  <Trash2 className="h-4 w-4" />
                </button>
              ) : null}
            </div>
          ))}
          <button
            type="button"
            onClick={() => setMeds((arr) => [...arr, ''])}
            className="inline-flex items-center gap-1 rounded-lg bg-brand/10 px-3 py-1.5 text-sm font-semibold text-brand hover:bg-brand/20"
          >
            <Plus className="h-4 w-4" /> Add medication
          </button>
        </div>
      </div>

      <Button
        type="button"
        variant="primary"
        size="md"
        loading={checking}
        disabled={cleaned.length === 0}
        onClick={() => void runCheck()}
      >
        <Sparkles className="h-4 w-4" /> Check
      </Button>

      {error ? <ErrorBanner message={error} /> : null}

      {result ? (
        <div className="space-y-3">
          {result.requiresReview ? (
            <GlassCard
              tone="light"
              padding="md"
              className="border-error/40 bg-error/10"
            >
              <div className="flex items-start gap-2 text-error">
                <AlertTriangle className="mt-0.5 h-4 w-4 flex-shrink-0" />
                <p className="text-sm font-bold">
                  Doctor review required before prescribing
                </p>
              </div>
            </GlassCard>
          ) : null}

          {result.summary ? (
            <p className="text-sm text-ink-muted">{result.summary}</p>
          ) : null}

          {sortedFindings.length === 0 ? (
            <GlassCard tone="light" padding="md" className="bg-green-50">
              <div className="flex items-start gap-2 text-green-700">
                <CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0" />
                <p className="text-sm font-semibold">
                  No clinically significant interactions detected
                </p>
              </div>
            </GlassCard>
          ) : (
            <ul className="space-y-3">
              {sortedFindings.map((f, i) => {
                const style = SEVERITY_STYLE[f.severity];
                return (
                  <li key={i}>
                    <GlassCard
                      tone="light"
                      padding="md"
                      className={`border ${style.card}`}
                    >
                      <div className="flex flex-wrap items-center gap-2">
                        <span
                          className={`rounded-pill px-2 py-0.5 text-[10px] font-bold uppercase ${style.pill}`}
                        >
                          {style.label}
                        </span>
                        <p className="text-sm font-bold text-ink">
                          {f.proposed}{' '}
                          <span className="text-ink-subtle">&#9888;</span>{' '}
                          {f.conflictWith}
                        </p>
                      </div>
                      <p className="mt-2 text-sm text-ink-muted">
                        <span className="font-semibold text-ink">Mechanism:</span>{' '}
                        {f.mechanism}
                      </p>
                      <p className="mt-1 text-sm text-ink">
                        <span className="font-semibold">Recommendation:</span>{' '}
                        {f.recommendation}
                      </p>
                    </GlassCard>
                  </li>
                );
              })}
            </ul>
          )}
        </div>
      ) : null}
    </div>
  );
}

// ============================================================
// Tab 3 — Differential
// ============================================================

const LIKELIHOOD_PILL: Record<'high' | 'moderate' | 'low', string> = {
  high: 'bg-brand/15 text-brand',
  moderate: 'bg-accent/15 text-accent-dark',
  low: 'bg-surface-alt text-ink-muted',
};

function DifferentialTab({ appointmentId }: { appointmentId: string }) {
  const [result, setResult] = useState<DifferentialResponse | null>(null);
  const [generating, setGenerating] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function generate() {
    setGenerating(true);
    setError(null);
    try {
      const res = await copilot.differential({ appointmentId });
      setResult(res);
    } catch (e) {
      setError(
        e instanceof ApiClientError ? e.message : 'Failed to generate differential',
      );
    } finally {
      setGenerating(false);
    }
  }

  return (
    <div className="space-y-4">
      <Button
        type="button"
        variant="primary"
        size="md"
        loading={generating}
        onClick={() => void generate()}
      >
        <Sparkles className="h-4 w-4" /> Generate differential
      </Button>

      {error ? <ErrorBanner message={error} /> : null}

      {result ? (
        <>
          {result.differentials.length === 0 ? (
            <GlassCard tone="light" padding="md">
              <p className="text-sm text-ink-muted">
                No differentials generated for this encounter.
              </p>
            </GlassCard>
          ) : (
            <ul className="space-y-3">
              {result.differentials.map((d, i) => (
                <li key={i}>
                  <GlassCard
                    tone="light"
                    padding="md"
                    className={
                      d.redFlag ? 'border border-error/40 bg-error/5' : ''
                    }
                  >
                    <div className="flex flex-wrap items-center gap-2">
                      <h3 className="text-base font-bold text-ink">{d.name}</h3>
                      <span
                        className={`rounded-pill px-2 py-0.5 text-[10px] font-bold uppercase ${LIKELIHOOD_PILL[d.likelihood]}`}
                      >
                        {d.likelihood}
                      </span>
                      {d.redFlag ? (
                        <span className="inline-flex items-center gap-1 rounded-pill bg-error/15 px-2 py-0.5 text-[10px] font-bold uppercase text-error">
                          <Flag className="h-3 w-3" /> Red flag
                        </span>
                      ) : null}
                    </div>
                    {d.keyDiscriminators.length > 0 ? (
                      <ul className="mt-2 list-disc space-y-1 pl-5 text-sm text-ink-muted">
                        {d.keyDiscriminators.map((k, j) => (
                          <li key={j}>{k}</li>
                        ))}
                      </ul>
                    ) : null}
                  </GlassCard>
                </li>
              ))}
            </ul>
          )}
          {result.notes ? (
            <p className="text-xs italic text-ink-muted">{result.notes}</p>
          ) : null}
        </>
      ) : null}
    </div>
  );
}

// ============================================================
// Shared
// ============================================================

function ErrorBanner({ message }: { message: string }) {
  return (
    <GlassCard tone="light" padding="md" className="border-error/40 bg-error/10">
      <div className="flex items-start gap-2 text-error">
        <AlertCircle className="mt-0.5 h-4 w-4 flex-shrink-0" />
        <p className="text-sm">{message}</p>
      </div>
    </GlassCard>
  );
}
