import { Repository, FindOptionsWhere, ILike, In, LessThanOrEqual, MoreThan, Between } from 'typeorm';
import { Operador, TipoLicencia, EstadoOperador } from '../entities/operador.entity';
import { DocumentoFlota, TipoDocumento, TipoEntidadDocumento } from '../entities/documento-flota.entity';
import { Asignacion } from '../entities/asignacion.entity';

// ============================================================================
// INTERFACES
// ============================================================================

export interface OperadorFilters {
  search?: string;
  estado?: EstadoOperador;
  estados?: EstadoOperador[];
  tipoLicencia?: TipoLicencia;
  sucursalId?: string;
  conUnidadAsignada?: boolean;
  activo?: boolean;
  limit?: number;
  offset?: number;
}

export interface CreateOperadorDto {
  numeroEmpleado: string;
  nombre: string;
  apellidoPaterno: string;
  apellidoMaterno?: string;
  curp?: string;
  rfc?: string;
  nss?: string;
  telefono?: string;
  telefonoEmergencia?: string;
  email?: string;
  direccion?: string;
  codigoPostal?: string;
  ciudad?: string;
  estadoResidencia?: string;
  fechaNacimiento?: Date;
  lugarNacimiento?: string;
  nacionalidad?: string;
  tipoLicencia?: TipoLicencia;
  numeroLicencia?: string;
  licenciaVigencia?: Date;
  licenciaEstadoExpedicion?: string;
  certificadoFisicoVigencia?: Date;
  antidopingVigencia?: Date;
  capacitacionMaterialesPeligrosos?: boolean;
  capacitacionMpVigencia?: Date;
  banco?: string;
  cuentaBancaria?: string;
  clabe?: string;
  salarioBase?: number;
  tipoPago?: string;
  fechaIngreso?: Date;
  sucursalId?: string;
}

export interface UpdateOperadorDto extends Partial<CreateOperadorDto> {
  estado?: EstadoOperador;
}

export interface AddCertificacionDto {
  tipo: TipoDocumento;
  nombre: string;
  numeroDocumento?: string;
  descripcion?: string;
  fechaEmision?: Date;
  fechaVencimiento?: Date;
  diasAlertaVencimiento?: number;
  archivoUrl?: string;
  archivoNombre?: string;
  archivoTipo?: string;
  archivoTamanoBytes?: number;
}

export interface AddDocumentoDto {
  tipo: TipoDocumento;
  nombre: string;
  numeroDocumento?: string;
  descripcion?: string;
  fechaEmision?: Date;
  fechaVencimiento?: Date;
  diasAlertaVencimiento?: number;
  archivoUrl?: string;
  archivoNombre?: string;
  archivoTipo?: string;
  archivoTamanoBytes?: number;
}

export interface DocumentoExpirando {
  documento: DocumentoFlota;
  operador: Operador;
  diasParaVencer: number;
}

export interface HorasServicio {
  operadorId: string;
  nombreCompleto: string;
  horasTrabajadasHoy: number;
  horasTrabajadasSemana: number;
  horasDescansadas: number;
  ultimoDescanso?: Date;
  proximoDescansoObligatorio?: Date;
  enCumplimiento: boolean;
  alertas: string[];
}

export interface PerformanceMetrics {
  operadorId: string;
  nombreCompleto: string;
  periodo: {
    inicio: Date;
    fin: Date;
  };
  totalViajes: number;
  totalKm: number;
  totalEntregasATiempo: number;
  porcentajeEntregasATiempo: number;
  incidentes: number;
  calificacionPromedio: number;
  combustibleEficiencia?: number;
  horasConduccion: number;
  diasTrabajados: number;
}

export interface OperadorStatistics {
  total: number;
  activos: number;
  disponibles: number;
  enViaje: number;
  enDescanso: number;
  vacaciones: number;
  incapacidad: number;
  suspendidos: number;
  licenciasPorVencer: number;
  certificadosPorVencer: number;
  sinUnidadAsignada: number;
}

