import formatDateTime from "@/lib/formatDateTime";
import timeAgo from "@/lib/timeAgo";
import { prisma } from "@/module/_global";
import cors from "@elysiajs/cors";
import { swagger } from "@elysiajs/swagger";
import Elysia, { t } from "elysia";
import _ from "lodash";
import moment from "moment";
import "moment/locale/id";

// Gabungkan semua ke dalam satu instance server yang dipasang di /api/monitoring
const MonitoringServer = new Elysia({ prefix: "/api/monitoring" })
   .use(cors({
      origin: "*",
      methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
      allowedHeaders: ["Content-Type", "Authorization"]
   }))
   .use(swagger({
      path: "/docs", // Karena prefix instance adalah /api/monitoring, maka ini akan diakses di /api/monitoring/docs
      documentation: {
         info: {
            title: "Des Plus - Monitoring API",
            version: "1.0.0",
            description: "API Khusus untuk kebutuhan Dashboard Monitoring",
         }
      }
   }))
   .onBeforeHandle(({ request, set, path }) => {
      // Docs tidak perlu API key
      if (path.startsWith("/api/monitoring/docs")) return;

      const apiKey = process.env.MONITORING_API_KEY;
      const incoming = request.headers.get("x-api-key");

      if (!apiKey || incoming !== apiKey) {
         set.status = 401;
         return { success: false, message: "Unauthorized" };
      }
   })

   .get("/grid-overview", async ({ query, set }) => {
      try {
         const version = await prisma.setting.findMany({
            select: {
               id: true,
               name: true,
               value: true
            }
         });

         const result_version = Object.fromEntries(version.map(item => [item.id, item.value]));

         const activity_today = await prisma.userLog.count({
            where: {
               createdAt: {
                  gte: moment().subtract(1, 'days').toDate(),
                  lte: moment().toDate(),
               }
            }
         })

         const activity_yesterday = await prisma.userLog.count({
            where: {
               createdAt: {
                  gte: moment().subtract(2, 'days').toDate(),
                  lte: moment().subtract(1, 'days').toDate(),
               }
            }
         })


         const activity_increase = (activity_today - activity_yesterday);
         const percentage_increase = (activity_increase / activity_yesterday) * 100

         const total_village = await prisma.village.findMany({
            where: {
               isDummy: false
            }
         })

         const total_village_active = total_village.filter((item) => item.isActive).length
         const total_village_inactive = total_village.filter((item) => !item.isActive).length

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: {
               version: result_version,
               activity: {
                  today: activity_today,
                  increase: _.isNaN(percentage_increase) ? 0 : percentage_increase.toFixed(2),
               },
               village: {
                  active: total_village_active,
                  inactive: total_village_inactive,
               },

            },
         };
      } catch (error) {
         console.error("[overview] grid-overview error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         detail: {
            summary: "Grid Overview",
            description: "Menu Overview - Mendapatkan daftar versi aplikasi.",
            tags: ["overview"],
         },
      }
   )
   .get("/daily-activity", async ({ query, set }) => {
      try {
         // const data = await prisma.userLog.findMany({
         //    where: {
         //       User: {
         //          Village: {
         //             isDummy: false
         //          }
         //       },
         //       createdAt: {
         //          gte: moment().subtract(7, 'days').toDate(),
         //          lte: moment().toDate(),
         //       }
         //    },
         //    select: {
         //       createdAt: true,
         //    }
         // })

         const data = await prisma.$queryRaw`
               SELECT 
                  DATE(ul."createdAt") AS tanggal,
                  COUNT(*) AS total
               FROM "UserLog" ul
               JOIN "User" u ON ul."idUser" = u."id"
               JOIN "Village" v ON u."idVillage" = v."id"
               WHERE v."isDummy" = false
               AND ul."createdAt" >= NOW() - INTERVAL '7 days'
               GROUP BY tanggal
               ORDER BY tanggal;` as any[];

         const result = [];

         // ubah data ke map biar gampang lookup
         const map = data.reduce((acc: any, item: any) => {
            const key = moment(item.tanggal).format('YYYY-MM-DD');
            acc[key] = Number(item.total);
            return acc;
         }, {});

         // generate 7 hari terakhir
         for (let i = 6; i >= 0; i--) {
            const date = moment().subtract(i, 'days');

            const key = date.format('YYYY-MM-DD');

            result.push({
               date: date.format('DD MMM'),
               logs: map[key] || 0
            });
         }

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: result,
         };
      } catch (error) {
         console.error("[overview] daily-activity error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         detail: {
            summary: "Daily Activity",
            description: "Menu Overview - Mendapatkan data grafik aktivitas harian semua desa.",
            tags: ["overview"],
         },
      }
   )
   .get("/comparison-activity", async ({ query, set }) => {
      try {
         const villages = await prisma.village.findMany({
            where: { isDummy: false },
            select: { name: true },
         });

         const data = await prisma.$queryRaw`
               SELECT 
                  v."name",
                  COUNT(ul."id") AS total_logs
               FROM "UserLog" ul
               JOIN "User" u ON ul."idUser" = u."id"
               JOIN "Village" v ON u."idVillage" = v."id"
               WHERE v."isDummy" = false
               AND ul."createdAt" >= NOW() - INTERVAL '7 days'
               GROUP BY v."id", v."name"
               ORDER BY total_logs DESC;
            ` as any[];

         const logMap: Record<string, number> = {};

         data.forEach((item) => {
            logMap[item.name] = Number(item.total_logs);
         });

         const result = villages.map((v) => ({
            village: v.name,
            activity: logMap[v.name] || 0,
         }));


         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: result,
         };
      } catch (error) {
         console.error("[overview] comparison-activity error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         detail: {
            summary: "Comparison Activity",
            description: "Menu Overview - Mendapatkan data grafik perbandingan aktivitas desa selama 7 hari terakhir.",
            tags: ["overview"],
         },
      }
   )
   .post("/version-update", async ({ body, set }) => {
      try {
         const { mobile_latest_version, mobile_minimum_version, mobile_maintenance, mobile_message_update } = body

         await prisma.$transaction([
            prisma.setting.update({
               where: { id: "mobile_latest_version" },
               data: { value: mobile_latest_version },
            }),
            prisma.setting.update({
               where: { id: "mobile_minimum_version" },
               data: { value: mobile_minimum_version },
            }),
            prisma.setting.update({
               where: { id: "mobile_maintenance" },
               data: { value: mobile_maintenance.toString() },
            }),
            prisma.setting.update({
               where: { id: "mobile_message_update" },
               data: { value: mobile_message_update },
            }),
         ]);

         return {
            success: true,
            message: "Berhasil update data",
         };
      } catch (error) {
         console.error("[overview] version-update error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
         };
      }
   },
      {
         body: t.Object({
            mobile_latest_version: t.String({
               error: "mobile latest version harus diisi",
               description: "mobile latest version yang ingin diupdate"
            }),
            mobile_minimum_version: t.String({
               error: "mobile minimum version harus diisi",
               description: "mobile minimum version yang ingin diupdate"
            }),
            mobile_maintenance: t.Boolean({
               description: "status maintenance mobile app"
            }),
            mobile_message_update: t.String({
               description: "pesan update mobile app"
            }),
         }),
         detail: {
            summary: "Version Update",
            description: "Menu Overview - Mengupdate data versi aplikasi.",
            tags: ["overview"],
         },
      }
   )
   .get("/get-villages", async ({ query, set }) => {
      const { search, page } = query;
      const pageNum = Number(page ?? 1);
      try {
         const data = await prisma.village.findMany({
            where: {
               ...(search && { name: { contains: search, mode: 'insensitive' } })
            },
            select: {
               id: true,
               name: true,
               isActive: true,
               isDummy: true,
               createdAt: true,
               User: {
                  where: {
                     idUserRole: "supadmin"
                  },
                  select: {
                     name: true,
                  },
                  take: 1,
               },
            },
            skip: (pageNum - 1) * 10,
            take: 10,
         })

         const count = await prisma.village.count({
            where: {
               ...(search && { name: { contains: search, mode: 'insensitive' } })
            },
         })

         const result = data.map((village) => ({
            id: village.id,
            name: village.name,
            isActive: village.isActive,
            isDummy: village.isDummy,
            createdAt: formatDateTime(village.createdAt),
            perbekel: village.User[0]?.name || null,
         }));

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: result,
            totalPage: Math.ceil(count / 10),
            currentPage: pageNum,
            totalData: count,
         };
      } catch (error) {
         console.error("[villages] get-villages error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         query: t.Object({
            search: t.Optional(t.String({ description: "Kata kunci pencarian nama desa" })),
            page: t.Optional(t.String({ description: "Halaman data (default: 1)" })),
         }),
         detail: {
            summary: "Get Villages",
            description: "Menu Villages - Mendapatkan semua data desa.",
            tags: ["villages"],
         },
      }
   )
   .post("/create-villages", async ({ body, set }) => {
      const { name, desc, username, phone, nik, email, gender } = body;
      try {
         const create_village = await prisma.village.create({
            data: {
               name: name,
               desc: desc,
               isDummy: false,
            },
            select: {
               id: true
            }
         })

         if (create_village) {
            const create_group = await prisma.group.create({
               data: {
                  idVillage: create_village.id,
                  name: "Dinas",
               },
               select: {
                  id: true
               }
            })

            const create_position = await prisma.position.create({
               data: {
                  idGroup: create_group.id,
                  name: "Perbekel",
               },
               select: {
                  id: true
               }
            })

            const cek_user = await prisma.user.count({
               where: {
                  OR: [
                     { nik: nik },
                     { phone: phone },
                     { email: email },
                  ]
               },
            });

            if (cek_user > 0) {
               return {
                  success: true,
                  message: "Desa berhasil ditambahkan, namun user sudah terdaftar. Silahkan daftar user pada menu list user.",
               };
            }

            const create_user = await prisma.user.create({
               data: {
                  idUserRole: "supadmin",
                  idVillage: create_village.id,
                  idGroup: create_group.id,
                  idPosition: create_position.id,
                  nik: nik,
                  name: username,
                  phone: phone,
                  email: email,
                  gender: gender
               },
               select: {
                  id: true
               }
            })

            if (create_user) {
               return {
                  success: true,
                  message: "Desa dan user berhasil ditambahkan.",
               };
            } else {
               return {
                  success: true,
                  message: "Desa berhasil ditambahkan, namun user gagal ditambahkan. Silahkan daftar user pada menu list user.",
               };
            }
         } else {
            return {
               success: false,
               message: "Gagal menambahkan data",
            };
         }
      } catch (error) {
         console.error("[villages] create-villages error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
         };
      }
   },
      {
         body: t.Object({
            name: t.String({ description: "Nama desa" }),
            desc: t.String({ description: "Deskripsi desa" }),
            username: t.String({ description: "Username" }),
            phone: t.String({ description: "Nomor telepon" }),
            nik: t.String({ description: "Nomor Induk Kependudukan" }),
            email: t.String({ description: "Email" }),
            gender: t.String({ description: "Jenis Kelamin" }),
         }),
         detail: {
            summary: "Create Villages",
            description: "Menu Villages - Membuat data desa.",
            tags: ["villages"],
         },
      }
   )
   .get("/info-villages", async ({ query, set }) => {
      const { id } = query;
      try {
         const data = await prisma.village.findUnique({
            where: {
               id: id,
            },
            select: {
               id: true,
               name: true,
               isActive: true,
               isDummy: true,
               createdAt: true,
               updatedAt: true,
               desc: true,
               User: {
                  where: {
                     idUserRole: "supadmin"
                  },
                  select: {
                     name: true,
                  },
                  take: 1,
               },
            },
         })

         if (!data) {
            set.status = 404;
            return {
               success: false,
               message: "Desa tidak ditemukan",
               data: null,
            };
         }

         const result = data ? {
            id: data?.id,
            name: data?.name,
            isActive: data?.isActive,
            isDummy: data?.isDummy,
            desc: data?.desc,
            createdAt: data?.createdAt ? formatDateTime(data.createdAt) : null,
            updatedAt: data?.updatedAt ? formatDateTime(data.updatedAt) : null,
            perbekel: data?.User[0]?.name || null,
         } : null;

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: result,
         };
      } catch (error) {
         console.error("[detail-villages] info-villages error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         query: t.Object({
            id: t.Optional(t.String({ description: "ID desa" })),
         }),
         detail: {
            summary: "Info Villages",
            description: "Menu Detail Villages - Mendapatkan info data desa untuk header dan kolom Informasi Sistem.",
            tags: ["detail-villages"],
         },
      }
   )
   .get("/grid-villages", async ({ query, set }) => {
      const { id } = query;

      try {
         const village = await prisma.village.findUnique({
            where: { id: id }
         });

         if (!village) {
            set.status = 404;
            return {
               success: false,
               message: "Desa tidak ditemukan",
               data: null,
            };
         }

         const dataUser = await prisma.user.findMany({
            where: {
               idVillage: id,
               NOT: {
                  idUserRole: "developer"
               }
            }
         })

         const dataGroup = await prisma.group.findMany({
            where: {
               idVillage: id,
            }
         })

         const dataDivision = await prisma.division.findMany({
            where: {
               idVillage: id,
            }
         })

         const dataProject = await prisma.project.findMany({
            where: {
               idVillage: id
            }
         })


         const result = {
            user: {
               active: dataUser.filter((user) => user.isActive).length,
               nonActive: dataUser.filter((user) => !user.isActive).length,
            },
            group: {
               active: dataGroup.filter((group) => group.isActive).length,
               nonActive: dataGroup.filter((group) => !group.isActive).length,
            },
            division: {
               active: dataDivision.filter((division) => division.isActive).length,
               nonActive: dataDivision.filter((division) => !division.isActive).length,
            },
            project: {
               active: dataProject.filter((project) => project.isActive).length,
               nonActive: dataProject.filter((project) => !project.isActive).length,
            }
         };

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: result,
         };
      } catch (error) {
         console.error("[detail-villages] grid-villages error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         query: t.Object({
            id: t.Optional(t.String({ description: "ID desa" })),
         }),
         detail: {
            summary: "Grid Villages",
            description: "Menu Grid Villages - Mendapatkan info data desa untuk 4 grid untuk halaman detail desa.",
            tags: ["detail-villages"],
         },
      }
   )
   .get("/graph-log-villages", async ({ query, set }) => {
      const { id, time } = query;

      try {
         const village = await prisma.village.findUnique({
            where: { id },
         });

         if (!village) {
            set.status = 404;
            return {
               success: false,
               message: "Desa tidak ditemukan",
               data: null,
            };
         }

         const now = new Date();
         let startDate: Date;

         if (time === "daily") {
            startDate = new Date();
            startDate.setDate(now.getDate() - 13); // 14 hari
         } else if (time === "monthly") {
            startDate = new Date(now.getFullYear(), 0, 1); // awal tahun
         } else if (time === "yearly") {
            startDate = new Date(now.getFullYear() - 4, 0, 1); // 5 tahun terakhir (opsional)
         } else {
            startDate = new Date(0);
         }

         const dataLog = await prisma.userLog.findMany({
            where: {
               createdAt: {
                  gte: startDate,
               },
               User: {
                  idVillage: id,
               },
            },
            select: {
               createdAt: true,
            },
         });

         // =========================
         // 🔥 GROUPING
         // =========================
         const map: Record<string, number> = {};

         dataLog.forEach((log) => {
            const date = new Date(log.createdAt);

            let label = "";

            if (time === "daily") {
               label = date.toLocaleDateString("id-ID", {
                  day: "2-digit",
                  month: "short",
               });
            } else if (time === "monthly") {
               label = date.toLocaleDateString("id-ID", {
                  month: "short",
               });
            } else if (time === "yearly") {
               label = date.getFullYear().toString();
            }

            map[label] = (map[label] || 0) + 1;
         });

         // =========================
         // 🔥 FORMAT FINAL
         // =========================
         let result: any[] = [];

         if (time === "daily") {
            for (let i = 13; i >= 0; i--) {
               const d = new Date();
               d.setDate(d.getDate() - i);

               const label = d.toLocaleDateString("id-ID", {
                  day: "2-digit",
                  month: "short",
               });

               result.push({
                  label,
                  aktivitas: map[label] || 0,
               });
            }
         } else if (time === "monthly") {
            const year = now.getFullYear();
            for (let m = 0; m <= 11; m++) {
               const d = new Date(year, m, 1);

               const label = d.toLocaleDateString("id-ID", {
                  month: "short",
               });

               result.push({
                  label,
                  aktivitas: map[label] || 0,
               });
            }
         } else if (time === "yearly") {
            const years = Object.keys(map).map(Number);

            if (years.length === 0) {
               const currentYear = new Date().getFullYear();

               result = [
                  { label: currentYear.toString(), aktivitas: 0 }
               ];
            } else {
               const minYear = Math.min(...years);
               const maxYear = Math.max(...years);

               result = [];

               for (let y = minYear; y <= maxYear; y++) {
                  const label = y.toString();

                  result.push({
                     label,
                     aktivitas: map[label] || 0,
                  });
               }
            }
         }

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: result,
         };
      } catch (error) {
         console.error("[graph-log-villages] error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         query: t.Object({
            id: t.String({ description: "ID desa" }),
            time: t.Enum(
               {
                  daily: "daily",
                  monthly: "monthly",
                  yearly: "yearly",
               },
               {
                  description: "Rentang waktu (daily = 14 hari, monthly = 1 tahun, yearly = per tahun)",
               }
            ),
         }),
         detail: {
            summary: "Graph Log Villages",
            description:
               "Mendapatkan data grafik log aktivitas desa berdasarkan rentang waktu (harian, bulanan, tahunan)",
            tags: ["detail-villages"],
         },
      }
   )
   .get("/list-group-villages", async ({ query, set }) => {
      const { id } = query;
      try {
         const data = await prisma.group.findMany({
            where: {
               idVillage: id,
            },
            select: {
               id: true,
               name: true,
            }
         })

         if (!data) {
            set.status = 404;
            return {
               success: false,
               message: "Desa tidak ditemukan",
               data: null,
            };
         }

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: data,
         };
      } catch (error) {
         console.error("[detail-villages] list-group-villages error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         query: t.Object({
            id: t.Optional(t.String({ description: "ID desa" })),
         }),
         detail: {
            summary: "List Group Villages",
            description: "Menu Detail Villages - Mendapatkan list group untuk dropdown.",
            tags: ["detail-villages"],
         },
      }
   )
   .get("/list-position-villages", async ({ query, set }) => {
      const { id } = query;
      try {
         const data = await prisma.position.findMany({
            where: {
               idGroup: id,
            },
            select: {
               id: true,
               name: true,
            }
         })

         if (!data) {
            set.status = 404;
            return {
               success: false,
               message: "Posisi tidak ditemukan",
               data: null,
            };
         }

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: data,
         };
      } catch (error) {
         console.error("[detail-villages] list-position-villages error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         query: t.Object({
            id: t.Optional(t.String({ description: "ID group" })),
         }),
         detail: {
            summary: "List Position Villages",
            description: "Menu Detail Villages - Mendapatkan list jabatan untuk dropdown.",
            tags: ["detail-villages"],
         },
      }
   )
   .get("/list-userrole-villages", async ({ query, set }) => {
      try {
         const data = await prisma.userRole.findMany({
            select: {
               id: true,
               name: true,
            }
         })

         if (!data) {
            set.status = 404;
            return {
               success: false,
               message: "Role tidak ditemukan",
               data: null,
            };
         }

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: data,
         };
      } catch (error) {
         console.error("[detail-villages] list-userrole-villages error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         detail: {
            summary: "List User Role",
            description: "Menu Detail Villages - Mendapatkan list role untuk dropdown.",
            tags: ["detail-villages"],
         },
      }
   )
   .post("/edit-villages", async ({ body, set }) => {
      const { id, name, desc, isDummy } = body;

      try {
         const village = await prisma.village.findUnique({
            where: { id },
         });

         if (!village) {
            set.status = 404;
            return {
               success: false,
               message: "Desa tidak ditemukan",
            };
         }

         const upd = await prisma.village.update({
            where: { id },
            data: {
               name,
               desc,
               isDummy,
            },
         });

         return {
            success: true,
            message: "Berhasil mengupdate data",
         };
      } catch (error) {
         console.error("[edit-villages] error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
         };
      }
   },
      {
         body: t.Object({
            id: t.String({ description: "ID desa" }),
            name: t.String({ description: "Nama desa" }),
            desc: t.String({ description: "Deskripsi desa" }),
            isDummy: t.Boolean({ description: "Apakah desa dummy" }),
         }),
         detail: {
            summary: "Edit Villages",
            description:
               "Mengupdate data desa",
            tags: ["detail-villages"],
         },
      }
   )
   .post("/update-status-villages", async ({ body, set }) => {
      const { id, active } = body;

      try {
         const village = await prisma.village.findUnique({
            where: { id },
         });

         if (!village) {
            set.status = 404;
            return {
               success: false,
               message: "Desa tidak ditemukan",
            };
         }

         const upd = await prisma.village.update({
            where: { id },
            data: {
               isActive: active,
            },
         });

         return {
            success: true,
            message: "Berhasil mengupdate data",
         };
      } catch (error) {
         console.error("[update-status-villages] error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
         };
      }
   },
      {
         body: t.Object({
            id: t.String({ description: "ID desa" }),
            active: t.Boolean({ description: "Status desa" }),
         }),
         detail: {
            summary: "Update Status Villages",
            description:
               "Mengupdate status desa",
            tags: ["detail-villages"],
         },
      }
   )
   .get("/log-all-villages", async ({ query, set }) => {
      const { page = 1, search } = query;
      const pageNum = Number(page) || 1;
      const take = 15;
      const skip = (pageNum - 1) * take;

      try {
         const dataLog = await prisma.userLog.findMany({
            where: {
               ...(search && {
                  OR: [
                     {
                        User: {
                           name: {
                              contains: search,
                              mode: "insensitive",
                           },
                        },
                     },
                     {
                        User: {
                           Village: {
                              name: {
                                 contains: search,
                                 mode: "insensitive",
                              },
                           },
                        },
                     },
                  ],
               }),
            },
            select: {
               id: true,
               createdAt: true,
               action: true,
               desc: true,
               User: {
                  select: {
                     name: true,
                     Village: {
                        select: {
                           name: true,
                        },
                     },
                  },
               },
            },
            orderBy: {
               createdAt: "desc",
            },
            skip,
            take,
         });

         const total = await prisma.userLog.count({
            where: {
               ...(search && {
                  OR: [
                     {
                        User: {
                           name: {
                              contains: search,
                              mode: "insensitive",
                           },
                        },
                     },
                     {
                        User: {
                           Village: {
                              name: {
                                 contains: search,
                                 mode: "insensitive",
                              },
                           },
                        },
                     },
                  ],
               }),
            },
         });

         const result = dataLog.map((item) => ({
            id: item.id,
            createdAt: timeAgo(item.createdAt),
            action: item.action,
            desc: item.desc,
            username: item.User.name,
            village: item.User.Village.name,
         }));


         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: {
               log: result,
               total,
               totalPage: Math.ceil(total / take),
               currentPage: pageNum,
            },
         };
      } catch (error) {
         console.error("[log-villages] error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         query: t.Object({
            page: t.Optional(t.String({ description: "Halaman" })),
            search: t.Optional(t.String({ description: "Pencarian" })),
         }),
         detail: {
            summary: "Log Villages",
            description:
               "Mendapatkan data log aktivitas desa berdasarkan halaman dan pencarian",
            tags: ["log-activity"],
         },
      }
   )
   .get("/user", async ({ query, set }) => {
      const { page = 1, search } = query;
      const pageNum = Number(page) || 1;
      const take = 15;
      const skip = (pageNum - 1) * take;

      try {
         const data = await prisma.user.findMany({
            where: {
               ...(search && {
                  OR: [
                     {
                        name: {
                           contains: search,
                           mode: "insensitive",
                        },
                     },
                     {
                        phone: {
                           contains: search,
                           mode: "insensitive",
                        },
                     },
                     {
                        email: {
                           contains: search,
                           mode: "insensitive",
                        },
                     },
                     {
                        nik: {
                           contains: search,
                           mode: "insensitive",
                        },
                     },
                     {
                        Village: {
                           name: {
                              contains: search,
                              mode: "insensitive",
                           },
                        },
                     },
                     {
                        idUserRole: search,
                     },
                  ],
               }),
            },
            select: {
               id: true,
               name: true,
               nik: true,
               phone: true,
               email: true,
               isWithoutOTP: true,
               isActive: true,
               idUserRole: true,
               idVillage: true,
               idGroup: true,
               idPosition: true,
               gender: true,
               UserRole: {
                  select: {
                     name: true,
                  },
               },
               Village: {
                  select: {
                     name: true,
                  },
               },
               Group: {
                  select: {
                     name: true,
                  },
               },
               Position: {
                  select: {
                     name: true,
                  },
               },
            },
            orderBy: {
               createdAt: "desc",
            },
            skip,
            take,
         });

         const total = await prisma.user.count({
            where: {
               ...(search && {
                  OR: [
                     {
                        name: {
                           contains: search,
                           mode: "insensitive",
                        },
                     },
                     {
                        phone: {
                           contains: search,
                           mode: "insensitive",
                        },
                     },
                     {
                        email: {
                           contains: search,
                           mode: "insensitive",
                        },
                     },
                     {
                        nik: {
                           contains: search,
                           mode: "insensitive",
                        },
                     },
                     {
                        Village: {
                           name: {
                              contains: search,
                              mode: "insensitive",
                           },
                        },
                     },
                     {
                        idUserRole: search,
                     },
                  ],
               }),
            },
         });

         const result = data.map((item) => ({
            id: item.id,
            name: item.name,
            nik: item.nik,
            phone: item.phone,
            email: item.email,
            gender: item.gender,
            isWithoutOTP: item.isWithoutOTP,
            isActive: item.isActive,
            role: item.UserRole?.name,
            village: item.Village?.name,
            group: item.Group?.name,
            position: item.Position?.name,
            idUserRole: item.idUserRole,
            idVillage: item.idVillage,
            idGroup: item.idGroup,
            idPosition: item.idPosition,
         }));

         return {
            success: true,
            message: "Berhasil mendapatkan data",
            data: {
               user: result,
               total,
               totalPage: Math.ceil(total / take),
               currentPage: pageNum,
            },
         };
      } catch (error) {
         console.error("[user] error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
            data: null,
         };
      }
   },
      {
         query: t.Object({
            page: t.Optional(t.String({ description: "Halaman" })),
            search: t.Optional(t.String({ description: "Pencarian" })),
         }),
         detail: {
            summary: "User",
            description:
               "Mendapatkan data user berdasarkan halaman dan pencarian",
            tags: ["user"],
         },
      }
   )
   .post("/create-user", async ({ body, set }) => {
      const { name, nik, phone, email, gender, idUserRole, idVillage, idGroup, idPosition } = body;

      try {
         const cekUser = await prisma.user.findFirst({
            where: {
               OR: [
                  { nik },
                  { phone },
                  { email },
               ],
            },
         });

         if (cekUser) {
            return {
               success: false,
               message: "User sudah ada",
            };
         }

         const user = await prisma.user.create({
            data: {
               name,
               nik,
               phone,
               email,
               gender,
               idUserRole,
               idVillage,
               idGroup,
               idPosition,
            },
         });

         return {
            success: true,
            message: "Berhasil membuat user",
         };
      } catch (error) {
         console.error("[create-user] error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
         };
      }
   },
      {
         body: t.Object({
            name: t.String({ description: "Nama" }),
            nik: t.String({ description: "NIK" }),
            phone: t.String({ description: "Nomor Telepon" }),
            email: t.String({ description: "Email" }),
            gender: t.String({ description: "Jenis Kelamin" }),
            idUserRole: t.String({ description: "ID Role" }),
            idVillage: t.String({ description: "ID Desa" }),
            idGroup: t.String({ description: "ID Group" }),
            idPosition: t.Optional(t.String({ description: "ID Posisi" })),
         }),
         detail: {
            summary: "Create User",
            description:
               "Membuat user",
            tags: ["user"],
         },
      }
   )
   .post("/edit-user", async ({ body, set }) => {
      const { id, name, nik, phone, email, gender, idUserRole, idVillage, idGroup, idPosition, isActive, isWithoutOTP } = body;

      try {
         const cekId = await prisma.user.findFirst({
            where: {
               id,
            },
         });

         if (!cekId) {
            return {
               success: false,
               message: "User tidak ditemukan",
            };
         }

         const cekUser = await prisma.user.findFirst({
            where: {
               id: {
                  not: id,
               },
               OR: [
                  { nik },
                  { phone },
                  { email },
               ],
            },
         });

         if (cekUser) {
            return {
               success: false,
               message: "User sudah ada",
            };
         }

         const user = await prisma.user.update({
            where: {
               id,
            },
            data: {
               name,
               nik,
               phone,
               email,
               gender,
               idUserRole,
               idVillage,
               idGroup,
               idPosition,
               isActive,
               isWithoutOTP,
            },
         });

         return {
            success: true,
            message: "Berhasil mengedit user",
         };
      } catch (error) {
         console.error("[edit-user] error:", error);
         set.status = 500;
         return {
            success: false,
            message: "Terjadi kesalahan pada server",
         };
      }
   },
      {
         body: t.Object({
            id: t.String({ description: "ID" }),
            name: t.String({ description: "Nama" }),
            nik: t.String({ description: "NIK" }),
            phone: t.String({ description: "Nomor Telepon" }),
            email: t.String({ description: "Email" }),
            gender: t.String({ description: "Jenis Kelamin" }),
            idUserRole: t.String({ description: "ID Role" }),
            idVillage: t.String({ description: "ID Desa" }),
            idGroup: t.String({ description: "ID Group" }),
            idPosition: t.Optional(t.Union([t.String(), t.Null()], { description: "ID Posisi" })),
            isActive: t.Boolean({ description: "Aktif" }),
            isWithoutOTP: t.Boolean({ description: "Tanpa OTP" }),
         }),
         detail: {
            summary: "Edit User",
            description:
               "Mengedit user",
            tags: ["user"],
         },
      }
   )

   // ─── API KEY MANAGEMENT ──────────────────────────────────────────────────

   .get("/api-keys", async ({ set }) => {
      try {
         const keys = await prisma.apiKey.findMany({ orderBy: { createdAt: "desc" } });
         return {
            success: true,
            message: "Berhasil mendapatkan API keys",
            data: keys.map((k) => ({ ...k, key: k.key.slice(0, 8) + "••••••••" + k.key.slice(-4) })),
         };
      } catch (error) {
         set.status = 500;
         return { success: false, message: "Gagal mendapatkan API keys" };
      }
   }, {
      detail: { summary: "List API Keys", tags: ["api-key"] },
   })

   .post("/api-keys", async ({ body, set }) => {
      try {
         const rawKey = "ak_" + crypto.randomUUID().replace(/-/g, "");
         const key = await prisma.apiKey.create({ data: { name: body.name, key: rawKey } });
         return {
            success: true,
            message: "API key berhasil dibuat",
            data: { ...key, key: rawKey },
         };
      } catch (error) {
         set.status = 500;
         return { success: false, message: "Gagal membuat API key" };
      }
   }, {
      body: t.Object({ name: t.String({ description: "Nama key" }) }),
      detail: { summary: "Buat API Key", tags: ["api-key"] },
   })

   .patch("/api-keys/:id", async ({ params, body, set }) => {
      try {
         const key = await prisma.apiKey.update({
            where: { id: params.id },
            data: { isActive: body.isActive },
         });
         return {
            success: true,
            message: "API key berhasil diupdate",
            data: { ...key, key: key.key.slice(0, 8) + "••••••••" + key.key.slice(-4) },
         };
      } catch (error) {
         set.status = 500;
         return { success: false, message: "Gagal mengupdate API key" };
      }
   }, {
      params: t.Object({ id: t.String() }),
      body: t.Object({ isActive: t.Boolean({ description: "Status aktif" }) }),
      detail: { summary: "Toggle API Key", tags: ["api-key"] },
   })

   .delete("/api-keys/:id", async ({ params, set }) => {
      try {
         await prisma.apiKey.delete({ where: { id: params.id } });
         return { success: true, message: "API key berhasil dihapus" };
      } catch (error) {
         set.status = 500;
         return { success: false, message: "Gagal menghapus API key" };
      }
   }, {
      params: t.Object({ id: t.String() }),
      detail: { summary: "Hapus API Key", tags: ["api-key"] },
   });

export const GET = MonitoringServer.handle;
export const POST = MonitoringServer.handle;
export const PATCH = MonitoringServer.handle;
export const DELETE = MonitoringServer.handle;
export const OPTIONS = MonitoringServer.handle;
