"use client";

import { useState } from "react";
import useSWR from "swr";
import {
  Building2,
  Check,
  Clock,
  Copy,
  CreditCard,
  Globe2,
  Info,
  Mail,
  MessageCircle,
  Pencil,
  Phone,
  Plus,
  RefreshCw,
  Share2,
  ShieldCheck,
  Trash2,
} from "lucide-react";
import { toast } from "sonner";
import type { Desa, KategoriLayanan, LayananPelanggan } from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { useSession } from "@/lib/use-session";
import { PageHeader, StatCard } from "@/components/page-header";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select } from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";

const KATEGORI_OPTIONS: { value: KategoriLayanan; label: string }[] = [
  { value: "TATAP_MUKA", label: "Tatap muka" },
  { value: "WHATSAPP", label: "WhatsApp" },
  { value: "TELEPON", label: "Telepon" },
  { value: "EMAIL", label: "Email" },
  { value: "WEBSITE", label: "Website" },
  { value: "SOSIAL_MEDIA", label: "Media sosial" },
];

const KATEGORI_ICON: Record<KategoriLayanan, typeof Phone> = {
  TATAP_MUKA: Building2,
  WHATSAPP: MessageCircle,
  TELEPON: Phone,
  EMAIL: Mail,
  WEBSITE: Globe2,
  SOSIAL_MEDIA: Share2,
};

const TOKEN_KEY = "layanan_opendesa_token";

type SettingItem = { kunci: string; nilai: string | null };

type FormState = {
  nama: string;
  kategori: KategoriLayanan;
  kontak: string;
  jamOperasional: string;
  deskripsi: string;
  urut: string;
  aktif: boolean;
};

const emptyForm: FormState = {
  nama: "",
  kategori: "TATAP_MUKA",
  kontak: "",
  jamOperasional: "",
  deskripsi: "",
  urut: "0",
  aktif: true,
};

type Tab = "info" | "kanal";

type TokenInfo = {
  valid: boolean;
  status: string;
  mulai: string | null;
  akhir: string | null;
};

function decodeToken(token: string): TokenInfo | null {
  if (!token.trim()) return null;
  try {
    const payloadPart = token.split(".")[1];
    if (!payloadPart) throw new Error("format");
    const base64 = payloadPart.replace(/-/g, "+").replace(/_/g, "/");
    const json = new TextDecoder().decode(
      Uint8Array.from(atob(base64), (char) => char.charCodeAt(0)),
    );
    const payload = JSON.parse(json) as {
      tanggal_berlangganan?: { mulai?: string; akhir?: string };
    };
    const mulai = payload.tanggal_berlangganan?.mulai ?? null;
    const akhir = payload.tanggal_berlangganan?.akhir ?? null;
    const aktif = akhir ? new Date(akhir).getTime() >= Date.now() : false;
    return {
      valid: true,
      status: aktif ? "Aktif" : "Berakhir",
      mulai,
      akhir,
    };
  } catch {
    return { valid: false, status: "Token tidak valid", mulai: null, akhir: null };
  }
}

function tanggal(value: string | null) {
  if (!value) return "-";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleDateString("id-ID", {
    day: "2-digit",
    month: "long",
    year: "numeric",
  });
}