// ============================================================================
// SERVICE
// ============================================================================

export class OperadorService {
  constructor(
    private readonly operadorRepository: Repository<Operador>,
    private readonly documentoRepository: Repository<DocumentoFlota>,
    private readonly asignacionRepository: Repository<Asignacion>
  ) {}

  // --------------------------------------------------------------------------
  // CRUD OPERATIONS
  // --------------------------------------------------------------------------

  /**
   * Crear perfil de operador/conductor
   */
  async create(tenantId: string, dto: CreateOperadorDto, createdById: string): Promise<Operador> {
    // Validar numero de empleado unico
    const existingNumero = await this.operadorRepository.findOne({
      where: { tenantId, numeroEmpleado: dto.numeroEmpleado },
    });
    if (existingNumero) {
      throw new Error(`Ya existe un operador con el numero de empleado ${dto.numeroEmpleado}`);
    }

    // Validar CURP unico si se proporciona
    if (dto.curp) {
      const existingCurp = await this.operadorRepository.findOne({
        where: { tenantId, curp: dto.curp },
      });
      if (existingCurp) {
        throw new Error(`Ya existe un operador con el CURP ${dto.curp}`);
      }
    }

    // Validar licencia unica si se proporciona
    if (dto.numeroLicencia) {
      const existingLicencia = await this.operadorRepository.findOne({
        where: { tenantId, numeroLicencia: dto.numeroLicencia },
      });
      if (existingLicencia) {
        throw new Error(`Ya existe un operador con el numero de licencia ${dto.numeroLicencia}`);
      }
    }

    const operador = this.operadorRepository.create({
      ...dto,
      tenantId,
      estado: EstadoOperador.ACTIVO,
      activo: true,
      createdById,
    });

    return this.operadorRepository.save(operador);
  }

  /**
   * Buscar operador por ID
   */
  async findById(tenantId: string, id: string): Promise<Operador | null> {
    return this.operadorRepository.findOne({
      where: { tenantId, id, activo: true },
      relations: ['unidadAsignada'],
    });
  }

  /**
   * Buscar operador por ID o lanzar error
   */
  async findByIdOrFail(tenantId: string, id: string): Promise<Operador> {
    const operador = await this.findById(tenantId, id);
    if (!operador) {
      throw new Error(`Operador con ID ${id} no encontrado`);
    }
    return operador;
  }

  /**
   * Listar operadores con filtros
   */
  async findAll(
    tenantId: string,
    filters: OperadorFilters = {}
  ): Promise<{ data: Operador[]; total: number }> {
    const {
      search,
      estado,
      estados,
      tipoLicencia,
      sucursalId,
      conUnidadAsignada,
      activo = true,
      limit = 50,
      offset = 0,
    } = filters;

    const qb = this.operadorRepository
      .createQueryBuilder('o')
      .leftJoinAndSelect('o.unidadAsignada', 'unidad')
      .where('o.tenant_id = :tenantId', { tenantId });

    if (activo !== undefined) {
      qb.andWhere('o.activo = :activo', { activo });
    }

    if (estado) {
      qb.andWhere('o.estado = :estado', { estado });
    }

    if (estados && estados.length > 0) {
      qb.andWhere('o.estado IN (:...estados)', { estados });
    }

    if (tipoLicencia) {
      qb.andWhere('o.tipo_licencia = :tipoLicencia', { tipoLicencia });
    }

    if (sucursalId) {
      qb.andWhere('o.sucursal_id = :sucursalId', { sucursalId });
    }

    if (conUnidadAsignada !== undefined) {
      if (conUnidadAsignada) {
        qb.andWhere('o.unidad_asignada_id IS NOT NULL');
      } else {
        qb.andWhere('o.unidad_asignada_id IS NULL');
      }
    }

    if (search) {
      qb.andWhere(
        '(o.numero_empleado ILIKE :search OR o.nombre ILIKE :search OR ' +
        'o.apellido_paterno ILIKE :search OR o.apellido_materno ILIKE :search OR ' +
        'o.numero_licencia ILIKE :search)',
        { search: `%${search}%` }
      );
    }

    const total = await qb.getCount();

    qb.orderBy('o.apellido_paterno', 'ASC')
      .addOrderBy('o.nombre', 'ASC')
      .offset(offset)
      .limit(limit);

    const data = await qb.getMany();

    return { data, total };
  }

