"use client";

import { CircleCheck, Clock, Pill, Search, Users } from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";

import { PrescriptionDetailSheet } from "@/components/prescriptions/prescription-detail-sheet";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import {
  type Prescription,
  formatPrescribedAt,
  listPrescriptions,
  updatePrescription,
} from "@/lib/prescriptions";
import { notify } from "@/lib/toast";

// "3 days" / "14 days" / "1 month" → a course length in days; null for
// open-ended values ("Ongoing", "As needed", free text we can't parse).
function parseDurationDays(duration: string | null): number | null {
  if (!duration) return null;
  const match = duration
    .trim()
    .toLowerCase()
    .match(/^(\d+)\s*(day|week|month)s?$/);
  if (!match) return null;
  const n = Number(match[1]);
  const unit = match[2] === "day" ? 1 : match[2] === "week" ? 7 : 30;
  return n * unit;
}

// When an active course runs out, or null if it has no parseable end.
function expiresAt(rx: Prescription): Date | null {
  const days = parseDurationDays(rx.duration);
  if (days == null) return null;
  const end = new Date(`${rx.prescribedAt}T00:00:00`);
  end.setDate(end.getDate() + days);
  return end;
}

function Kpi({
  label,
  value,
  icon: Icon,
}: {
  label: string;
  value: string;
  icon: typeof Pill;
}) {
  return (
    <Card className="flex-row items-center gap-3 p-4">
      <div className="flex size-9 items-center justify-center rounded-lg border bg-background text-muted-foreground">
        <Icon className="size-4" />
      </div>
      <div className="flex flex-col">
        <span className="text-muted-foreground text-xs">{label}</span>
        <span className="font-semibold text-foreground text-lg tracking-tight">
          {value}
        </span>
      </div>
    </Card>
  );
}

function QueueRow({
  rx,
  expiring,
  onOpen,
  onComplete,
}: {
  rx: Prescription;
  expiring: boolean;
  onOpen: () => void;
  onComplete: () => void;
}) {
  const { t } = useTranslation();
  return (
    <div
      className="flex cursor-pointer items-center gap-3 px-4 py-3 transition-colors hover:bg-accent/50"
      onClick={onOpen}
      onKeyDown={(event) => {
        if (event.key === "Enter" || event.key === " ") {
          event.preventDefault();
          onOpen();
        }
      }}
      role="button"
      tabIndex={0}
    >
      <Avatar className="size-8">
        <AvatarFallback>{rx.initials}</AvatarFallback>
      </Avatar>
      <div className="flex min-w-0 flex-1 flex-col">
        <span className="truncate font-medium text-foreground text-sm">
          {rx.medication}
          {rx.dose && (
            <span className="font-normal text-muted-foreground"> · {rx.dose}</span>
          )}
        </span>
        <span className="truncate text-muted-foreground text-xs">
          {rx.name} · #{rx.fileNumber} · {rx.frequency}
        </span>
      </div>
      <div className="hidden min-w-0 flex-col items-end sm:flex">
        <span className="truncate text-foreground text-xs">{rx.prescriber}</span>
        <span className="text-muted-foreground text-xs">
          {formatPrescribedAt(rx.prescribedAt)}
        </span>
      </div>
      {expiring && (
        <Badge variant="destructive">{t("pharmacy.expiringBadge")}</Badge>
      )}
      <Button
        onClick={(event) => {
          event.stopPropagation();
          onComplete();
        }}
        size="sm"
        type="button"
        variant="outline"
      >
        <CircleCheck className="size-4" />
        {t("pharmacy.markCompleted")}
      </Button>
    </div>
  );
}

