import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
import { PrismaService } from '../../common/prisma.service';
import { DeleteOperationException } from '../../common/exceptions/delete-operation.exception';
import { AuditService } from '../../common/audit.service';

@Injectable()
export class SeatClassesService {
  constructor(private prisma: PrismaService, private auditService: AuditService) {}

  listSeatClasses() {
    return this.prisma.seatClass.findMany({
      where: { isActive: true },
      orderBy: { createdAt: 'asc' },
    });
  }

  async getSeatClass(id: string) {
    const sc = await this.prisma.seatClass.findUnique({ where: { id } });
    if (!sc) throw new NotFoundException('SeatClass not found');
    if (!sc.isActive) throw new NotFoundException('SeatClass is not active');
    return sc;
  }

  async updateSeatClass(id: string, dto: any) {
    const sc = await this.prisma.seatClass.findUnique({ where: { id } });
    if (!sc) throw new NotFoundException('SeatClass not found');
    const { basePrice, ...rest } = dto;
    const data = {
      ...rest,
      ...(basePrice !== undefined && { baseFareMinor: basePrice }),
    };
    const updated = await this.prisma.seatClass.update({ where: { id }, data });
    await this.auditService.log({ action: 'UPDATE', entityType: 'SeatClass', entityId: id, newData: { name: updated.name } });
    return updated;
  }

  async createSeatClass(dto: any) {
    try {
      const { basePrice, ...rest } = dto;
      const data = {
        ...rest,
        ...(basePrice !== undefined && { baseFareMinor: basePrice }),
      };
      const sc = await this.prisma.seatClass.create({ data });
      await this.auditService.log({ action: 'CREATE', entityType: 'SeatClass', entityId: sc.id, newData: { name: sc.name } });
      return sc;
    } catch (e: any) {
      if (e.code === 'P2002') throw new ConflictException(`Seat class "${dto.name}" already exists`);
      throw e;
    }
  }

  async deleteSeatClass(id: string, cascade = false) {
    const sc = await this.prisma.seatClass.findUnique({
      where: { id },
      include: {
        _count: { select: { fareRules: true, routeFareRules: true, segmentFares: true } },
      },
    });
    if (!sc) throw new NotFoundException('SeatClass not found');

    const totalFareRules =
      (sc as any)._count.fareRules +
      (sc as any)._count.routeFareRules +
      (sc as any)._count.segmentFares;

    if (totalFareRules > 0 && !cascade)
      throw new DeleteOperationException('Seat Class', sc.name, [
        { entityName: 'fare rule', count: totalFareRules, action: 'delete' },
      ]);

    if (cascade) {
      await this.prisma.fareRule.deleteMany({ where: { seatClassId: id } });
      await this.prisma.routeFareRule.deleteMany({ where: { seatClassId: id } });
      await this.prisma.segmentFareRule.deleteMany({ where: { seatClassId: id } });
    }

    const deleted = await this.prisma.seatClass.delete({ where: { id } });
    await this.auditService.log({ action: 'DELETE', entityType: 'SeatClass', entityId: id, oldData: { name: sc.name } });
    return deleted;
  }
}
