import { Request, Response } from 'express';
import { AppError } from '../errors/app-error';
import {
  getDashboardResponsable,
  listerAnomaliesResponsable,
  listerHistoriqueResponsable,
  listerNotificationsResponsable,
  listerMaterielsResponsable,
  listerEmpruntsResponsable,
  marquerNotificationResponsableLue,
  marquerToutesNotificationsResponsableLues,
  parseCategorieId,
  parseLu,
  parseNotificationId,
  parseDateQuery,
  parsePositiveIntQuery,
  parseStatutAnomalie,
  parseStatutMateriel,
  parseStatutEmprunt,
} from '../services/responsable.service';
import {
  toAnomalieResponsableResponse,
  toDashboardResponsableResponse,
  toEmpruntResponsableResponse,
  toHistoriqueResponsableResponse,
  toMaterielResponsableResponse,
  toNotificationResponsableResponse,
} from '../dtos/responsable.dto';

function getHistoriqueFiltres(req: Request) {
  const action = typeof req.query.action === 'string' ? req.query.action : undefined;
  return {
    action,
    utilisateurId: parsePositiveIntQuery(req.query.utilisateurId, 'utilisateurId'),
    materielId: parsePositiveIntQuery(req.query.materielId, 'materielId'),
    empruntId: parsePositiveIntQuery(req.query.empruntId, 'empruntId'),
    dateDebut: parseDateQuery(req.query.dateDebut, 'dateDebut'),
    dateFin: parseDateQuery(req.query.dateFin, 'dateFin'),
  };
}

function escapeCsv(value: string | number | Date | null): string {
  if (value === null) {
    return '';
  }
  const raw = value instanceof Date ? value.toISOString() : String(value);
  return `"${raw.replace(/"/g, '""')}"`;
}

export async function getDashboard(req: Request, res: Response): Promise<void> {
  const user = req.user;
  if (!user) {
    throw new AppError(401, 'Authentification requise');
  }

  const dashboard = await getDashboardResponsable(user.id, user.roleCode, user.campusId);
  res.json({ data: toDashboardResponsableResponse(dashboard) });
}

export async function getEmprunts(req: Request, res: Response): Promise<void> {
  const user = req.user;
  if (!user) {
    throw new AppError(401, 'Authentification requise');
  }

  const statut = parseStatutEmprunt(req.query.statut);
  const emprunts = await listerEmpruntsResponsable(user.roleCode, user.campusId, { statut });
  res.json({ data: emprunts.map(toEmpruntResponsableResponse) });
}

export async function getMateriels(req: Request, res: Response): Promise<void> {
  const user = req.user;
  if (!user) {
    throw new AppError(401, 'Authentification requise');
  }

  const statut = parseStatutMateriel(req.query.statut);
  const categorieId = parseCategorieId(req.query.categorieId);
  const recherche = typeof req.query.q === 'string' ? req.query.q : undefined;

  const materiels = await listerMaterielsResponsable(user.roleCode, user.campusId, {
    statut,
    categorieId,
    recherche,
  });
  res.json({ data: materiels.map(toMaterielResponsableResponse) });
}

export async function getAnomalies(req: Request, res: Response): Promise<void> {
  const user = req.user;
  if (!user) {
    throw new AppError(401, 'Authentification requise');
  }

  const statut = parseStatutAnomalie(req.query.statut);
  const type = typeof req.query.type === 'string' ? req.query.type : undefined;

  const anomalies = await listerAnomaliesResponsable(user.roleCode, user.campusId, {
    statut,
    type,
  });
  res.json({ data: anomalies.map(toAnomalieResponsableResponse) });
}

export async function getNotifications(req: Request, res: Response): Promise<void> {
  const user = req.user;
  if (!user) {
    throw new AppError(401, 'Authentification requise');
  }

  const lu = parseLu(req.query.lu);
  const notifications = await listerNotificationsResponsable(user.id, user.roleCode, { lu });
  res.json({ data: notifications.map(toNotificationResponsableResponse) });
}

export async function patchNotificationLue(req: Request, res: Response): Promise<void> {
  const user = req.user;
  if (!user) {
    throw new AppError(401, 'Authentification requise');
  }

  const notificationId = parseNotificationId(req.params.id);
  const notification = await marquerNotificationResponsableLue(
    user.id,
    user.roleCode,
    notificationId,
  );
  res.json({ data: toNotificationResponsableResponse(notification) });
}

export async function patchNotificationsLues(req: Request, res: Response): Promise<void> {
  const user = req.user;
  if (!user) {
    throw new AppError(401, 'Authentification requise');
  }

  const count = await marquerToutesNotificationsResponsableLues(user.id, user.roleCode);
  res.json({ data: { count } });
}

export async function getHistorique(req: Request, res: Response): Promise<void> {
  const user = req.user;
  if (!user) {
    throw new AppError(401, 'Authentification requise');
  }

  const historique = await listerHistoriqueResponsable(
    user.roleCode,
    user.campusId,
    getHistoriqueFiltres(req),
  );
  res.json({ data: historique.map(toHistoriqueResponsableResponse) });
}

export async function getHistoriqueCsv(req: Request, res: Response): Promise<void> {
  const user = req.user;
  if (!user) {
    throw new AppError(401, 'Authentification requise');
  }

  const historique = await listerHistoriqueResponsable(
    user.roleCode,
    user.campusId,
    getHistoriqueFiltres(req),
  );
  const lignes = [
    ['id', 'dateAction', 'action', 'description', 'utilisateur', 'email', 'materiel', 'empruntId']
      .map(escapeCsv)
      .join(','),
    ...historique.map((item) =>
      [
        item.id,
        item.dateAction,
        item.action,
        item.description,
        `${item.utilisateur.prenom} ${item.utilisateur.nom}`,
        item.utilisateur.email,
        item.materiel ? `${item.materiel.nom} (${item.materiel.reference})` : null,
        item.empruntId,
      ]
        .map(escapeCsv)
        .join(','),
    ),
  ];

  res.setHeader('Content-Type', 'text/csv; charset=utf-8');
  res.setHeader('Content-Disposition', 'attachment; filename="historique-responsable.csv"');
  res.send(lignes.join('\n'));
}
