import { Prisma } from '@prisma/client';
import { prisma } from '../db/prisma';

export interface StatutCount {
  statut: string;
  count: number;
}

export type ActiviteResponsable = Prisma.HistoriqueGetPayload<{
  include: {
    utilisateur: true;
    materiel: true;
    emprunt: true;
  };
}>;

export type EmpruntResponsable = Prisma.EmpruntGetPayload<{
  include: {
    utilisateur: true;
    materiel: { include: { categorie: true } };
  };
}>;

export type MaterielResponsable = Prisma.MaterielGetPayload<{
  include: {
    categorie: true;
    accessoires: { include: { accessoire: true } };
  };
}>;

export type AnomalieResponsable = Prisma.AnomalieGetPayload<{
  include: {
    emprunt: true;
    etudiant: true;
    materiel: { include: { categorie: true } };
    traitePar: true;
  };
}>;

export type NotificationResponsable = Prisma.NotificationGetPayload<{
  include: {
    anomalie: {
      include: {
        emprunt: true;
        materiel: true;
      };
    };
  };
}>;

export type HistoriqueResponsable = Prisma.HistoriqueGetPayload<{
  include: {
    utilisateur: true;
    materiel: true;
    emprunt: true;
    sallePret: true;
    posteEmprunt: true;
  };
}>;

export interface EmpruntResponsableFiltres {
  statut?: string;
}

export interface MaterielResponsableFiltres {
  statut?: string;
  categorieId?: number;
  recherche?: string;
}

export interface AnomalieResponsableFiltres {
  statut?: string;
  type?: string;
}

export interface NotificationResponsableFiltres {
  lu?: boolean;
}

export interface HistoriqueResponsableFiltres {
  action?: string;
  utilisateurId?: number;
  materielId?: number;
  empruntId?: number;
  dateDebut?: Date;
  dateFin?: Date;
}

function mapStatutCounts(rows: Array<{ statut: string; _count: { _all: number } }>): StatutCount[] {
  return rows.map((row) => ({ statut: row.statut, count: row._count._all }));
}

export async function countMaterielsParStatut(campusId: number): Promise<StatutCount[]> {
  const rows = await prisma.materiel.groupBy({
    by: ['statut'],
    where: { campusId, actif: true },
    _count: { _all: true },
  });

  return mapStatutCounts(rows);
}

export async function countEmpruntsParStatut(campusId: number): Promise<StatutCount[]> {
  const rows = await prisma.emprunt.groupBy({
    by: ['statut'],
    where: { campusId },
    _count: { _all: true },
  });

  return mapStatutCounts(rows);
}

export async function countAnomaliesParStatut(campusId: number): Promise<StatutCount[]> {
  const rows = await prisma.anomalie.groupBy({
    by: ['statut'],
    where: { emprunt: { campusId } },
    _count: { _all: true },
  });

  return mapStatutCounts(rows);
}

export function countNotificationsNonLues(utilisateurId: number): Promise<number> {
  return prisma.notification.count({
    where: { utilisateurId, lu: false },
  });
}

export function findActiviteRecente(
  campusId: number,
  limite: number,
): Promise<ActiviteResponsable[]> {
  return prisma.historique.findMany({
    where: { campusId },
    include: {
      utilisateur: true,
      materiel: true,
      emprunt: true,
    },
    orderBy: { dateAction: 'desc' },
    take: limite,
  });
}

export function findEmpruntsResponsable(
  campusId: number,
  filtres: EmpruntResponsableFiltres,
): Promise<EmpruntResponsable[]> {
  return prisma.emprunt.findMany({
    where: {
      campusId,
      ...(filtres.statut ? { statut: filtres.statut } : {}),
    },
    include: {
      utilisateur: true,
      materiel: { include: { categorie: true } },
    },
    orderBy: { dateEmprunt: 'desc' },
  });
}

export function findMaterielsResponsable(
  campusId: number,
  filtres: MaterielResponsableFiltres,
): Promise<MaterielResponsable[]> {
  return prisma.materiel.findMany({
    where: {
      campusId,
      actif: true,
      ...(filtres.statut ? { statut: filtres.statut } : {}),
      ...(filtres.categorieId !== undefined ? { categorieId: filtres.categorieId } : {}),
      ...(filtres.recherche
        ? {
            OR: [
              { nom: { contains: filtres.recherche } },
              { marque: { contains: filtres.recherche } },
              { modele: { contains: filtres.recherche } },
              { reference: { contains: filtres.recherche } },
            ],
          }
        : {}),
    },
    include: {
      categorie: true,
      accessoires: { include: { accessoire: true } },
    },
    orderBy: { nom: 'asc' },
  });
}

export function findAnomaliesResponsable(
  campusId: number,
  filtres: AnomalieResponsableFiltres,
): Promise<AnomalieResponsable[]> {
  return prisma.anomalie.findMany({
    where: {
      emprunt: { campusId },
      ...(filtres.statut ? { statut: filtres.statut } : {}),
      ...(filtres.type ? { type: filtres.type } : {}),
    },
    include: {
      emprunt: true,
      etudiant: true,
      materiel: { include: { categorie: true } },
      traitePar: true,
    },
    orderBy: { dateDetection: 'desc' },
  });
}

export function findNotificationsResponsable(
  utilisateurId: number,
  filtres: NotificationResponsableFiltres,
): Promise<NotificationResponsable[]> {
  return prisma.notification.findMany({
    where: {
      utilisateurId,
      ...(filtres.lu !== undefined ? { lu: filtres.lu } : {}),
    },
    include: {
      anomalie: {
        include: {
          emprunt: true,
          materiel: true,
        },
      },
    },
    orderBy: { dateCreation: 'desc' },
  });
}

export function marquerNotificationLue(
  utilisateurId: number,
  notificationId: number,
): Promise<NotificationResponsable> {
  return prisma.notification.update({
    where: {
      id: notificationId,
      utilisateurId,
    },
    data: { lu: true },
    include: {
      anomalie: {
        include: {
          emprunt: true,
          materiel: true,
        },
      },
    },
  });
}

export async function marquerNotificationsResponsableLues(utilisateurId: number): Promise<number> {
  const result = await prisma.notification.updateMany({
    where: { utilisateurId, lu: false },
    data: { lu: true },
  });

  return result.count;
}

export function findHistoriqueResponsable(
  campusId: number,
  filtres: HistoriqueResponsableFiltres,
): Promise<HistoriqueResponsable[]> {
  return prisma.historique.findMany({
    where: {
      campusId,
      ...(filtres.action ? { action: filtres.action } : {}),
      ...(filtres.utilisateurId !== undefined ? { utilisateurId: filtres.utilisateurId } : {}),
      ...(filtres.materielId !== undefined ? { materielId: filtres.materielId } : {}),
      ...(filtres.empruntId !== undefined ? { empruntId: filtres.empruntId } : {}),
      ...(filtres.dateDebut || filtres.dateFin
        ? {
            dateAction: {
              ...(filtres.dateDebut ? { gte: filtres.dateDebut } : {}),
              ...(filtres.dateFin ? { lte: filtres.dateFin } : {}),
            },
          }
        : {}),
    },
    include: {
      utilisateur: true,
      materiel: true,
      emprunt: true,
      sallePret: true,
      posteEmprunt: true,
    },
    orderBy: { dateAction: 'desc' },
  });
}
