import { ConflictException, ForbiddenException, NotFoundException } from '@nestjs/common';
import { AccountStatus, Prisma, UserRole } from '@prisma/client';
import { PrismaService } from '../database/prisma.service';
import { calculateProfileCompletion } from './profile-completion';
import { RequestUser } from './request-user';

export async function assertActiveGuardForEstate(
  prisma: PrismaService,
  guardId: string,
  estateId: string,
  user: RequestUser,
  deviceId?: string
) {
  const guard = await prisma.guard.findFirst({
    where: {
      id: guardId,
      estateId,
      status: AccountStatus.ACTIVE
    }
  });

  if (!guard) {
    throw new NotFoundException('Active guard was not found in this estate');
  }

  if (user.role === UserRole.GUARD && guard.userId !== user.id) {
    throw new ForbiddenException('Guard identity does not match the authenticated user');
  }

  const completion = calculateProfileCompletion(UserRole.GUARD, guard);
  if (!completion.complete) {
    throw new ForbiddenException({
      message: 'Guard profile must be complete before scanning visitors',
      profileCompletion: completion.completion,
      missing: completion.missing
    });
  }

  if (!guard.assignedGateId) {
    throw new ForbiddenException('Guard must be assigned to a gate before scanning visitors');
  }

  const normalizedDeviceId = deviceId?.trim();
  if (!normalizedDeviceId) {
    return guard;
  }

  if (guard.deviceId && guard.deviceId !== normalizedDeviceId) {
    throw new ForbiddenException('Guard account is assigned to a different device');
  }

  if (!guard.deviceId) {
    try {
      return await prisma.guard.update({
        where: { id: guard.id },
        data: { deviceId: normalizedDeviceId }
      });
    } catch (error) {
      if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2002') {
        throw new ConflictException('This device is already assigned to another guard');
      }
      throw error;
    }
  }

  return guard;
}
