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/noc
const NocServer = new Elysia({ prefix: "/api/noc" })
   .use(cors({
      origin: "*",
      methods: ["GET", "POST", "OPTIONS"],
   }))
   .use(swagger({
      path: "/docs", // Karena prefix instance adalah /api/noc, maka ini akan diakses di /api/noc/docs
      documentation: {
         info: {
            title: "Sistem Desa Mandiri - NOC API",
            version: "1.0.0",
            description: "API Khusus untuk kebutuhan NOC (Network Operation Center) dan Monitoring Desa",
         },
         tags: [
            { name: "NOC", description: "Endpoint khusus monitoring" }
         ]
      }
   }))

   // ── GET /api/noc/active-divisions ──────────────────────────────────────────
   .get(
      "/active-divisions",
      async ({ query, set }) => {
         const { idDesa, limit } = query;

         if (!idDesa) {
            set.status = 400;
            return {
               success: false,
               message: "Parameter idDesa wajib diisi",
               data: null,
            };
         }

         const maxResults = Number(limit ?? 5);

         try {
            // Cek apakah desa ada
            const village = await prisma.village.findUnique({
               where: { id: idDesa },
               select: { id: true, name: true },
            });

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

            // Ambil semua divisi milik desa ini
            const divisions = await prisma.division.findMany({
               where: {
                  idVillage: idDesa,
                  isActive: true,
               },
               select: {
                  id: true,
                  name: true,
                  idGroup: true,
                  Group: {
                     select: {
                        name: true,
                     },
                  },
                  _count: {
                     select: {
                        DivisionProject: true,
                     },
                  },
               },
            });

            // Hitung total kegiatan per divisi & urutkan descending, ambil top sesuai limit
            const ranked = divisions
               .map((d: any) => ({
                  id: d.id,
                  division: d.name,
                  group: d.Group.name,
                  totalKegiatan: d._count.DivisionProject
               }))
               .sort((a: any, b: any) => b.totalKegiatan - a.totalKegiatan)
               .slice(0, maxResults);

            return {
               success: true,
               message: "Berhasil mendapatkan divisi teraktif",
               data: {
                  idDesa: village.id,
                  namaDesa: village.name,
                  divisi: ranked,
               },
            };
         } catch (error) {
            console.error("[NOC] active-divisions error:", error);
            set.status = 500;
            return {
               success: false,
               message: "Terjadi kesalahan pada server",
               data: null,
            };
         }
      },
      {
         query: t.Object({
            idDesa: t.String({ description: "ID Desa yang ingin dicari" }),
            limit: t.Optional(t.String({ description: "Jumlah maksimal data (default: 5)" })),
         }),
         detail: {
            summary: "Divisi Teraktif",
            description: "Menu Beranda - Mendapatkan daftar divisi teraktif berdasarkan jumlah proyek pada desa tertentu.",
            tags: ["NOC"],
         },
      }
   )

   // ── GET /api/noc/latest-projects ──────────────────────────────────────────
   .get(
      "/latest-projects",
      async ({ query, set }) => {
         const { idDesa, limit } = query;

         if (!idDesa) {
            set.status = 400;
            return {
               success: false,
               message: "Parameter idDesa wajib diisi",
               data: null,
            };
         }

         const maxResults = Math.min(Number(limit ?? 5), 50);

         try {
            // Cek apakah desa ada
            const village = await prisma.village.findUnique({
               where: { id: idDesa },
               select: { id: true, name: true },
            });

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

            // Ambil proyek umum terbaru dari desa ini
            const projects = await prisma.project.findMany({
               where: {
                  idVillage: idDesa,
                  isActive: true,
               },
               select: {
                  id: true,
                  title: true,
                  status: true,
                  desc: true,
                  updatedAt: true,
                  Group: {
                     select: {
                        name: true,
                     },
                  },
                  User: {
                     select: {
                        name: true,
                     },
                  },
               },
               orderBy: {
                  updatedAt: "desc",
               },
               take: maxResults,
            });

            const mapped = projects.map((p: any) => ({
               id: p.id,
               title: p.title,
               status: p.status,
               desc: p.desc,
               group: p.Group.name,
               createdBy: p.User.name,
               updatedAt: p.updatedAt,
            }));

            return {
               success: true,
               message: "Berhasil mendapatkan proyek terbaru",
               data: {
                  idDesa: village.id,
                  namaDesa: village.name,
                  total: mapped.length,
                  projects: mapped,
               },
            };
         } catch (error) {
            console.error("[NOC] latest-projects error:", error);
            set.status = 500;
            return {
               success: false,
               message: "Terjadi kesalahan pada server",
               data: null,
            };
         }
      },
      {
         query: t.Object({
            idDesa: t.String({ description: "ID Desa yang ingin dicari" }),
            limit: t.Optional(
               t.String({ description: "Jumlah maksimal proyek (default: 5, maks: 50)" })
            ),
         }),
         detail: {
            summary: "Latest Projects General",
            description: "Menu kinerja divisi - Mendapatkan daftar proyek umum terbaru dari berbagai grup pada desa tertentu.",
            tags: ["NOC"],
         },
      }
   )

   // ── GET /api/noc/upcoming-events ───────────────────────────────────────────
   .get(
      "/upcoming-events",
      async ({ query, set }) => {
         const { idDesa, limit, filter } = query;

         if (!idDesa) {
            set.status = 400;
            return {
               success: false,
               message: "Parameter idDesa wajib diisi",
               data: null,
            };
         }

         const maxResults = Math.min(Number(limit ?? 10), 50);
         const today = moment().startOf("day").toDate();

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

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

            const events = await prisma.divisionCalendarReminder.findMany({
               where: {
                  isActive: true,
                  dateStart: {
                     gte: today,
                  },
                  Division: {
                     idVillage: idDesa,
                     isActive: true,
                  },
                  DivisionCalendar: {
                     isActive: true,
                  },
               },
               select: {
                  id: true,
                  idCalendar: true,
                  dateStart: true,
                  dateEnd: true,
                  timeStart: true,
                  timeEnd: true,
                  status: true,
                  Division: {
                     select: {
                        id: true,
                        name: true,
                     },
                  },
                  DivisionCalendar: {
                     select: {
                        title: true,
                        desc: true,
                        linkMeet: true,
                        repeatEventTyper: true,
                        User: {
                           select: {
                              name: true,
                           },
                        },
                     },
                  },
               },
               orderBy: [
                  { dateStart: "asc" },
                  { timeStart: "asc" },
               ],
               take: maxResults,
            });

            const todayMoment = moment().startOf("day");
            const mapper = (e: any) => ({
               id: e.id,
               idCalendar: e.idCalendar,
               title: e.DivisionCalendar.title,
               desc: e.DivisionCalendar.desc,
               linkMeet: e.DivisionCalendar.linkMeet ?? null,
               repeatEventTyper: e.DivisionCalendar.repeatEventTyper,
               dateStart: moment(e.dateStart).format("YYYY-MM-DD"),
               dateEnd: e.dateEnd
                  ? moment(e.dateEnd).format("YYYY-MM-DD")
                  : null,
               timeStart: moment.utc(e.timeStart).format("HH:mm"),
               timeEnd: moment.utc(e.timeEnd).format("HH:mm"),
               status: e.status,
               createdBy: e.DivisionCalendar.User.name,
               divisi: {
                  id: e.Division.id,
                  name: e.Division.name,
               },
            });

            const todayEvents = events.filter((e: any) => moment(e.dateStart).isSame(todayMoment, 'day')).map(mapper);
            const upcomingEvents = events.filter((e: any) => moment(e.dateStart).isAfter(todayMoment, 'day')).map(mapper);

            let data: any = {
               idDesa: village.id,
               namaDesa: village.name,
            };

            if (filter === "today") {
               data.events = todayEvents;
            } else if (filter === "upcoming") {
               data.events = upcomingEvents;
            } else {
               data.today = todayEvents;
               data.upcoming = upcomingEvents;
            }

            return {
               success: true,
               message: "Berhasil mendapatkan events",
               data: data,
            };
         } catch (error) {
            console.error("[NOC] upcoming-events error:", error);
            set.status = 500;
            return {
               success: false,
               message: "Terjadi kesalahan pada server",
               data: null,
            };
         }
      },
      {
         query: t.Object({
            idDesa: t.String({ description: "ID Desa yang ingin dicari" }),
            limit: t.Optional(
               t.String({ description: "Jumlah maksimal event (default: 10, maks: 50)" })
            ),
            filter: t.Optional(
               t.String({ description: "Filter event: 'today' atau 'upcoming'" })
            ),
         }),
         detail: {
            summary: "Events (Today & Upcoming)",
            description: "Menu beranda dan kinerja divisi - Mendapatkan daftar event pada hari ini dan yang akan datang untuk semua divisi pada desa tertentu.",
            tags: ["NOC"],
         },
      }
   )

   // ── GET /api/noc/diagram-jumlah-document ───────────────────────────────────────────────
   .get(
      "/diagram-jumlah-document",
      async ({ query, set }) => {
         const { idDesa } = query;

         if (!idDesa) {
            set.status = 400;
            return {
               success: false,
               message: "Parameter idDesa wajib diisi",
               data: null,
            };
         }

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

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

            const documents = await prisma.divisionDocumentFolderFile.findMany({
               where: {
                  isActive: true,
                  category: 'FILE',
                  Division: {
                     isActive: true,
                     idVillage: idDesa,
                     Group: {
                        isActive: true,
                     }
                  }
               }
            })

            const groupData = _.map(_.groupBy(documents, "extension"), (v: any) => ({
               file: v[0].extension,
               jumlah: v.length,
            }))

            const image = ['jpg', 'jpeg', 'png', 'heic']


            let hasilImage = {
               label: 'Gambar',
               value: 0,
               color: '#fac858'
            }

            let hasilFile = {
               label: 'Dokumen',
               value: 0,
               color: '#92cc76'
            }

            groupData.map((v: any) => {
               if (image.some((i: any) => i == v.file)) {
                  hasilImage = {
                     label: 'Gambar',
                     value: hasilImage.value + v.jumlah,
                     color: '#fac858'
                  }
               } else {
                  hasilFile = {
                     label: 'Dokumen',
                     value: hasilFile.value + v.jumlah,
                     color: '#92cc76'
                  }
               }
            })

            const allData = [hasilImage, hasilFile]

            return {
               success: true,
               message: "Berhasil mendapatkan jumlah document",
               data: allData
            };
         } catch (error) {
            console.error("[NOC] jumlah-document error:", error);
            set.status = 500;
            return {
               success: false,
               message: "Terjadi kesalahan pada server",
               data: null,
            };
         }
      },
      {
         query: t.Object({
            idDesa: t.String({ description: "ID Desa yang ingin dicari" }),
         }),
         detail: {
            summary: "Diagram Jumlah Document",
            description: "Menu kinerja divisi - Mendapatkan diagram jumlah document pada desa tertentu.",
            tags: ["NOC"],
         },
      }
   )

   // -- GET /api/noc/diagram-progres-kegiatan
   .get(
      "/diagram-progres-kegiatan",
      async ({ query, set }) => {
         const { idDesa } = query;

         if (!idDesa) {
            set.status = 400;
            return {
               success: false,
               message: "Parameter idDesa wajib diisi",
               data: null,
            };
         }

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

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

            const data = await prisma.project.groupBy({
               where: {
                  isActive: true,
                  idVillage: idDesa,
                  Group: {
                     isActive: true,
                  }
               },
               by: ["status"],
               _count: true
            })

            const dataStatus = [{ name: 'Segera dikerjakan', status: 0, color: '#177AD5' }, { name: 'Dikerjakan', status: 1, color: '#fac858' }, { name: 'Selesai dikerjakan', status: 2, color: '#92cc76' }, { name: 'Dibatalkan', status: 3, color: '#ED6665' }]
            const hasil: any[] = []
            let input
            for (let index = 0; index < dataStatus.length; index++) {
               const cek = data.some((i: any) => i.status == dataStatus[index].status)
               if (cek) {
                  const find = ((Number(data.find((i: any) => i.status == dataStatus[index].status)?._count) * 100) / data.reduce((n: any, { _count }: any) => n + _count, 0)).toFixed(2)
                  const fix = find != "100.00" ? find.substr(-2, 2) == "00" ? find.substr(0, 2) : find : "100"
                  input = {
                     text: fix + '%',
                     value: fix,
                     color: dataStatus[index].color
                  }
               } else {
                  input = {
                     text: '0%',
                     value: 0,
                     color: dataStatus[index].color
                  }
               }
               hasil.push(input)
            }

            return {
               success: true,
               message: "Berhasil mendapatkan progres kegiatan",
               data: hasil
            };
         } catch (error) {
            console.error("[NOC] progres-kegiatan error:", error);
            set.status = 500;
            return {
               success: false,
               message: "Terjadi kesalahan pada server",
               data: null,
            };
         }
      },
      {
         query: t.Object({
            idDesa: t.String({ description: "ID Desa yang ingin dicari" }),
         }),
         detail: {
            summary: "Diagram Progres Kegiatan",
            description: "Menu kinerja divisi - Mendapatkan diagram progres kegiatan pada desa tertentu.",
            tags: ["NOC"],
         },
      }
   )

   // -- GET /api/noc/latest-discussion
   .get(
      "/latest-discussion",
      async ({ query, set }) => {
         const { idDesa, limit } = query;

         const maxResults = Math.min(Number(limit ?? 5), 50);

         if (!idDesa) {
            set.status = 400;
            return {
               success: false,
               message: "Parameter idDesa wajib diisi",
               data: null,
            };
         }

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

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

            const data = await prisma.discussion.findMany({
               take: maxResults,
               where: {
                  idVillage: idDesa,
                  isActive: true,
                  status: 1,
               },
               select: {
                  id: true,
                  title: true,
                  desc: true,
                  createdAt: true,
                  User: {
                     select: {
                        name: true
                     }
                  },
                  Group: {
                     select: {
                        name: true
                     }
                  }
               },
               orderBy: {
                  createdAt: "desc"
               }
            })

            const allData = data.map((v: any) => ({
               ..._.omit(v, ["createdAt", "User", "Group"]),
               date: moment(v.createdAt).format("ll"),
               user: v.User.name,
               group: v.Group.name
            }))

            return {
               success: true,
               message: "Berhasil mendapatkan latest discussion",
               data: allData
            };
         } catch (error) {
            console.error("[NOC] latest-discussion error:", error);
            set.status = 500;
            return {
               success: false,
               message: "Terjadi kesalahan pada server",
               data: null,
            };
         }
      },
      {
         query: t.Object({
            idDesa: t.String({ description: "ID Desa yang ingin dicari" }),
            limit: t.Optional(t.String({ description: "Limit data" })),
         }),
         detail: {
            summary: "Latest Discussion",
            description: "Menu kinerja divisi - Mendapatkan latest discussion pada desa tertentu.",
            tags: ["NOC"],
         },
      }
   );


export const GET = NocServer.handle;
export const POST = NocServer.handle;