  /**
   * Obtener operadores disponibles
   */
  async findAvailable(tenantId: string): Promise<Operador[]> {
    return this.operadorRepository.find({
      where: {
        tenantId,
        estado: In([EstadoOperador.DISPONIBLE, EstadoOperador.ACTIVO]),
        activo: true,
      },
      order: { apellidoPaterno: 'ASC', nombre: 'ASC' },
    });
  }

  /**
   * Filtrar operadores por estado
   */
  async findByStatus(tenantId: string, estado: EstadoOperador): Promise<Operador[]> {
    return this.operadorRepository.find({
      where: { tenantId, estado, activo: true },
      order: { apellidoPaterno: 'ASC', nombre: 'ASC' },
    });
  }

  /**
   * Actualizar operador
   */
  async update(
    tenantId: string,
    id: string,
    dto: UpdateOperadorDto,
    updatedById: string
  ): Promise<Operador> {
    const operador = await this.findByIdOrFail(tenantId, id);

    // Validar numero de empleado si cambia
    if (dto.numeroEmpleado && dto.numeroEmpleado !== operador.numeroEmpleado) {
      const existing = await this.operadorRepository.findOne({
        where: { tenantId, numeroEmpleado: dto.numeroEmpleado },
      });
      if (existing) {
        throw new Error(`Ya existe un operador con el numero de empleado ${dto.numeroEmpleado}`);
      }
    }

    // Validar CURP si cambia
    if (dto.curp && dto.curp !== operador.curp) {
      const existing = await this.operadorRepository.findOne({
        where: { tenantId, curp: dto.curp },
      });
      if (existing && existing.id !== id) {
        throw new Error(`Ya existe un operador con el CURP ${dto.curp}`);
      }
    }

    // Validar licencia si cambia
    if (dto.numeroLicencia && dto.numeroLicencia !== operador.numeroLicencia) {
      const existing = await this.operadorRepository.findOne({
        where: { tenantId, numeroLicencia: dto.numeroLicencia },
      });
      if (existing && existing.id !== id) {
        throw new Error(`Ya existe un operador con el numero de licencia ${dto.numeroLicencia}`);
      }
    }

    Object.assign(operador, {
      ...dto,
      updatedById,
    });

    return this.operadorRepository.save(operador);
  }

  /**
   * Cambiar estado del operador
   */
  async updateStatus(
    tenantId: string,
    id: string,
    estado: EstadoOperador,
    updatedById: string
  ): Promise<Operador> {
    const operador = await this.findByIdOrFail(tenantId, id);

    // Validaciones de transicion de estado
    if (operador.estado === EstadoOperador.BAJA) {
      throw new Error('No se puede cambiar el estado de un operador dado de baja');
    }

    if (estado === EstadoOperador.EN_VIAJE && !operador.unidadAsignadaId) {
      throw new Error('No se puede poner en viaje a un operador sin unidad asignada');
    }

    // Validar documentos vigentes para estados operativos
    if (estado === EstadoOperador.EN_VIAJE || estado === EstadoOperador.DISPONIBLE) {
      const hoy = new Date();
      if (operador.licenciaVigencia && operador.licenciaVigencia < hoy) {
        throw new Error('El operador tiene la licencia vencida');
      }
      if (operador.certificadoFisicoVigencia && operador.certificadoFisicoVigencia < hoy) {
        throw new Error('El operador tiene el certificado fisico vencido');
      }
      if (operador.antidopingVigencia && operador.antidopingVigencia < hoy) {
        throw new Error('El operador tiene el antidoping vencido');
      }
    }

    operador.estado = estado;
    operador.updatedById = updatedById;

    return this.operadorRepository.save(operador);
  }

