"use client";

import { useActionState, useEffect, useMemo, useRef, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { ArrowRight, CheckCircle2, FileUp, Loader2, Send, Sparkles, TrendingDown, Upload } from "lucide-react";
import { toast } from "sonner";

import { Progress } from "@/components/ui/progress";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { TeethChart } from "@/components/teeth-chart";
import { Textarea } from "@/components/ui/textarea";
import { createJobAction } from "@/lib/appwrite/job-actions";
import {
  PROSTHETIC_TYPE_LABELS,
  initialJobFormState,
} from "@/lib/appwrite/job-types";
import type { JobCounterpart } from "@/lib/appwrite/job-queries";
import type { ProstheticType } from "@/lib/appwrite/schema";

const NONE_PATIENT = "__none__";

type PatientOption = { id: string; code: string; label: string };
type ProstheticOption = {
  id: string;
  name: string;
  type: string;
  unitPrice: number;
  currency?: string;
};

type Quote = {
  amount: number;
  currency: string;
  source: "clinic_custom" | "clinic_discount" | "catalog";
  unitPrice: number;
  catalogUnitPrice?: number;
  catalogTotal?: number;
  savings?: number;
  discountPercent?: number;
  teethCount: number;
};

function formatMoney(amount: number, currency: string): string {
  try {
    return new Intl.NumberFormat("tr-TR", { style: "currency", currency }).format(amount);
  } catch {
    return `${amount.toFixed(2)} ${currency}`;
  }
}

export function NewJobForm({
  labs,
  patients,
  prostheticsByLab,
  defaultCurrency,
}: {
  labs: JobCounterpart[];
  patients: PatientOption[];
  prostheticsByLab: Record<string, ProstheticOption[]>;
  defaultCurrency: string;
}) {
  const router = useRouter();
  const [state, action, pending] = useActionState(createJobAction, initialJobFormState);
  const [patientId, setPatientId] = useState<string>(
    patients.length > 0 ? patients[0].id : NONE_PATIENT,
  );
  const [teeth, setTeeth] = useState<string[]>([]);
  const [labTenantId, setLabTenantId] = useState<string>(labs[0]?.tenantId ?? "");
  const [prostheticId, setProstheticId] = useState<string>("");
  const [quote, setQuote] = useState<Quote | null>(null);
  const [quoteLoading, setQuoteLoading] = useState(false);
  // Wizard step — once the job is created we switch to the file upload step
  // and keep the user on this page until they finish or skip.
  const [step, setStep] = useState<"details" | "files">("details");
  const [createdJobId, setCreatedJobId] = useState<string | null>(null);

  const labProsthetics = prostheticsByLab[labTenantId] ?? [];
  const selectedProsthetic = labProsthetics.find((p) => p.id === prostheticId);

  const patientById = useMemo(
    () => new Map(patients.map((p) => [p.id, p])),
    [patients],
  );
  const selectedPatient = patientId !== NONE_PATIENT ? patientById.get(patientId) : undefined;

  useEffect(() => {
    if (state.ok && state.jobId) {
      toast.success("İş kaydedildi. Dosyaları ekleyebilirsiniz.");
      setCreatedJobId(state.jobId);
      setStep("files");
    } else if (state.error) {
      toast.error(state.error);
    }
  }, [state]);

  // Reset prosthetic selection when the lab changes so we never carry the
  // previous lab's catalog ID over.
  useEffect(() => {
    setProstheticId("");
  }, [labTenantId]);

  // Live price quote — debounced to a single fetch per 250ms when inputs settle.
  useEffect(() => {
    if (!prostheticId || teeth.length === 0) {
      setQuote(null);
      setQuoteLoading(false);
      return;
    }
    setQuoteLoading(true);
    const ctrl = new AbortController();
    const timer = setTimeout(() => {
      fetch("/api/pricing/quote", {
        method: "POST",
        signal: ctrl.signal,
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ prostheticId, teethCount: teeth.length }),
      })
        .then((r) => r.json())
        .then((d) => {
          setQuote(d?.quote ?? null);
          setQuoteLoading(false);
        })
        .catch(() => {
          if (!ctrl.signal.aborted) setQuoteLoading(false);
        });
    }, 250);
    return () => {
      ctrl.abort();
      clearTimeout(timer);
    };
  }, [prostheticId, teeth.length]);

  if (step === "files" && createdJobId) {
    return (
      <FilesStep
        jobId={createdJobId}
        onDone={() => router.push(`/jobs/${createdJobId}`)}
        onSkip={() => router.push("/jobs/outbound")}
      />
    );
  }

  return (
    <form action={action} className="grid gap-5">
      <StepIndicator step="details" />
      <div className="grid gap-3 md:grid-cols-2">
        <div className="grid gap-2 md:col-span-2">
          <Label htmlFor="labTenantId">Laboratuvar *</Label>
          <input type="hidden" name="labTenantId" value={labTenantId} />
          <Select value={labTenantId} onValueChange={setLabTenantId}>
            <SelectTrigger id="labTenantId">
              <SelectValue placeholder="Bir laboratuvar seçin" />
            </SelectTrigger>
            <SelectContent>
              {labs.map((l) => (
                <SelectItem key={l.tenantId} value={l.tenantId}>
                  {l.companyName}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          {state.fieldErrors?.labTenantId && (
            <p className="text-destructive text-xs">{state.fieldErrors.labTenantId}</p>
          )}
        </div>

        <div className="grid gap-2 md:col-span-2">
          <div className="flex items-baseline justify-between gap-3">
            <Label htmlFor="patientId">Hasta</Label>
            <Link
              href="/patients"
              className="text-muted-foreground hover:text-foreground text-xs underline-offset-4 hover:underline"
            >
              + Yeni hasta ekle
            </Link>
          </div>
          <input
            type="hidden"
            name="patientId"
            value={patientId === NONE_PATIENT ? "" : patientId}
          />
          <Select value={patientId} onValueChange={setPatientId}>
            <SelectTrigger id="patientId">
              <SelectValue placeholder="Hasta seçin" />
            </SelectTrigger>
            <SelectContent>
              {patients.map((p) => (
                <SelectItem key={p.id} value={p.id}>
                  {p.label}{" "}
                  <span className="text-muted-foreground ml-1 font-mono text-xs">
                    {p.code}
                  </span>
                </SelectItem>
              ))}
              <SelectItem value={NONE_PATIENT}>
                Hasta listesinde yok — kodu manuel gir
              </SelectItem>
            </SelectContent>
          </Select>
          {state.fieldErrors?.patientId && (
            <p className="text-destructive text-xs">{state.fieldErrors.patientId}</p>
          )}
        </div>

        <div className="grid gap-2">
          <Label htmlFor="patientCode">
            Hasta Kodu *{" "}
            {selectedPatient && (
              <span className="text-muted-foreground text-xs">(seçili hastadan)</span>
            )}
          </Label>
          <Input
            id="patientCode"
            name="patientCode"
            required
            maxLength={50}
            placeholder="Örn. 000892"
            value={selectedPatient?.code ?? undefined}
            defaultValue={selectedPatient ? undefined : ""}
            readOnly={Boolean(selectedPatient)}
            style={{ textTransform: "uppercase" }}
            className="font-mono"
          />
          {state.fieldErrors?.patientCode && (
            <p className="text-destructive text-xs">{state.fieldErrors.patientCode}</p>
          )}
        </div>

        <div className="grid gap-2">
          <Label htmlFor="prostheticId">Ürün *</Label>
          <input type="hidden" name="prostheticId" value={prostheticId} />
          <Select value={prostheticId} onValueChange={setProstheticId} disabled={labProsthetics.length === 0}>
            <SelectTrigger id="prostheticId">
              <SelectValue
                placeholder={
                  labProsthetics.length === 0
                    ? "Laboratuvarın aktif ürünü yok"
                    : "Bir ürün seçin"
                }
              />
            </SelectTrigger>
            <SelectContent>
              {labProsthetics.map((p) => (
                <SelectItem key={p.id} value={p.id}>
                  <span className="flex w-full items-center justify-between gap-3">
                    <span>{p.name}</span>
                    <span className="text-muted-foreground text-xs tabular-nums">
                      {p.unitPrice.toLocaleString("tr-TR")} {p.currency || defaultCurrency} / diş
                    </span>
                  </span>
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          {selectedProsthetic && (
            <p className="text-muted-foreground text-xs">
              Kategori: {PROSTHETIC_TYPE_LABELS[selectedProsthetic.type as ProstheticType] ?? selectedProsthetic.type}
            </p>
          )}
          {state.fieldErrors?.prostheticId && (
            <p className="text-destructive text-xs">{state.fieldErrors.prostheticId}</p>
          )}
        </div>

        <div className="grid gap-2">
          <Label htmlFor="color">Renk (Vita)</Label>
          <Input id="color" name="color" maxLength={20} placeholder="Örn. A2" />
        </div>

        <div className="grid gap-2">
          <Label htmlFor="dueDate">Termin Tarihi</Label>
          <Input id="dueDate" name="dueDate" type="date" />
        </div>

        <div className="grid gap-2 md:col-span-2">
          <Label>Diş Seçimi * <span className="text-muted-foreground text-xs">(en az 1 diş)</span></Label>
          <TeethChart value={teeth} onChange={setTeeth} />
          {state.fieldErrors?.teeth && (
            <p className="text-destructive text-xs">{state.fieldErrors.teeth}</p>
          )}
        </div>

        <div className="md:col-span-2">
          <PriceQuoteCard
            quote={quote}
            loading={quoteLoading}
            hasInputs={Boolean(prostheticId && teeth.length > 0)}
          />
        </div>

        <div className="grid gap-2 md:col-span-2">
          <Label htmlFor="description">Açıklama</Label>
          <Textarea
            id="description"
            name="description"
            rows={4}
            maxLength={2000}
            placeholder="Lab'a iletmek istediğiniz notlar — hijyenik gövde, materyal tercihi, vs."
          />
        </div>
      </div>

      <div className="flex justify-end">
        <Button type="submit" disabled={pending || labs.length === 0 || teeth.length === 0}>
          {pending ? (
            <>
              <Loader2 className="size-4 animate-spin" />
              Kaydediliyor...
            </>
          ) : (
            <>
              <ArrowRight className="size-4" />
              Devam Et — Dosyalar
            </>
          )}
        </Button>
      </div>
    </form>
  );
}

function StepIndicator({ step }: { step: "details" | "files" }) {
  const items: { id: "details" | "files"; label: string }[] = [
    { id: "details", label: "İş Bilgileri" },
    { id: "files", label: "Dosyalar" },
  ];
  return (
    <ol className="flex items-center gap-3 text-xs">
      {items.map((it, idx) => {
        const active = it.id === step;
        const done = items.findIndex((x) => x.id === step) > idx;
        return (
          <li key={it.id} className="flex items-center gap-3">
            <span
              className={`flex size-6 items-center justify-center rounded-full text-[11px] font-semibold ${
                active
                  ? "bg-primary text-primary-foreground"
                  : done
                    ? "bg-emerald-600 text-white"
                    : "bg-muted text-muted-foreground"
              }`}
            >
              {done ? <CheckCircle2 className="size-3.5" /> : idx + 1}
            </span>
            <span className={active ? "font-medium" : "text-muted-foreground"}>{it.label}</span>
            {idx < items.length - 1 && (
              <span className="bg-border h-px w-6" aria-hidden />
            )}
          </li>
        );
      })}
    </ol>
  );
}

type PendingUpload = {
  id: string;
  file: File;
  kind: "scan" | "image" | "document";
  status: "queued" | "uploading" | "processing" | "done" | "error";
  progress: number;
  error?: string;
};

function inferKind(file: File): PendingUpload["kind"] {
  const lower = file.name.toLowerCase();
  if (
    lower.endsWith(".stl") ||
    lower.endsWith(".ply") ||
    lower.endsWith(".obj") ||
    lower.endsWith(".dcm")
  )
    return "scan";
  if (file.type.startsWith("image/")) return "image";
  return "document";
}

function FilesStep({
  jobId,
  onDone,
  onSkip,
}: {
  jobId: string;
  onDone: () => void;
  onSkip: () => void;
}) {
  const [items, setItems] = useState<PendingUpload[]>([]);
  const inputRef = useRef<HTMLInputElement>(null);

  const allDone = items.length > 0 && items.every((i) => i.status === "done");
  const anyBusy = items.some(
    (i) => i.status === "uploading" || i.status === "processing" || i.status === "queued",
  );

  function addFiles(files: FileList | null) {
    if (!files || files.length === 0) return;
    const additions: PendingUpload[] = Array.from(files).map((file) => ({
      id: `${file.name}-${file.size}-${Math.random().toString(36).slice(2, 8)}`,
      file,
      kind: inferKind(file),
      status: "queued",
      progress: 0,
    }));
    setItems((prev) => [...prev, ...additions]);
    additions.forEach(uploadOne);
  }

  function uploadOne(item: PendingUpload) {
    const fd = new FormData();
    fd.append("file", item.file);
    fd.append("kind", item.kind);

    setItems((prev) =>
      prev.map((i) => (i.id === item.id ? { ...i, status: "uploading" } : i)),
    );

    const xhr = new XMLHttpRequest();
    xhr.open("POST", `/api/jobs/${jobId}/files`);
    xhr.upload.onprogress = (e) => {
      if (!e.lengthComputable) return;
      const pct = Math.round((e.loaded / e.total) * 100);
      setItems((prev) =>
        prev.map((i) => (i.id === item.id ? { ...i, progress: pct } : i)),
      );
    };
    xhr.upload.onload = () => {
      // Bytes are up — server is now writing to Appwrite (can take a while
      // for big STL scans). Switch the row to a 'processing' state so the
      // user doesn't think we hung.
      setItems((prev) =>
        prev.map((i) =>
          i.id === item.id ? { ...i, status: "processing", progress: 100 } : i,
        ),
      );
    };
    xhr.onerror = () => {
      setItems((prev) =>
        prev.map((i) =>
          i.id === item.id
            ? { ...i, status: "error", error: "Ağ hatası" }
            : i,
        ),
      );
    };
    xhr.onload = () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        setItems((prev) =>
          prev.map((i) => (i.id === item.id ? { ...i, status: "done" } : i)),
        );
      } else {
        let msg = `HTTP ${xhr.status}`;
        try {
          const d = JSON.parse(xhr.responseText);
          if (d?.error) msg = d.error;
        } catch {}
        setItems((prev) =>
          prev.map((i) =>
            i.id === item.id ? { ...i, status: "error", error: msg } : i,
          ),
        );
      }
    };
    xhr.send(fd);
  }

  return (
    <div className="grid gap-5">
      <StepIndicator step="files" />

      <div className="bg-muted/30 grid gap-2 rounded-md border p-4 text-sm">
        <div className="flex items-center gap-2 font-medium">
          <FileUp className="size-4" />
          Tarama, görsel veya doküman ekleyin
        </div>
        <p className="text-muted-foreground text-xs">
          STL/PLY/OBJ/DCM dosyaları tarama olarak; JPG/PNG görsel olarak;
          diğerleri doküman olarak kaydedilir. Her dosya 200 MB&apos;a kadar olabilir.
        </p>
        <div>
          <input
            ref={inputRef}
            type="file"
            multiple
            className="hidden"
            onChange={(e) => {
              addFiles(e.target.files);
              if (inputRef.current) inputRef.current.value = "";
            }}
          />
          <Button
            type="button"
            variant="outline"
            onClick={() => inputRef.current?.click()}
            disabled={anyBusy}
          >
            <Upload className="size-4" />
            Dosya seç
          </Button>
        </div>
      </div>

      {items.length > 0 && (
        <ul className="divide-y rounded-md border">
          {items.map((i) => (
            <li key={i.id} className="grid gap-1.5 px-3 py-2.5">
              <div className="flex items-center justify-between gap-3">
                <span className="truncate text-sm">{i.file.name}</span>
                <span className="text-muted-foreground shrink-0 text-xs">
                  {(i.file.size / (1024 * 1024)).toFixed(1)} MB
                </span>
              </div>
              {i.status === "done" && (
                <p className="flex items-center gap-1.5 text-xs text-emerald-600 dark:text-emerald-400">
                  <CheckCircle2 className="size-3.5" />
                  Yüklendi
                </p>
              )}
              {i.status === "error" && (
                <p className="text-destructive text-xs">Hata: {i.error}</p>
              )}
              {(i.status === "uploading" || i.status === "processing") && (
                <div className="flex items-center gap-2">
                  <Progress value={i.progress} className="flex-1" />
                  <span className="text-muted-foreground w-20 text-right text-xs">
                    {i.status === "processing"
                      ? "İşleniyor..."
                      : `${i.progress}%`}
                  </span>
                </div>
              )}
            </li>
          ))}
        </ul>
      )}

      <div className="flex flex-wrap items-center justify-end gap-2">
        <button
          type="button"
          onClick={onSkip}
          className="text-muted-foreground hover:text-foreground text-sm underline-offset-4 hover:underline"
        >
          Şimdilik atla
        </button>
        <Button onClick={onDone} disabled={anyBusy || (items.length > 0 && !allDone)}>
          {anyBusy ? (
            <>
              <Loader2 className="size-4 animate-spin" />
              Bekleyin...
            </>
          ) : (
            <>
              <Send className="size-4" />
              İlanı Tamamla
            </>
          )}
        </Button>
      </div>
    </div>
  );
}

function PriceQuoteCard({
  quote,
  loading,
  hasInputs,
}: {
  quote: Quote | null;
  loading: boolean;
  hasInputs: boolean;
}) {
  if (!hasInputs) {
    return (
      <div className="bg-muted/30 text-muted-foreground rounded-md border p-3 text-xs">
        Tahmini fiyat için laboratuvar, protez türü ve dişleri seçin.
      </div>
    );
  }
  if (loading) {
    return (
      <div className="bg-muted/30 text-muted-foreground flex items-center gap-2 rounded-md border p-3 text-xs">
        <Loader2 className="size-3.5 animate-spin" />
        Fiyat hesaplanıyor...
      </div>
    );
  }
  if (!quote) {
    return (
      <div className="bg-muted/30 rounded-md border p-3 text-xs">
        <p className="text-foreground font-medium">
          Bu protez türü laboratuvarın katalogunda yok.
        </p>
        <p className="text-muted-foreground mt-1">
          Fiyat işe başlanırken laboratuvar tarafından belirlenecek. İşi şimdi yayınlayabilirsiniz.
        </p>
      </div>
    );
  }

  const hasDiscount =
    typeof quote.savings === "number" && quote.savings > 0 && quote.catalogTotal !== undefined;

  return (
    <div className="bg-muted/30 rounded-md border p-3 text-sm">
      <div className="text-muted-foreground mb-2 flex items-center gap-1.5 text-xs font-medium uppercase tracking-wide">
        <Sparkles className="size-3.5" />
        Tahmini Fiyat
      </div>

      {hasDiscount && quote.catalogTotal !== undefined ? (
        <div className="space-y-1.5">
          <Row
            label={`Katalog (${quote.teethCount} diş × ${formatMoney(quote.catalogUnitPrice ?? 0, quote.currency)})`}
            value={formatMoney(quote.catalogTotal, quote.currency)}
            muted
          />
          <Row
            label={
              quote.source === "clinic_discount" && quote.discountPercent
                ? `Klinik indirimi (%${quote.discountPercent})`
                : "Klinik özel fiyatı"
            }
            value={`- ${formatMoney(quote.savings!, quote.currency)}`}
            tone="positive"
            icon={<TrendingDown className="size-3.5" />}
          />
          <div className="border-border my-1 border-t" />
          <Row
            label="Toplam"
            value={formatMoney(quote.amount, quote.currency)}
            strong
          />
        </div>
      ) : (
        <div className="space-y-1.5">
          <Row
            label={`${quote.teethCount} diş × ${formatMoney(quote.unitPrice, quote.currency)}`}
            value={formatMoney(quote.amount, quote.currency)}
            strong
          />
          {quote.source === "catalog" && (
            <p className="text-muted-foreground text-xs">Katalog fiyatı uygulanıyor.</p>
          )}
          {quote.source === "clinic_custom" && (
            <p className="text-muted-foreground text-xs">Sizin için özel fiyat tanımlı.</p>
          )}
        </div>
      )}
    </div>
  );
}

function Row({
  label,
  value,
  muted = false,
  strong = false,
  tone,
  icon,
}: {
  label: string;
  value: string;
  muted?: boolean;
  strong?: boolean;
  tone?: "positive" | "negative";
  icon?: React.ReactNode;
}) {
  const toneClass =
    tone === "positive"
      ? "text-emerald-600 dark:text-emerald-400"
      : tone === "negative"
        ? "text-rose-600 dark:text-rose-400"
        : "";
  return (
    <div
      className={`flex items-center justify-between text-xs ${
        muted ? "text-muted-foreground" : ""
      } ${strong ? "text-sm font-semibold" : ""} ${toneClass}`}
    >
      <span className="flex items-center gap-1.5">
        {icon}
        {label}
      </span>
      <span className="tabular-nums">{value}</span>
    </div>
  );
}
