import type { Request, Response } from "express";
import { prisma } from "../../config/prisma.js";
import { asyncHandler } from "../../utils/asyncHandler.js";
import { computePriorityForDate, summarisePriority, PRIORITY_LABELS } from "../../utils/priority.js";
import { listRenewals } from "../../utils/renewals.js";

export const stats = asyncHandler(async (req: Request, res: Response) => {
  const companyId = req.query.companyId ? Number(req.query.companyId) : null;
  const companyFilter = companyId ? { companyId } : {};
  const employeeFilter = companyId ? { companyId } : {};

  const today = new Date();
  const inDays = (n: number) => new Date(today.getTime() + n * 86400000);

  const [employees, activeEmployees, companies, activeCompanies, documents, activeDocs] = await Promise.all([
    prisma.employee.count({ where: employeeFilter }),
    prisma.employee.count({ where: { ...employeeFilter, status: "active" } }),
    companyId ? null : prisma.company.count(),
    companyId ? null : prisma.company.count({ where: { isActive: true } }),
    prisma.document.count({ where: companyFilter }),
    prisma.document.count({ where: { ...companyFilter, status: "active" } }),
  ]);

  const [expiredDocs, docs7, docs30, docs60] = await Promise.all([
    prisma.document.count({ where: { ...companyFilter, expiryDate: { lt: today } } }),
    prisma.document.count({ where: { ...companyFilter, expiryDate: { gte: today, lte: inDays(7) } } }),
    prisma.document.count({ where: { ...companyFilter, expiryDate: { gte: today, lte: inDays(30) } } }),
    prisma.document.count({ where: { ...companyFilter, expiryDate: { gte: today, lte: inDays(60) } } }),
  ]);

  const [expiredIqamas, iqamas7, iqamas30, expiredPassports, passports30, expiredInsurance, insurance30] = await Promise.all([
    prisma.employee.count({ where: { ...employeeFilter, iqamaExpiry: { lt: today } } }),
    prisma.employee.count({ where: { ...employeeFilter, iqamaExpiry: { gte: today, lte: inDays(7) } } }),
    prisma.employee.count({ where: { ...employeeFilter, iqamaExpiry: { gte: today, lte: inDays(30) } } }),
    prisma.employee.count({ where: { ...employeeFilter, passportExpiry: { lt: today } } }),
    prisma.employee.count({ where: { ...employeeFilter, passportExpiry: { gte: today, lte: inDays(30) } } }),
    prisma.employee.count({ where: { ...employeeFilter, insuranceExpiry: { lt: today } } }),
    prisma.employee.count({ where: { ...employeeFilter, insuranceExpiry: { gte: today, lte: inDays(30) } } }),
  ]);

  const [companiesExpiring, companiesExpired] = companyId
    ? [0, 0]
    : await Promise.all([
        prisma.company.count({ where: { isActive: true, crExpiry: { gte: today, lte: inDays(30) } } }),
        prisma.company.count({ where: { crExpiry: { lt: today } } }),
      ]);

  const unreadNotifications = await prisma.notification.count({ where: { readAt: null } });

  res.json({
    success: true,
    data: {
      employees,
      activeEmployees,
      companies: companies ?? 0,
      activeCompanies: activeCompanies ?? 0,
      companiesExpiring,
      companiesExpired,
      documents,
      activeDocs,
      expiredDocs,
      docs7,
      docs30,
      docs60,
      expiredIqamas,
      iqamas7,
      iqamas30,
      expiredPassports,
      passports30,
      expiredInsurance,
      insurance30,
      unreadNotifications,
    },
  });
});

export const upcoming = asyncHandler(async (req: Request, res: Response) => {
  const limit = Number(req.query.limit || 10);
  const days = Number(req.query.days || 90);
  const companyId = req.query.companyId ? Number(req.query.companyId) : null;
  const today = new Date();
  const horizon = new Date(today.getTime() + days * 86400000);

  const documents = await prisma.document.findMany({
    where: {
      ...(companyId ? { companyId } : {}),
      expiryDate: { lte: horizon },
    },
    include: {
      company: { select: { id: true, name: true } },
      employee: { select: { id: true, fullName: true } },
      documentType: true,
    },
    orderBy: { expiryDate: "asc" },
    take: limit,
  });

  const data = await Promise.all(
    documents.map(async (d) => ({ ...d, priority: summarisePriority(await computePriorityForDate(d.expiryDate)) }))
  );
  res.json({ success: true, data });
});

export const priorityDistribution = asyncHandler(async (req: Request, res: Response) => {
  const companyId = req.query.companyId ? Number(req.query.companyId) : null;
  const companyFilter = companyId ? { companyId } : {};
  const today = new Date();
  const thresholds = await getThresholds();
  const inDays = (n: number) => new Date(today.getTime() + n * 86400000);

  const [expired, critical, high, medium, low] = await Promise.all([
    prisma.document.count({ where: { ...companyFilter, expiryDate: { lt: today } } }),
    prisma.document.count({ where: { ...companyFilter, expiryDate: { gte: today, lte: inDays(thresholds.critical) } } }),
    prisma.document.count({ where: { ...companyFilter, expiryDate: { gt: inDays(thresholds.critical), lte: inDays(thresholds.high) } } }),
    prisma.document.count({ where: { ...companyFilter, expiryDate: { gt: inDays(thresholds.high), lte: inDays(thresholds.medium) } } }),
    prisma.document.count({ where: { ...companyFilter, expiryDate: { gt: inDays(thresholds.medium) } } }),
  ]);
  res.json({
    success: true,
    data: [
      { key: "expired", label: PRIORITY_LABELS.expired, count: expired },
      { key: "critical", label: PRIORITY_LABELS.critical, count: critical },
      { key: "high", label: PRIORITY_LABELS.high, count: high },
      { key: "medium", label: PRIORITY_LABELS.medium, count: medium },
      { key: "low", label: PRIORITY_LABELS.low, count: low },
    ],
  });
});

/**
 * قائمة أولويات التجديد الموحدة:
 * سجلات الشركات + المستندات الحكومية + الإقامات + الجوازات + التأمين الطبي
 * مرتبة حسب الأولوية وتاريخ الانتهاء، مع فلاتر وترقيم صفحات.
 */
export const renewalPriority = asyncHandler(async (req: Request, res: Response) => {
  const { search, kind, companyId, priority, days, fromDate, toDate, limit, page, pageSize } = req.query;
  const result = await listRenewals({
    search: search ? String(search) : undefined,
    kind: kind ? String(kind) : undefined,
    companyId: companyId ? Number(companyId) : undefined,
    priority: priority ? String(priority) : undefined,
    days: days ? Number(days) : undefined,
    from: fromDate ? String(fromDate) : undefined,
    to: toDate ? String(toDate) : undefined,
    page: page ? Number(page) : 1,
    pageSize: pageSize ? Number(pageSize) : limit ? Number(limit) : 50,
  });
  res.json({ success: true, ...result });
});

export const recentNotifications = asyncHandler(async (req: Request, res: Response) => {
  const limit = Number(req.query.limit || 5);
  const notifications = await prisma.notification.findMany({
    orderBy: { createdAt: "desc" },
    take: limit,
  });
  res.json({ success: true, data: notifications });
});

async function getThresholds() {
  const settings = await prisma.setting.findMany({
    where: { key: { in: ["priority_critical_days", "priority_high_days", "priority_medium_days"] } },
  });
  const get = (k: string, d: number) => Number(settings.find((s) => s.key === k)?.value ?? d);
  return { critical: get("priority_critical_days", 7), high: get("priority_high_days", 30), medium: get("priority_medium_days", 60) };
}