  // --------------------------------------------------------------------------
  // DOCUMENTS & CERTIFICATIONS
  // --------------------------------------------------------------------------

  /**
   * Agregar certificacion al operador
   */
  async addCertificacion(
    tenantId: string,
    operadorId: string,
    dto: AddCertificacionDto,
    createdById: string
  ): Promise<DocumentoFlota> {
    // Verificar que el operador existe
    await this.findByIdOrFail(tenantId, operadorId);

    const documento = this.documentoRepository.create({
      tenantId,
      entidadTipo: TipoEntidadDocumento.OPERADOR,
      entidadId: operadorId,
      tipoDocumento: dto.tipo,
      nombre: dto.nombre,
      numeroDocumento: dto.numeroDocumento,
      descripcion: dto.descripcion,
      fechaEmision: dto.fechaEmision,
      fechaVencimiento: dto.fechaVencimiento,
      diasAlertaVencimiento: dto.diasAlertaVencimiento || 30,
      archivoUrl: dto.archivoUrl,
      archivoNombre: dto.archivoNombre,
      archivoTipo: dto.archivoTipo,
      archivoTamanoBytes: dto.archivoTamanoBytes,
      activo: true,
      createdById,
    });

    return this.documentoRepository.save(documento);
  }

  /**
   * Agregar documento al operador
   */
  async addDocumento(
    tenantId: string,
    operadorId: string,
    dto: AddDocumentoDto,
    createdById: string
  ): Promise<DocumentoFlota> {
    // Verificar que el operador existe
    await this.findByIdOrFail(tenantId, operadorId);

    const documento = this.documentoRepository.create({
      tenantId,
      entidadTipo: TipoEntidadDocumento.OPERADOR,
      entidadId: operadorId,
      tipoDocumento: dto.tipo,
      nombre: dto.nombre,
      numeroDocumento: dto.numeroDocumento,
      descripcion: dto.descripcion,
      fechaEmision: dto.fechaEmision,
      fechaVencimiento: dto.fechaVencimiento,
      diasAlertaVencimiento: dto.diasAlertaVencimiento || 30,
      archivoUrl: dto.archivoUrl,
      archivoNombre: dto.archivoNombre,
      archivoTipo: dto.archivoTipo,
      archivoTamanoBytes: dto.archivoTamanoBytes,
      activo: true,
      createdById,
    });

    return this.documentoRepository.save(documento);
  }

  /**
   * Obtener documentos de un operador
   */
  async getDocumentos(tenantId: string, operadorId: string): Promise<DocumentoFlota[]> {
    return this.documentoRepository.find({
      where: {
        tenantId,
        entidadTipo: TipoEntidadDocumento.OPERADOR,
        entidadId: operadorId,
        activo: true,
      },
      order: { fechaVencimiento: 'ASC' },
    });
  }

  /**
   * Obtener documentos por vencer de todos los operadores
   */
  async getDocumentsExpiring(tenantId: string, dias: number = 30): Promise<DocumentoExpirando[]> {
    const hoy = new Date();
    const fechaLimite = new Date();
    fechaLimite.setDate(fechaLimite.getDate() + dias);

    const documentos = await this.documentoRepository.find({
      where: {
        tenantId,
        entidadTipo: TipoEntidadDocumento.OPERADOR,
        fechaVencimiento: Between(hoy, fechaLimite),
        activo: true,
      },
      order: { fechaVencimiento: 'ASC' },
    });

    const result: DocumentoExpirando[] = [];

    for (const doc of documentos) {
      const operador = await this.operadorRepository.findOne({
        where: { id: doc.entidadId, tenantId },
      });

      if (operador) {
        const diasParaVencer = Math.ceil(
          (doc.fechaVencimiento.getTime() - hoy.getTime()) / (1000 * 60 * 60 * 24)
        );

        result.push({
          documento: doc,
          operador,
          diasParaVencer,
        });
      }
    }

    return result;
  }

