/* eslint-disable @typescript-eslint/no-explicit-any */
import ApiFetch from "@/lib/api-fetch";
import { Prisma } from "@prisma/client";
import { toast } from "react-toastify";
import { proxy } from "valtio";
import { z } from "zod";

// --- Zod Schema ---
const ApbdesItemSchema = z.object({
  kode: z.string().min(1, "Kode wajib diisi"),
  uraian: z.string().min(1, "Uraian wajib diisi"),
  anggaran: z.number().min(0),
  realisasi: z.number().min(0),
  selisih: z.number(),
  persentase: z.number(),
  level: z.number().int().min(1).max(3),
  tipe: z.enum(['pendapatan', 'belanja', 'pembiayaan']).nullable().optional(),
});

const ApbdesFormSchema = z.object({
  tahun: z.number().int().min(2000, "Tahun tidak valid"),
  imageId: z.string().min(1, "Gambar wajib diunggah"),
  fileId: z.string().min(1, "File wajib diunggah"),
  items: z.array(ApbdesItemSchema).min(1, "Minimal ada 1 item"),
});

// --- Default Form ---
const defaultApbdesForm = {
  tahun: new Date().getFullYear(),
  imageId: "",
  fileId: "",
  items: [] as z.infer<typeof ApbdesItemSchema>[],
};

// --- Helper: hitung selisih & persentase otomatis (opsional di frontend) ---
// --- Helper: hitung selisih & persentase otomatis (opsional di frontend) ---
function normalizeItem(item: Partial<z.infer<typeof ApbdesItemSchema>>): z.infer<typeof ApbdesItemSchema> {
  const anggaran = item.anggaran ?? 0;
  const realisasi = item.realisasi ?? 0;

  

  
  // ✅ Formula yang benar
  const selisih = anggaran - realisasi; // positif = sisa anggaran, negatif = over budget
  const persentase = anggaran > 0 ? (realisasi / anggaran) * 100 : 0; // persentase realisasi terhadap anggaran

  return {
    kode: item.kode || "",
    uraian: item.uraian || "",
    anggaran,
    realisasi,
    selisih,
    persentase,
    level: item.level || 1,
    tipe: item.tipe, // biarkan null jika memang null
  };
}

