import { useState } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useServerFn } from "@tanstack/react-start";
import { Loader2, Paperclip, Plus, Sparkles } from "lucide-react";
import { toast } from "sonner";


import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { cn } from "@/lib/utils";
import {
  daftarKategori as kategoriUntuk,
  simpanTransaksi,
  unggahBukti,
  type Jenis,
  type Kas,
} from "@/lib/keuangan";
import { bacaBukti } from "@/lib/ocr.functions";


function hariIni() {
  const d = new Date();
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
}

export function TransaksiForm({ trigger, kas = "operasional" }: { trigger?: React.ReactNode; kas?: Kas }) {
  const [open, setOpen] = useState(false);
  const [jenis, setJenis] = useState<Jenis>("pengeluaran");
  const [nominal, setNominal] = useState("");
  const [tanggal, setTanggal] = useState(hariIni());
  const [kategori, setKategori] = useState((kategoriUntuk(kas, "pengeluaran")[0] ?? "Lainnya"));
  const [catatan, setCatatan] = useState("");
  const [sumber, setSumber] = useState("");
  const [tujuan, setTujuan] = useState("");
  const [file, setFile] = useState<File | null>(null);
  const [membaca, setMembaca] = useState(false);
  const qc = useQueryClient();
  const jalankanBacaBukti = useServerFn(bacaBukti);

  const daftarKategori = kategoriUntuk(kas, jenis);

  function reset() {
    setJenis("pengeluaran");
    setNominal("");
    setTanggal(hariIni());
    setKategori((kategoriUntuk(kas, "pengeluaran")[0] ?? "Lainnya"));
    setCatatan("");
    setSumber("");
    setTujuan("");
    setFile(null);
    setMembaca(false);
  }

  function keBase64(f: File) {
    return new Promise<string>((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(String(reader.result).split(",")[1] ?? "");
      reader.onerror = () => reject(new Error("Gagal membaca berkas"));
      reader.readAsDataURL(f);
    });
  }

  async function bacaGambar() {
    if (!file || !file.type.startsWith("image/")) return;
    setMembaca(true);
    try {
      const base64 = await keBase64(file);
      const hasil = await jalankanBacaBukti({
        data: { imageBase64: base64, mimeType: file.type },
      });
      if (!hasil.ok) {
        toast.error(hasil.pesan ?? "Bukti tidak terbaca. Silakan isi manual.");
        return;
      }
      const terisi: string[] = [];
      if (hasil.nominal && hasil.nominal > 0) {
        setNominal(Number(hasil.nominal).toLocaleString("id-ID"));
        terisi.push("nominal");
      }
      if (hasil.tanggal) {
        setTanggal(hasil.tanggal);
        terisi.push("tanggal");
      }
      if (hasil.jenis) {
        setJenis(hasil.jenis);
        setKategori((kategoriUntuk(kas, hasil.jenis)[0] ?? "Lainnya"));
      }
      if (hasil.merchant) {
        setTujuan(hasil.merchant.slice(0, 100));
        terisi.push("merchant");
      }
      if (hasil.catatan) setCatatan(hasil.catatan.slice(0, 500));
      toast.success(
        terisi.length
          ? `Terisi otomatis: ${terisi.join(", ")}. Periksa dulu sebelum simpan.`
          : "Sebagian data terisi. Periksa dulu sebelum simpan.",
      );
    } catch {
      toast.error("Gagal membaca bukti. Silakan isi manual.");
    } finally {
      setMembaca(false);
    }
  }


  const mutation = useMutation({
    mutationFn: async () => {
      const angka = Number(nominal.replace(/[^\d]/g, ""));
      if (!angka || angka <= 0) throw new Error("Nominal harus lebih dari nol");
      if (!kategori) throw new Error("Kategori wajib diisi");
      let bukti: { path: string; nama: string } | null = null;
      if (file) {
        if (file.size > 10 * 1024 * 1024) throw new Error("Ukuran berkas maksimal 10MB");
        bukti = await unggahBukti(file);
      }
      await simpanTransaksi({
        jenis,
        nominal: angka,
        tanggal,
        kategori,
        kas,
        catatan: catatan.trim().slice(0, 500) || null,
        sumber: sumber.trim().slice(0, 100) || null,
        tujuan: tujuan.trim().slice(0, 100) || null,
        bukti_path: bukti?.path ?? null,
        bukti_nama: bukti?.nama ?? null,
      });
    },
    onSuccess: () => {
      toast.success("Transaksi tersimpan");
      qc.invalidateQueries({ queryKey: ["transaksi"] });
      reset();
      setOpen(false);
    },
    onError: (e: Error) => toast.error(e.message || "Gagal menyimpan transaksi"),
  });

  return (
    <Dialog
      open={open}
      onOpenChange={(v) => {
        setOpen(v);
        if (!v) reset();
      }}
    >
      <DialogTrigger asChild>
        {trigger ?? (
          <Button size="lg" className="w-full gap-2">
            <Plus className="size-4" /> Catat transaksi
          </Button>
        )}
      </DialogTrigger>
      <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-md">
        <DialogHeader>
          <DialogTitle>Catat transaksi</DialogTitle>
          <DialogDescription>Isi cepat, bukti transfer bisa diunggah sekalian.</DialogDescription>
        </DialogHeader>

        <form
          className="space-y-4"
          onSubmit={(e) => {
            e.preventDefault();
            mutation.mutate();
          }}
        >
          <div className="grid grid-cols-2 gap-2 rounded-2xl bg-muted p-1">
            {(["pengeluaran", "pemasukan"] as Jenis[]).map((j) => (
              <button
                key={j}
                type="button"
                onClick={() => {
                  setJenis(j);
                  setKategori((kategoriUntuk(kas, j)[0] ?? "Lainnya"));
                }}
                className={cn(
                  "rounded-xl py-2 text-sm font-medium capitalize transition-colors",
                  jenis === j
                    ? "bg-card text-foreground shadow-sm"
                    : "text-muted-foreground hover:text-foreground",
                )}
              >
                {j}
              </button>
            ))}
          </div>

          <div className="space-y-1.5">
            <Label htmlFor="nominal">Nominal (Rp)</Label>
            <Input
              id="nominal"
              inputMode="numeric"
              placeholder="50.000"
              value={nominal}
              maxLength={15}
              onChange={(e) => {
                const angka = e.target.value.replace(/[^\d]/g, "");
                setNominal(angka ? Number(angka).toLocaleString("id-ID") : "");
              }}
              className="h-12 text-lg font-semibold"
            />
          </div>

          <div className="grid grid-cols-2 gap-3">
            <div className="space-y-1.5">
              <Label htmlFor="tanggal">Tanggal</Label>
              <Input
                id="tanggal"
                type="date"
                value={tanggal}
                onChange={(e) => setTanggal(e.target.value)}
              />
            </div>
            <div className="space-y-1.5">
              <Label>Kategori</Label>
              <Select value={kategori} onValueChange={setKategori}>
                <SelectTrigger>
                  <SelectValue placeholder="Pilih" />
                </SelectTrigger>
                <SelectContent>
                  {daftarKategori.map((k) => (
                    <SelectItem key={k} value={k}>
                      {k}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="grid grid-cols-2 gap-3">
            <div className="space-y-1.5">
              <Label htmlFor="sumber">Dari</Label>
              <Input
                id="sumber"
                placeholder="BCA 1234"
                maxLength={100}
                value={sumber}
                onChange={(e) => setSumber(e.target.value)}
              />
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="tujuan">Ke</Label>
              <Input
                id="tujuan"
                placeholder="GoPay / nama toko"
                maxLength={100}
                value={tujuan}
                onChange={(e) => setTujuan(e.target.value)}
              />
            </div>
          </div>

          <div className="space-y-1.5">
            <Label htmlFor="catatan">Catatan (opsional)</Label>
            <Textarea
              id="catatan"
              rows={2}
              maxLength={500}
              placeholder="Misal: bayar patungan makan"
              value={catatan}
              onChange={(e) => setCatatan(e.target.value)}
            />
          </div>

          <div className="space-y-1.5">
            <Label htmlFor="bukti">Bukti transaksi (opsional)</Label>
            <label
              htmlFor="bukti"
              className="flex cursor-pointer items-center gap-2 rounded-xl border border-dashed border-border bg-muted/40 px-3 py-3 text-sm text-muted-foreground"
            >
              <Paperclip className="size-4" />
              {file ? file.name : "Unggah foto atau PDF bukti transfer"}
            </label>
            <input
              id="bukti"
              type="file"
              accept="image/*,application/pdf"
              className="hidden"
              onChange={(e) => setFile(e.target.files?.[0] ?? null)}
            />
            {file?.type.startsWith("image/") && (
              <Button
                type="button"
                variant="secondary"
                className="w-full gap-2"
                disabled={membaca}
                onClick={bacaGambar}
              >
                {membaca ? (
                  <Loader2 className="size-4 animate-spin" />
                ) : (
                  <Sparkles className="size-4" />
                )}
                {membaca ? "Membaca bukti…" : "Baca bukti & isi otomatis"}
              </Button>
            )}
            <p className="text-xs text-muted-foreground">
              Hasil pembacaan AI hanya perkiraan — periksa dan ubah sebelum menyimpan.
            </p>
          </div>


          <Button type="submit" size="lg" className="w-full" disabled={mutation.isPending}>
            {mutation.isPending && <Loader2 className="mr-2 size-4 animate-spin" />}
            Simpan transaksi
          </Button>
        </form>
      </DialogContent>
    </Dialog>
  );
}