  /**
   * Obtener operadores con licencia por vencer
   */
  async getOperadoresLicenciaPorVencer(tenantId: string, dias: number = 30): Promise<Operador[]> {
    const hoy = new Date();
    const fechaLimite = new Date();
    fechaLimite.setDate(fechaLimite.getDate() + dias);

    return this.operadorRepository
      .createQueryBuilder('o')
      .where('o.tenant_id = :tenantId', { tenantId })
      .andWhere('o.activo = true')
      .andWhere('o.licencia_vigencia BETWEEN :hoy AND :fechaLimite', { hoy, fechaLimite })
      .orderBy('o.licencia_vigencia', 'ASC')
      .getMany();
  }

  // --------------------------------------------------------------------------
  // HOURS OF SERVICE (HOS)
  // --------------------------------------------------------------------------

  /**
   * Obtener horas de servicio del operador (HOS tracking)
   */
  async getHoursOfService(tenantId: string, operadorId: string): Promise<HorasServicio> {
    const operador = await this.findByIdOrFail(tenantId, operadorId);
    const alertas: string[] = [];

    // Obtener asignaciones para calcular horas trabajadas
    const hoy = new Date();
    const inicioSemana = new Date(hoy);
    inicioSemana.setDate(hoy.getDate() - hoy.getDay());
    inicioSemana.setHours(0, 0, 0, 0);

    const inicioHoy = new Date(hoy);
    inicioHoy.setHours(0, 0, 0, 0);

    // Calcular horas trabajadas (simplificado - en produccion se calcularia desde eventos de viaje)
    // Por ahora retornamos valores basados en el estado del operador
    let horasTrabajadasHoy = 0;
    let horasTrabajadasSemana = 0;

    if (operador.estado === EstadoOperador.EN_VIAJE || operador.estado === EstadoOperador.EN_RUTA) {
      // Estimado si esta en viaje
      horasTrabajadasHoy = 8;
      horasTrabajadasSemana = operador.totalViajes * 8; // Aproximado
    }

    // Reglas NOM-087 (simplificadas)
    const HORAS_MAX_DIA = 14;
    const HORAS_MAX_SEMANA = 60;
    const HORAS_DESCANSO_MIN = 10;

    const horasDescansadas = 24 - horasTrabajadasHoy;
    let enCumplimiento = true;

    if (horasTrabajadasHoy >= HORAS_MAX_DIA) {
      alertas.push(`Excede limite de ${HORAS_MAX_DIA} horas diarias`);
      enCumplimiento = false;
    }

    if (horasTrabajadasSemana >= HORAS_MAX_SEMANA) {
      alertas.push(`Excede limite de ${HORAS_MAX_SEMANA} horas semanales`);
      enCumplimiento = false;
    }

    if (horasDescansadas < HORAS_DESCANSO_MIN && operador.estado === EstadoOperador.EN_VIAJE) {
      alertas.push(`Requiere minimo ${HORAS_DESCANSO_MIN} horas de descanso`);
      enCumplimiento = false;
    }

    // Calcular proximo descanso obligatorio
    const proximoDescansoObligatorio = new Date(hoy);
    proximoDescansoObligatorio.setHours(proximoDescansoObligatorio.getHours() + (HORAS_MAX_DIA - horasTrabajadasHoy));

    return {
      operadorId: operador.id,
      nombreCompleto: operador.nombreCompleto,
      horasTrabajadasHoy,
      horasTrabajadasSemana,
      horasDescansadas,
      ultimoDescanso: operador.estado === EstadoOperador.DESCANSO ? hoy : undefined,
      proximoDescansoObligatorio: horasTrabajadasHoy > 0 ? proximoDescansoObligatorio : undefined,
      enCumplimiento,
      alertas,
    };
  }

