import { prisma } from '../../config/database';
import { AppError } from '../../middleware/error-handler';
import { logger } from '../../utils/logger';
import type { UpsertNeedsInput } from './participant-needs.schemas';

export const participantNeedsService = {

  async upsert(data: UpsertNeedsInput, userId?: string, contactId?: string) {
    if (!userId && !contactId) {
      throw new AppError(400, 'Either userId or contactId is required', 'MISSING_IDENTIFIER');
    }

    const where = userId
      ? { userId }
      : { contactId: contactId! };

    const existing = await prisma.participantNeeds.findUnique({ where });

    if (existing) {
      return prisma.participantNeeds.update({
        where: { id: existing.id },
        data,
      });
    }

    return prisma.participantNeeds.create({
      data: {
        ...data,
        ...(userId ? { userId } : { contactId }),
      },
    });
  },

  async findByUserId(userId: string) {
    return prisma.participantNeeds.findUnique({ where: { userId } });
  },

  async findByContactId(contactId: string) {
    return prisma.participantNeeds.findUnique({ where: { contactId } });
  },

  async aggregateForVoters(userIds: string[], contactIds: string[]) {
    const records = await prisma.participantNeeds.findMany({
      where: {
        OR: [
          ...(userIds.length > 0 ? [{ userId: { in: userIds } }] : []),
          ...(contactIds.length > 0 ? [{ contactId: { in: contactIds } }] : []),
        ],
      },
    });

    const summary = {
      total: records.length,
      accessibility: {
        wheelchair: 0,
        groundFloor: 0,
        hearingLoop: 0,
        signLanguage: 0,
        other: 0,
      },
      dietary: {
        vegan: 0,
        vegetarian: 0,
        glutenFree: 0,
        halal: 0,
        kosher: 0,
        nutAllergy: 0,
        other: 0,
      },
      childcare: 0,
      transportation: 0,
      translation: 0,
      languages: {} as Record<string, number>,
    };

    for (const r of records) {
      if (r.needsWheelchair) summary.accessibility.wheelchair++;
      if (r.needsGroundFloor) summary.accessibility.groundFloor++;
      if (r.needsHearingLoop) summary.accessibility.hearingLoop++;
      if (r.needsSignLanguage) summary.accessibility.signLanguage++;
      if (r.otherAccessibility) summary.accessibility.other++;

      if (r.isVegan) summary.dietary.vegan++;
      if (r.isVegetarian) summary.dietary.vegetarian++;
      if (r.isGlutenFree) summary.dietary.glutenFree++;
      if (r.isHalal) summary.dietary.halal++;
      if (r.isKosher) summary.dietary.kosher++;
      if (r.hasNutAllergy) summary.dietary.nutAllergy++;
      if (r.otherDietary) summary.dietary.other++;

      if (r.needsChildcare) summary.childcare++;
      if (r.needsTransportation) summary.transportation++;
      if (r.needsTranslation) summary.translation++;

      if (r.translationLanguage) {
        summary.languages[r.translationLanguage] = (summary.languages[r.translationLanguage] || 0) + 1;
      }
    }

    return summary;
  },

  async deleteById(id: string) {
    const existing = await prisma.participantNeeds.findUnique({ where: { id } });
    if (!existing) {
      throw new AppError(404, 'Participant needs record not found', 'NOT_FOUND');
    }
    await prisma.participantNeeds.delete({ where: { id } });
  },

  async purgeExpired() {
    const cutoff = new Date();
    cutoff.setDate(cutoff.getDate() - 7);

    const result = await prisma.participantNeeds.deleteMany({
      where: {
        updatedAt: { lt: cutoff },
        userId: null,
        contactId: null,
      },
    });

    if (result.count > 0) {
      logger.info(`Purged ${result.count} orphaned participant needs records older than 7 days`);
    }

    return { purged: result.count };
  },
};