export default function LayananPelangganPage() {
  const { user } = useSession();
  const isAdmin = user?.role === "ADMIN";
  const [tab, setTab] = useState<Tab>("info");

  const { data, isLoading, mutate } = useSWR<LayananPelanggan[]>(
    "/layanan-pelanggan",
    fetcher,
  );
  const daftar = data ?? [];
  const { data: desa } = useSWR<Desa>("/desa", fetcher);
  const { data: pengaturan, mutate: mutatePengaturan } = useSWR<SettingItem[]>(
    isAdmin ? "/pengaturan-sistem?grup=pelanggan" : null,
    fetcher,
  );
  const token = pengaturan?.find((item) => item.kunci === TOKEN_KEY)?.nilai ?? "";
  const info = decodeToken(token);

  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<LayananPelanggan | null>(null);
  const [form, setForm] = useState<FormState>(emptyForm);
  const [saving, setSaving] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<LayananPelanggan | null>(null);
  const [deleting, setDeleting] = useState(false);
  const [tokenOpen, setTokenOpen] = useState(false);
  const [tokenDraft, setTokenDraft] = useState("");
  const [tokenSaving, setTokenSaving] = useState(false);
  const [copied, setCopied] = useState(false);

  function openCreate() {
    setEditing(null);
    setForm(emptyForm);
    setFormOpen(true);
  }

  function openEdit(item: LayananPelanggan) {
    setEditing(item);
    setForm({
      nama: item.nama,
      kategori: item.kategori,
      kontak: item.kontak ?? "",
      jamOperasional: item.jamOperasional ?? "",
      deskripsi: item.deskripsi ?? "",
      urut: String(item.urut),
      aktif: item.aktif,
    });
    setFormOpen(true);
  }

  async function save(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);
    try {
      const payload = {
        nama: form.nama,
        kategori: form.kategori,
        urut: Number(form.urut) || 0,
        aktif: form.aktif,
        ...(form.kontak ? { kontak: form.kontak } : {}),
        ...(form.jamOperasional ? { jamOperasional: form.jamOperasional } : {}),
        ...(form.deskripsi ? { deskripsi: form.deskripsi } : {}),
      };
      if (editing) {
        await apiSend(`/layanan-pelanggan/${editing.id}`, "PATCH", payload);
        toast.success("Layanan pelanggan diperbarui");
      } else {
        await apiSend("/layanan-pelanggan", "POST", payload);
        toast.success("Layanan pelanggan ditambahkan");
      }
      setFormOpen(false);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan data");
    } finally {
      setSaving(false);
    }
  }

  async function remove() {
    if (!deleteTarget) return;
    setDeleting(true);
    try {
      await apiSend(`/layanan-pelanggan/${deleteTarget.id}`, "DELETE");
      toast.success("Layanan pelanggan dihapus");
      setDeleteTarget(null);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menghapus data");
    } finally {
      setDeleting(false);
    }
  }

  async function copyToken() {
    if (!token) return;
    try {
      await navigator.clipboard.writeText(token);
      setCopied(true);
      toast.success("Token disalin");
      window.setTimeout(() => setCopied(false), 2000);
    } catch {
      toast.error("Gagal menyalin token");
    }
  }

  async function saveToken(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setTokenSaving(true);
    try {
      await apiSend("/pengaturan-sistem", "PUT", {
        items: [
          {
            kunci: TOKEN_KEY,
            nilai: tokenDraft.trim() || null,
            grup: "pelanggan",
            keterangan: "Token layanan pelanggan OpenDesa",
          },
        ],
      });
      toast.success("Token layanan disimpan");
      setTokenOpen(false);
      await mutatePengaturan();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan token");
    } finally {
      setTokenSaving(false);
    }
  }

  return (
    <div className="animate-fade-in space-y-6">
      <PageHeader
        title="Layanan Pelanggan"
        description="Informasi keanggotaan layanan desa serta kanal komunikasi resmi Pemerintah Desa Mulyadadi."
        action={
          tab === "kanal" && isAdmin ? (
            <Button onClick={openCreate}>
              <Plus className="h-4 w-4" />
              Tambah Layanan
            </Button>
          ) : undefined
        }
      />

      <div className="inline-flex rounded-xl border border-border bg-card p-1">
        {[
          { key: "info" as const, label: "Info Layanan", icon: CreditCard },
          { key: "kanal" as const, label: "Kanal Layanan", icon: Phone },
        ].map((item) => (
          <button
            key={item.key}
            type="button"
            onClick={() => setTab(item.key)}
            className={cn(
              "inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors",
              tab === item.key
                ? "bg-primary text-primary-foreground shadow-sm"
                : "text-muted-foreground hover:bg-muted",
            )}
          >
            <item.icon className="h-4 w-4" />
            {item.label}
          </button>
        ))}
      </div>

      {tab === "info" ? (
        <>
          <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
            <StatCard
              title="Status pelanggan"
              value={info ? info.status : "Belum diatur"}
              hint={info?.valid ? "Dari token layanan" : "Atur token layanan"}
              icon={ShieldCheck}
            />
            <StatCard
              title="Mulai berlangganan"
              value={tanggal(info?.mulai ?? null)}
              icon={Clock}
              tone="sky"
            />
            <StatCard
              title="Akhir berlangganan"
              value={tanggal(info?.akhir ?? null)}
              icon={CreditCard}
              tone="amber"
            />
            <StatCard
              title="Domain desa"
              value={desa?.website ?? "-"}
              icon={Globe2}
              tone="violet"
            />
          </div>

          {!info && (
            <Card>
              <CardContent className="flex gap-3 p-4 text-sm text-muted-foreground">
                <Info className="mt-0.5 h-4 w-4 shrink-0 text-primary" />
                <p>
                  Token layanan pelanggan belum diatur. Buka{" "}
                  <span className="font-medium text-foreground">
                    Pengaturan Pelanggan
                  </span>{" "}
                  untuk menyimpan token dari penyedia layanan, lalu data
                  langganan akan ditampilkan di sini.
                </p>
              </CardContent>
            </Card>
          )}

          <Card>
            <CardHeader className="flex-row items-center justify-between gap-2 space-y-0">
              <CardTitle>Rincian Pelanggan</CardTitle>
              <div className="flex flex-wrap gap-1">
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => mutatePengaturan()}
                >
                  <RefreshCw className="h-3.5 w-3.5" />
                  Perbarui
                </Button>
                {isAdmin && (
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => {
                      setTokenDraft(token);
                      setTokenOpen(true);
                    }}
                  >
                    <Pencil className="h-3.5 w-3.5" />
                    Pengaturan Pelanggan
                  </Button>
                )}
              </div>
            </CardHeader>
            <CardContent className="p-0">
              <div className="divide-y">
                <InfoRow label="ID Pelanggan">{desa?.kodeDesa ?? "-"}</InfoRow>
                <InfoRow label="Kode Desa">{desa?.kodeDesa ?? "-"}</InfoRow>
                <InfoRow label="Desa">
                  {desa
                    ? `Desa ${desa.nama.replace(/^Desa\s+/i, "")}, Kecamatan ${desa.kecamatan}, Kabupaten ${desa.kabupaten}, Provinsi ${desa.provinsi}`
                    : "-"}
                </InfoRow>
                <InfoRow label="Domain Desa">{desa?.website ?? "-"}</InfoRow>
                <InfoRow label="Nama Kontak">
                  {desa?.kontakNama
                    ? `${desa.kontakNama}${desa.kontakJabatan ? ` — ${desa.kontakJabatan}` : ""}`
                    : "-"}
                </InfoRow>
                <InfoRow label="Token">
                  {token ? (
                    <div className="flex items-start gap-2">
                      <code className="max-h-24 flex-1 overflow-auto whitespace-pre-wrap break-all rounded-md bg-muted/60 p-2 text-xs">
                        {token}
                      </code>
                      <Button
                        type="button"
                        variant="outline"
                        size="icon"
                        className="h-8 w-8 shrink-0"
                        onClick={copyToken}
                        aria-label="Salin token"
                      >
                        {copied ? (
                          <Check className="h-4 w-4 text-emerald-600" />
                        ) : (
                          <Copy className="h-4 w-4" />
                        )}
                      </Button>
                    </div>
                  ) : (
                    <span className="text-muted-foreground">Belum diatur</span>
                  )}
                </InfoRow>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Rincian Pemesanan</CardTitle>
            </CardHeader>
            <CardContent>
              <div className="rounded-lg border border-dashed py-10 text-center">
                <p className="font-medium">Belum ada data pemesanan</p>
                <p className="mx-auto mt-1 max-w-md text-sm text-muted-foreground">
                  Rincian pemesanan dan nota faktur diambil dari server layanan
                  penyedia saat token pelanggan terhubung.
                </p>
              </div>
            </CardContent>
          </Card>
        </>
      ) : (
        <>
          <div className="grid gap-4 sm:grid-cols-3">
            <StatCard title="Total kanal" value={daftar.length} icon={Phone} />
            <StatCard
              title="Kanal aktif"
              value={daftar.filter((item) => item.aktif).length}
              icon={Clock}
              tone="sky"
            />
            <StatCard
              title="Kanal nonaktif"
              value={daftar.filter((item) => !item.aktif).length}
              icon={Share2}
              tone="amber"
            />
          </div>

          {isLoading ? (
            <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
              {Array.from({ length: 3 }).map((_, index) => (
                <div key={index} className="h-44 animate-pulse rounded-xl bg-muted" />
              ))}
            </div>
          ) : daftar.length ? (
            <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
              {daftar.map((item) => {
                const Icon = KATEGORI_ICON[item.kategori] ?? Phone;
                return (
                  <Card key={item.id} className={item.aktif ? undefined : "opacity-75"}>
                    <CardContent className="space-y-3 p-5">
                      <div className="flex items-start justify-between gap-3">
                        <div className="flex items-center gap-3">
                          <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-secondary text-primary">
                            <Icon className="h-5 w-5" />
                          </div>
                          <div>
                            <div className="font-semibold leading-tight">{item.nama}</div>
                            <div className="mt-1 flex items-center gap-2">
                              <Badge variant="secondary">
                                {KATEGORI_OPTIONS.find(
                                  (option) => option.value === item.kategori,
                                )?.label ?? item.kategori}
                              </Badge>
                              {!item.aktif && <Badge variant="danger">Nonaktif</Badge>}
                            </div>
                          </div>
                        </div>
                        {isAdmin && (
                          <div className="flex shrink-0 gap-1">
                            <Button
                              variant="ghost"
                              size="sm"
                              onClick={() => openEdit(item)}
                              aria-label="Ubah"
                            >
                              <Pencil className="h-4 w-4" />
                            </Button>
                            <Button
                              variant="ghost"
                              size="sm"
                              className="text-destructive hover:text-destructive"
                              onClick={() => setDeleteTarget(item)}
                              aria-label="Hapus"
                            >
                              <Trash2 className="h-4 w-4" />
                            </Button>
                          </div>
                        )}
                      </div>

                      <div className="space-y-1.5 text-sm">
                        <div className="flex items-start gap-2">
                          <MessageCircle className="mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground" />
                          <span className="break-all">{item.kontak ?? "-"}</span>
                        </div>
                        <div className="flex items-start gap-2 text-muted-foreground">
                          <Clock className="mt-0.5 h-3.5 w-3.5 shrink-0" />
                          <span>{item.jamOperasional ?? "Jam layanan belum diatur"}</span>
                        </div>
                      </div>

                      <p className="text-sm leading-relaxed text-muted-foreground">
                        {item.deskripsi ?? "Belum ada keterangan."}
                      </p>
                    </CardContent>
                  </Card>
                );
              })}
            </div>
          ) : (
            <Card>
              <CardContent className="py-16 text-center">
                <p className="font-semibold">Belum ada kanal layanan</p>
                <p className="mt-1 text-sm text-muted-foreground">
                  Tambahkan nomor telepon, WhatsApp, email, atau loket layanan desa.
                </p>
              </CardContent>
            </Card>
          )}
        </>
      )}

      <Dialog open={tokenOpen} onOpenChange={setTokenOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>Pengaturan Pelanggan</DialogTitle>
            <DialogDescription>
              Tempelkan token layanan pelanggan dari penyedia. Token disimpan di
              basis data desa.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={saveToken} className="space-y-4">
            <Field label="Token layanan">
              <Textarea
                rows={5}
                value={tokenDraft}
                onChange={(event) => setTokenDraft(event.target.value)}
                placeholder="eyJhbGciOi…"
                className="font-mono text-xs"
              />
            </Field>
            <p className="rounded-lg bg-muted/50 p-3 text-xs text-muted-foreground">
              Token tidak dikirim ke mana pun. Data tanggal berlangganan dibaca
              langsung dari isi token untuk ditampilkan pada halaman ini.
            </p>
            <DialogFooter>
              <Button
                type="button"
                variant="outline"
                onClick={() => setTokenOpen(false)}
              >
                Batal
              </Button>
              <Button type="submit" disabled={tokenSaving}>
                {tokenSaving ? "Menyimpan…" : "Simpan Token"}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle>
              {editing ? "Ubah Layanan Pelanggan" : "Tambah Layanan Pelanggan"}
            </DialogTitle>
            <DialogDescription>
              Kanal ini menjadi rujukan warga untuk menghubungi pemerintah desa.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={save} className="space-y-4">
            <div className="grid gap-4 sm:grid-cols-2">
              <Field label="Nama layanan" required>
                <Input
                  required
                  value={form.nama}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, nama: event.target.value }))
                  }
                  placeholder="WhatsApp Layanan Desa"
                />
              </Field>
              <Field label="Kategori" required>
                <Select
                  value={form.kategori}
                  onChange={(event) =>
                    setForm((current) => ({
                      ...current,
                      kategori: event.target.value as KategoriLayanan,
                    }))
                  }
                >
                  {KATEGORI_OPTIONS.map((option) => (
                    <option key={option.value} value={option.value}>
                      {option.label}
                    </option>
                  ))}
                </Select>
              </Field>
              <Field label="Kontak">
                <Input
                  value={form.kontak}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, kontak: event.target.value }))
                  }
                  placeholder="0812-3456-7890"
                />
              </Field>
              <Field label="Jam operasional">
                <Input
                  value={form.jamOperasional}
                  onChange={(event) =>
                    setForm((current) => ({
                      ...current,
                      jamOperasional: event.target.value,
                    }))
                  }
                  placeholder="Senin–Jumat, 08.00–15.00 WIB"
                />
              </Field>
              <Field label="Urutan tampil">
                <Input
                  type="number"
                  min={0}
                  value={form.urut}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, urut: event.target.value }))
                  }
                />
              </Field>
            </div>
            <Field label="Deskripsi">
              <Textarea
                rows={3}
                value={form.deskripsi}
                onChange={(event) =>
                  setForm((current) => ({ ...current, deskripsi: event.target.value }))
                }
              />
            </Field>
            <label className="flex items-center gap-2 text-sm">
              <input
                type="checkbox"
                checked={form.aktif}
                onChange={(event) =>
                  setForm((current) => ({ ...current, aktif: event.target.checked }))
                }
                className="h-4 w-4 rounded border-input accent-emerald-600"
              />
              Kanal aktif dan ditampilkan
            </label>
            <DialogFooter>
              <Button type="button" variant="outline" onClick={() => setFormOpen(false)}>
                Batal
              </Button>
              <Button type="submit" disabled={saving}>
                {saving ? "Menyimpan…" : editing ? "Simpan Perubahan" : "Tambah Layanan"}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <Dialog open={!!deleteTarget} onOpenChange={(open) => !open && setDeleteTarget(null)}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus layanan?</DialogTitle>
            <DialogDescription>
              Kanal “{deleteTarget?.nama}” akan dihapus permanen.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeleteTarget(null)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={remove} disabled={deleting}>
              {deleting ? "Menghapus…" : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

function InfoRow({
  label,
  children,
}: {
  label: string;
  children: React.ReactNode;
}) {
  return (
    <div className="grid gap-1 px-4 py-3 text-sm sm:grid-cols-[180px_1fr] sm:gap-3">
      <span className="text-muted-foreground">{label}</span>
      <span>{children}</span>
    </div>
  );
}

function Field({
  label,
  required,
  children,
}: {
  label: string;
  required?: boolean;
  children: React.ReactNode;
}) {
  return (
    <div className="space-y-1.5">
      <Label className="text-xs">
        {label}
        {required && <span className="text-destructive"> *</span>}
      </Label>
      {children}
    </div>
  );
}