  // --------------------------------------------------------------------------
  // PERFORMANCE METRICS
  // --------------------------------------------------------------------------

  /**
   * Obtener metricas de desempenio del operador
   */
  async getPerformance(
    tenantId: string,
    operadorId: string,
    dateRange: { inicio: Date; fin: Date }
  ): Promise<PerformanceMetrics> {
    const operador = await this.findByIdOrFail(tenantId, operadorId);

    // En produccion, estos datos vendrian de tablas de viajes, eventos, etc.
    // Por ahora usamos los datos acumulados del operador

    const totalViajes = operador.totalViajes || 0;
    const totalKm = operador.totalKm || 0;
    const incidentes = operador.incidentes || 0;
    const calificacionPromedio = Number(operador.calificacion) || 5.0;

    // Calcular dias en el rango
    const diasEnRango = Math.ceil(
      (dateRange.fin.getTime() - dateRange.inicio.getTime()) / (1000 * 60 * 60 * 24)
    );

    // Estimaciones basadas en datos disponibles
    const totalEntregasATiempo = Math.round(totalViajes * 0.95); // 95% estimado
    const porcentajeEntregasATiempo = totalViajes > 0
      ? (totalEntregasATiempo / totalViajes) * 100
      : 100;

    // Horas de conduccion estimadas (8 horas por viaje promedio)
    const horasConduccion = totalViajes * 8;

    // Dias trabajados estimados
    const diasTrabajados = Math.min(totalViajes, diasEnRango);

    return {
      operadorId: operador.id,
      nombreCompleto: operador.nombreCompleto,
      periodo: dateRange,
      totalViajes,
      totalKm,
      totalEntregasATiempo,
      porcentajeEntregasATiempo,
      incidentes,
      calificacionPromedio,
      combustibleEficiencia: undefined, // Requiere datos de combustible
      horasConduccion,
      diasTrabajados,
    };
  }

  // --------------------------------------------------------------------------
  // STATISTICS
  // --------------------------------------------------------------------------

  /**
   * Obtener estadisticas de operadores
   */
  async getStatistics(tenantId: string): Promise<OperadorStatistics> {
    const hoy = new Date();
    const fechaLimite30 = new Date();
    fechaLimite30.setDate(fechaLimite30.getDate() + 30);

    const total = await this.operadorRepository.count({
      where: { tenantId, activo: true },
    });

    const activos = await this.operadorRepository.count({
      where: { tenantId, estado: EstadoOperador.ACTIVO, activo: true },
    });

    const disponibles = await this.operadorRepository.count({
      where: { tenantId, estado: EstadoOperador.DISPONIBLE, activo: true },
    });

    const enViaje = await this.operadorRepository.count({
      where: { tenantId, estado: In([EstadoOperador.EN_VIAJE, EstadoOperador.EN_RUTA]), activo: true },
    });

    const enDescanso = await this.operadorRepository.count({
      where: { tenantId, estado: EstadoOperador.DESCANSO, activo: true },
    });

    const vacaciones = await this.operadorRepository.count({
      where: { tenantId, estado: EstadoOperador.VACACIONES, activo: true },
    });

    const incapacidad = await this.operadorRepository.count({
      where: { tenantId, estado: EstadoOperador.INCAPACIDAD, activo: true },
    });

    const suspendidos = await this.operadorRepository.count({
      where: { tenantId, estado: EstadoOperador.SUSPENDIDO, activo: true },
    });

    // Licencias por vencer en 30 dias
    const licenciasPorVencer = await this.operadorRepository
      .createQueryBuilder('o')
      .where('o.tenant_id = :tenantId', { tenantId })
      .andWhere('o.activo = true')
      .andWhere('o.licencia_vigencia BETWEEN :hoy AND :fechaLimite', { hoy, fechaLimite: fechaLimite30 })
      .getCount();

    // Certificados por vencer (certificado fisico, antidoping)
    const certificadosPorVencer = await this.operadorRepository
      .createQueryBuilder('o')
      .where('o.tenant_id = :tenantId', { tenantId })
      .andWhere('o.activo = true')
      .andWhere(
        '(o.certificado_fisico_vigencia BETWEEN :hoy AND :fechaLimite OR ' +
        'o.antidoping_vigencia BETWEEN :hoy AND :fechaLimite)',
        { hoy, fechaLimite: fechaLimite30 }
      )
      .getCount();

    // Sin unidad asignada
    const sinUnidadAsignada = await this.operadorRepository.count({
      where: {
        tenantId,
        activo: true,
        estado: In([EstadoOperador.ACTIVO, EstadoOperador.DISPONIBLE]),
      },
    });

    // Restar los que si tienen unidad
    const conUnidad = await this.operadorRepository
      .createQueryBuilder('o')
      .where('o.tenant_id = :tenantId', { tenantId })
      .andWhere('o.activo = true')
      .andWhere('o.estado IN (:...estados)', { estados: [EstadoOperador.ACTIVO, EstadoOperador.DISPONIBLE] })
      .andWhere('o.unidad_asignada_id IS NOT NULL')
      .getCount();

    return {
      total,
      activos,
      disponibles,
      enViaje,
      enDescanso,
      vacaciones,
      incapacidad,
      suspendidos,
      licenciasPorVencer,
      certificadosPorVencer,
      sinUnidadAsignada: sinUnidadAsignada - conUnidad,
    };
  }

