"use client";

import { useEffect, useState } from "react";
import useSWR from "swr";
import { RotateCcw, Save, Upload } from "lucide-react";
import { toast } from "sonner";
import { apiSend, ApiError, fetcher } from "@/lib/api";
import { PageHeader } from "@/components/page-header";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
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";

export interface SettingField {
  kunci: string;
  label: string;
  type?: "text" | "textarea" | "number" | "select" | "checkbox" | "url" | "email" | "password" | "image";
  options?: { value: string; label: string }[];
  placeholder?: string;
  help?: string;
  defaultValue?: string;
  full?: boolean;
}

interface SettingRow {
  id: number;
  kunci: string;
  nilai: string | null;
  grup: string | null;
}

function bacaSebagaiDataUrl(file: File) {
  return new Promise<string>((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(String(reader.result));
    reader.onerror = () => reject(new Error("Gagal membaca berkas"));
    reader.readAsDataURL(file);
  });
}

export function SettingsForm({
  grup,
  title,
  description,
  fields,
  children,
  hideHeader,
  cardTitle,
  submitLabel = "Simpan Pengaturan",
  showReset = false,
}: {
  grup: string;
  title: string;
  description?: string;
  fields: SettingField[];
  children?: React.ReactNode;
  hideHeader?: boolean;
  cardTitle?: string;
  submitLabel?: string;
  showReset?: boolean;
}) {
  const { data, mutate } = useSWR<SettingRow[]>(
    `/pengaturan-sistem?grup=${grup}`,
    fetcher,
  );
  const [values, setValues] = useState<Record<string, string>>({});
  const [saving, setSaving] = useState(false);
  const [mengunggah, setMengunggah] = useState<string | null>(null);

  useEffect(() => {
    const stored = new Map((data ?? []).map((row) => [row.kunci, row.nilai ?? ""]));
    const next: Record<string, string> = {};
    for (const field of fields) {
      next[field.kunci] = stored.get(field.kunci) ?? field.defaultValue ?? "";
    }
    setValues(next);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [data]);

  async function save(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);
    try {
      await apiSend("/pengaturan-sistem", "PUT", {
        items: fields.map((field) => ({
          kunci: field.kunci,
          nilai: values[field.kunci] ?? "",
          grup,
        })),
      });
      toast.success("Pengaturan disimpan");
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan pengaturan");
    } finally {
      setSaving(false);
    }
  }

  async function unggahBerkas(field: SettingField, file?: File) {
    if (!file) return;
    setMengunggah(field.kunci);
    try {
      const dataUrl = await bacaSebagaiDataUrl(file);
      const hasil = await apiSend<{ kunci: string; nilai: string }>(
        "/pengaturan-sistem/berkas",
        "POST",
        { kunci: field.kunci, grup, dataUrl },
      );
      setValues((current) => ({ ...current, [field.kunci]: hasil.nilai }));
      toast.success(`${field.label} diunggah`);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal mengunggah berkas");
    } finally {
      setMengunggah(null);
    }
  }

  return (
    <div className="space-y-5">
      {!hideHeader && <PageHeader title={title} description={description} />}
      <Card>
        <CardHeader>
          <CardTitle className="text-base">{cardTitle ?? "Formulir Pengaturan"}</CardTitle>
          <CardDescription>Perubahan berlaku setelah disimpan.</CardDescription>
        </CardHeader>
        <CardContent>
          <form onSubmit={save} className="space-y-4">
            <div className="grid gap-4 sm:grid-cols-2">
              {fields.map((field) => {
                const value = values[field.kunci] ?? "";
                return (
                  <div
                    key={field.kunci}
                    className={cn(
                      "space-y-1.5",
                      (field.full || field.type === "textarea" || field.type === "image") &&
                        "sm:col-span-2",
                    )}
                  >
                    <Label htmlFor={`setting-${field.kunci}`}>{field.label}</Label>
                    {field.type === "textarea" ? (
                      <Textarea
                        id={`setting-${field.kunci}`}
                        value={value}
                        onChange={(event) =>
                          setValues((current) => ({ ...current, [field.kunci]: event.target.value }))
                        }
                        placeholder={field.placeholder}
                        rows={4}
                      />
                    ) : field.type === "select" ? (
                      <Select
                        id={`setting-${field.kunci}`}
                        value={value}
                        onChange={(event) =>
                          setValues((current) => ({ ...current, [field.kunci]: event.target.value }))
                        }
                      >
                        {field.options?.map((option) => (
                          <option key={option.value} value={option.value}>
                            {option.label}
                          </option>
                        ))}
                      </Select>
                    ) : field.type === "checkbox" ? (
                      <label className="flex h-10 items-center gap-2 rounded-lg border border-input bg-card px-3 text-sm">
                        <input
                          id={`setting-${field.kunci}`}
                          type="checkbox"
                          checked={value === "1"}
                          onChange={(event) =>
                            setValues((current) => ({
                              ...current,
                              [field.kunci]: event.target.checked ? "1" : "0",
                            }))
                          }
                          className="h-4 w-4 accent-[hsl(var(--primary))]"
                        />
                        {field.help ?? "Aktifkan"}
                      </label>
                    ) : field.type === "image" ? (
                      <div className="flex flex-wrap items-center gap-3">
                        {value ? (
                          // eslint-disable-next-line @next/next/no-img-element
                          <img
                            src={value}
                            alt={field.label}
                            className="h-20 w-32 rounded-lg border bg-muted object-cover"
                          />
                        ) : (
                          <div className="flex h-20 w-32 items-center justify-center rounded-lg border border-dashed px-2 text-center text-[11px] text-muted-foreground">
                            Belum ada gambar
                          </div>
                        )}
                        <label className="inline-flex h-9 cursor-pointer items-center gap-2 rounded-md border border-input bg-card px-3 text-sm font-medium hover:bg-muted">
                          <Upload className="h-4 w-4" />
                          {mengunggah === field.kunci ? "Mengunggah…" : "Unggah"}
                          <input
                            type="file"
                            accept="image/png,image/jpeg,image/webp"
                            className="sr-only"
                            disabled={mengunggah === field.kunci}
                            onChange={(event) => {
                              const file = event.target.files?.[0];
                              event.target.value = "";
                              void unggahBerkas(field, file);
                            }}
                          />
                        </label>
                        {value && (
                          <Button
                            type="button"
                            variant="ghost"
                            onClick={() =>
                              setValues((current) => ({ ...current, [field.kunci]: "" }))
                            }
                          >
                            Kosongkan
                          </Button>
                        )}
                      </div>
                    ) : (
                      <Input
                        id={`setting-${field.kunci}`}
                        type={field.type === "number" ? "number" : field.type ?? "text"}
                        value={value}
                        onChange={(event) =>
                          setValues((current) => ({ ...current, [field.kunci]: event.target.value }))
                        }
                        placeholder={field.placeholder}
                      />
                    )}
                    {field.help && field.type !== "checkbox" && (
                      <p className="text-[11px] text-muted-foreground">{field.help}</p>
                    )}
                  </div>
                );
              })}
            </div>
            {children}
            <div className="flex flex-wrap justify-end gap-2">
              {showReset && (
                <Button
                  type="button"
                  variant="outline"
                  onClick={() => {
                    const awal: Record<string, string> = {};
                    for (const field of fields) {
                      awal[field.kunci] = field.defaultValue ?? "";
                    }
                    setValues(awal);
                    toast.info("Standar spesifikasi dimuat. Simpan untuk menerapkan.");
                  }}
                >
                  <RotateCcw className="h-4 w-4" /> Kembalikan Standar Spesifikasi
                </Button>
              )}
              <Button type="submit" disabled={saving}>
                <Save className="h-4 w-4" /> {saving ? "Menyimpan…" : submitLabel}
              </Button>
            </div>
          </form>
        </CardContent>
      </Card>
    </div>
  );
}