// The pharmacy department home: a dispensing work queue over the clinic's
// prescriptions. Pharmacy holds prescription read/write (no delete and no
// create UI — prescribing stays with clinicians), so the only action here is
// completing a course.
export function PharmacyView() {
  const { t } = useTranslation();
  const [list, setList] = useState<Prescription[]>([]);
  const [selected, setSelected] = useState<Prescription | null>(null);
  const [sheetOpen, setSheetOpen] = useState(false);
  const [query, setQuery] = useState("");

  useEffect(() => {
    let active = true;
    listPrescriptions()
      .then((data) => {
        if (active) setList(data);
      })
      .catch(() => {
        /* api-client redirects on 401; otherwise leave the list empty */
      });
    return () => {
      active = false;
    };
  }, []);

  const now = new Date();
  // Start of today, so a course ending today still counts as expiring (not
  // already elapsed by a few hours).
  const startOfToday = new Date(now);
  startOfToday.setHours(0, 0, 0, 0);
  const soon = new Date(now);
  soon.setDate(soon.getDate() + 7);
  const isExpiringSoon = (rx: Prescription) => {
    if (rx.status !== "active") return false;
    const end = expiresAt(rx);
    // Only courses ending in the next 7 days — not ones that already elapsed.
    return end != null && end >= startOfToday && end <= soon;
  };

  const active = useMemo(
    () => list.filter((rx) => rx.status === "active"),
    [list],
  );

  // The dispensing queue: active prescriptions, oldest first.
  const search = query.trim().toLowerCase();
  const queue = useMemo(() => {
    const base = [...active].sort((a, b) =>
      a.prescribedAt.localeCompare(b.prescribedAt),
    );
    if (!search) return base;
    return base.filter(
      (rx) =>
        rx.name.toLowerCase().includes(search) ||
        rx.fileNumber.includes(search) ||
        rx.medication.toLowerCase().includes(search) ||
        rx.prescriber.toLowerCase().includes(search),
    );
  }, [active, search]);

  const kpis = [
    {
      label: t("pharmacy.kpi.active"),
      value: String(active.length),
      icon: Pill,
    },
    {
      label: t("pharmacy.kpi.expiring"),
      value: String(active.filter(isExpiringSoon).length),
      icon: Clock,
    },
    {
      label: t("pharmacy.kpi.patients"),
      value: String(new Set(active.map((rx) => rx.fileNumber)).size),
      icon: Users,
    },
  ];

  const openRx = (rx: Prescription) => {
    setSelected(rx);
    setSheetOpen(true);
  };

  // PUT requires the full record — resend the row with the new status.
  const markCompleted = async (rx: Prescription) => {
    try {
      const updated = await updatePrescription(rx.id, {
        fileNumber: rx.fileNumber,
        name: rx.name,
        initials: rx.initials,
        medication: rx.medication,
        dose: rx.dose,
        frequency: rx.frequency,
        prescriber: rx.prescriber,
        prescribedAt: rx.prescribedAt,
        status: "completed",
        duration: rx.duration,
        notes: rx.notes,
      });
      setList((prev) => prev.map((p) => (p.id === updated.id ? updated : p)));
      notify.success(
        t("pharmacy.completedTitle"),
        t("pharmacy.completedBody", { medication: rx.medication, name: rx.name }),
      );
    } catch {
      notify.error(t("pharmacy.completeFailedTitle"), t("pharmacy.completeFailedBody"));
    }
  };

  return (
    <div className="mx-auto flex w-full max-w-5xl flex-col gap-10 px-6 py-10">
      <div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
        <div>
          <h1 className="font-semibold text-2xl tracking-tight">
            {t("pharmacy.title")}
          </h1>
          <p className="text-muted-foreground text-sm">{t("pharmacy.subtitle")}</p>
        </div>
        <div className="relative">
          <Search className="-translate-y-1/2 absolute top-1/2 left-3 size-4 text-muted-foreground" />
          <Input
            className="w-full pl-9 sm:w-64"
            onChange={(event) => setQuery(event.target.value)}
            placeholder={t("pharmacy.searchPlaceholder")}
            value={query}
          />
        </div>
      </div>

      <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
        {kpis.map((k) => (
          <Kpi key={k.label} {...k} />
        ))}
      </div>

      <section className="flex flex-col gap-3">
        <div>
          <h2 className="font-semibold text-lg tracking-tight">
            {t("pharmacy.queue.title")}
          </h2>
          <p className="text-muted-foreground text-sm">
            {t("pharmacy.queue.description")}
          </p>
        </div>
        <div className="divide-y divide-border overflow-hidden rounded-2xl border bg-card/30">
          {queue.map((rx) => (
            <QueueRow
              expiring={isExpiringSoon(rx)}
              key={rx.id}
              onComplete={() => markCompleted(rx)}
              onOpen={() => openRx(rx)}
              rx={rx}
            />
          ))}
          {queue.length === 0 && (
            <p className="p-6 text-center text-muted-foreground text-sm">
              {search ? t("pharmacy.queue.noMatches") : t("pharmacy.queue.empty")}
            </p>
          )}
        </div>
      </section>

      <PrescriptionDetailSheet
        onOpenChange={setSheetOpen}
        open={sheetOpen}
        rx={selected}
      />
    </div>
  );
}