  /**
   * Dar de baja operador
   */
  async darDeBaja(
    tenantId: string,
    id: string,
    motivoBaja: string,
    updatedById: string
  ): Promise<Operador> {
    const operador = await this.findByIdOrFail(tenantId, id);

    if (operador.estado === EstadoOperador.EN_VIAJE || operador.estado === EstadoOperador.EN_RUTA) {
      throw new Error('No se puede dar de baja un operador en viaje');
    }

    // Si tiene unidad asignada, desasignar
    if (operador.unidadAsignadaId) {
      const asignacion = await this.asignacionRepository.findOne({
        where: { tenantId, operadorId: id, activa: true },
      });
      if (asignacion) {
        asignacion.activa = false;
        asignacion.fechaFin = new Date();
        await this.asignacionRepository.save(asignacion);
      }
      operador.unidadAsignadaId = undefined as unknown as string;
    }

    operador.estado = EstadoOperador.BAJA;
    operador.activo = false;
    operador.fechaBaja = new Date();
    operador.motivoBaja = motivoBaja;
    operador.updatedById = updatedById;

    return this.operadorRepository.save(operador);
  }

  /**
   * Actualizar metricas del operador despues de un viaje
   */
  async updateMetricsAfterTrip(
    tenantId: string,
    operadorId: string,
    tripData: {
      kmRecorridos: number;
      calificacion?: number;
      incidente?: boolean;
    }
  ): Promise<Operador> {
    const operador = await this.findByIdOrFail(tenantId, operadorId);

    operador.totalViajes = (operador.totalViajes || 0) + 1;
    operador.totalKm = (operador.totalKm || 0) + tripData.kmRecorridos;

    if (tripData.incidente) {
      operador.incidentes = (operador.incidentes || 0) + 1;
    }

    // Actualizar calificacion promedio
    if (tripData.calificacion !== undefined) {
      const currentRating = Number(operador.calificacion) || 5.0;
      const totalTrips = operador.totalViajes;
      // Promedio ponderado
      operador.calificacion = Number(
        ((currentRating * (totalTrips - 1) + tripData.calificacion) / totalTrips).toFixed(2)
      );
    }

    return this.operadorRepository.save(operador);
  }
}