// --- State Utama ---
const apbdes = proxy({
  create: {
    form: { ...defaultApbdesForm },
    loading: false,

    addItem(item: Partial<z.infer<typeof ApbdesItemSchema>>) {
      const normalized = normalizeItem(item);
      this.form.items.push(normalized);
    },

    removeItem(index: number) {
      this.form.items.splice(index, 1);
    },

    updateItem(index: number, updates: Partial<z.infer<typeof ApbdesItemSchema>>) {
      const current = this.form.items[index];
      if (current) {
        const updated = normalizeItem({ ...current, ...updates });
        this.form.items[index] = updated;
      }
    },

    reset() {
      this.form = { ...defaultApbdesForm };
    },

    async create() {
      const parsed = ApbdesFormSchema.safeParse(this.form);
      if (!parsed.success) {
        const errors = parsed.error.issues.map((issue) => `${issue.path.join(".")} - ${issue.message}`);
        toast.error(`Validasi gagal:\n${errors.join("\n")}`);
        return;
      }

      try {
        this.loading = true;
        const res = await ApiFetch.api.landingpage.apbdes["create"].post(parsed.data);

        if (res.data?.success) {
          toast.success("APBDes berhasil dibuat");
          apbdes.findMany.load();
          this.reset();
        } else {
          toast.error(res.data?.message || "Gagal membuat APBDes");
        }
      } catch (error: any) {
        console.error("Create APBDes error:", error);
        toast.error(error?.message || "Terjadi kesalahan saat membuat APBDes");
      } finally {
        this.loading = false;
      }
    },
  },

  findMany: {
    data: null as
      | Prisma.APBDesGetPayload<{
          include: { image: true; file: true; items: true };
        }>[]
      | null,
    page: 1,
    totalPages: 1,
    total: 0,
    loading: false,
    search: "",

    load: async (page = 1, limit = 10, search = "") => {
      apbdes.findMany.loading = true;
      apbdes.findMany.page = page;
      apbdes.findMany.search = search;
    
      try {
        const query: Record<string, string> = { page: String(page), limit: String(limit) };
        if (search) query.search = search;
    
        const res = await ApiFetch.api.landingpage.apbdes["findMany"].get({ query });
    
        if (res.data?.success) {
          apbdes.findMany.data = res.data.data || [];
          apbdes.findMany.total = res.data.meta?.total || 0;
          apbdes.findMany.totalPages = res.data.meta?.totalPages || 1;
        } else {
          apbdes.findMany.data = [];
          apbdes.findMany.total = 0;
          apbdes.findMany.totalPages = 1;
          toast.error(res.data?.message || "Gagal memuat data");
        }
      } catch (error) {
        console.error("FindMany error:", error);
        apbdes.findMany.data = [];
        apbdes.findMany.total = 0;
        apbdes.findMany.totalPages = 1;
        toast.error("Gagal memuat daftar APBDes");
      } finally {
        apbdes.findMany.loading = false;
      }
    },
  },

  findUnique: {
    data: null as
      | Prisma.APBDesGetPayload<{
          include: { image: true; file: true; items: true };
        }>
      | null,
    loading: false,
    error: null as string | null,
  
    async load(id: string) {
      if (!id || id.trim() === '') {
        this.data = null;
        this.error = "ID tidak valid";
        return;
      }
  
      this.loading = true;
      this.error = null;
  
      try {
        // Pastikan URL-nya benar
        const url = `/api/landingpage/apbdes/${id}`;
        console.log("🌐 Fetching:", url);
  
        // Gunakan fetch biasa atau ApiFetch dengan cara yang benar
        const response = await fetch(url);
        const res = await response.json();
  
        console.log("📦 Response:", res);
  
        if (res.success && res.data) {
          this.data = res.data;
        } else {
          this.data = null;
          this.error = res.message || "Gagal memuat detail APBDes";
          toast.error(this.error);
        }
      } catch (error) {
        console.error("❌ FindUnique error:", error);
        this.data = null;
        this.error = "Gagal memuat detail APBDes";
        toast.error(this.error);
      } finally {
        this.loading = false;
      }
    }
  },

  delete: {
    loading: false,
    async byId(id: string) {
      if (!id) return toast.warn("ID tidak valid");

      try {
        this.loading = true;
        const res = await (ApiFetch.api.landingpage.apbdes as any)["del"][id].delete();

        if (res.data?.success) {
          toast.success("APBDes berhasil dihapus");
          apbdes.findMany.load();
        } else {
          toast.error(res.data?.message || "Gagal menghapus APBDes");
        }
      } catch (error: any) {
        console.error("Delete error:", error);
        toast.error(error?.message || "Terjadi kesalahan saat menghapus");
      } finally {
        this.loading = false;
      }
    },
  },

  edit: {
    id: "",
    form: { ...defaultApbdesForm },
    loading: false,

    async load(id: string) {
      if (!id) return toast.warn("ID tidak valid");

      try {
        this.loading = true;
        const res = await (ApiFetch.api.landingpage.apbdes as any)[id].get();

        if (res.data?.success) {
          const data = res.data.data;
          this.id = data.id;
          this.form = {
            tahun: data.tahun || new Date().getFullYear(),
            imageId: data.imageId || "",
            fileId: data.fileId || "",
            items: (data.items || []).map((item: any) => ({
              kode: item.kode,
              uraian: item.uraian,
              anggaran: item.anggaran,
              realisasi: item.realisasi,
              selisih: item.selisih,
              persentase: item.persentase,
              level: item.level,
              tipe: item.tipe || 'pendapatan',
            })),
          };
          return data;
        } else {
          throw new Error(res.data?.message || "Gagal memuat data");
        }
      } catch (error: any) {
        console.error("Edit load error:", error);
        toast.error(error.message || "Gagal memuat data untuk diedit");
      } finally {
        this.loading = false;
      }
    },

    async update() {
      const parsed = ApbdesFormSchema.safeParse(this.form);
      if (!parsed.success) {
        const errors = parsed.error.issues.map((issue) => `${issue.path.join(".")} - ${issue.message}`);
        toast.error(`Validasi gagal:\n${errors.join("\n")}`);
        return false;
      }

      try {
        this.loading = true;
        // Include the ID in the request body
        const requestData = {
          ...parsed.data,
          id: this.id, // Add the ID to the request body
        };
        
        const res = await (ApiFetch.api.landingpage.apbdes as any)[this.id].put(requestData);

        if (res.data?.success) {
          toast.success("APBDes berhasil diperbarui");
          apbdes.findMany.load();
          return true;
        } else {
          throw new Error(res.data?.message || "Gagal memperbarui APBDes");
        }
      } catch (error: any) {
        console.error("Update error:", error);
        toast.error(error.message || "Gagal memperbarui APBDes");
        return false;
      } finally {
        this.loading = false;
      }
    },

    addItem(item: Partial<z.infer<typeof ApbdesItemSchema>>) {
      const normalized = normalizeItem(item);
      this.form.items.push(normalized);
    },

    removeItem(index: number) {
      this.form.items.splice(index, 1);
    },

    reset() {
      this.id = "";
      this.form = { ...defaultApbdesForm };
    },
  },
});

export default apbdes;