import { ConflictException, Injectable, NotFoundException } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { PrismaService } from 'src/prisma/prisma.service';
import { CreatePersonaDto } from './dto/create-persona.dto';
import { UpdatePersonaDto } from './dto/update-persona.dto';

type PersonaValidationInput = {
  empresa_id?: string;
  tipo_documento_id?: string;
  ciudad_id?: string | null;
  naturaleza_id?: string;
  tipo_contribuyente_id?: string;
  ruc?: string | null;
  dv?: number | null;
  nro_documento?: string | null;
  otro_tipo_documento?: string | null;
  direccion?: string | null;
  pais_id?: string | null;
};

@Injectable()
export class PersonasService {
  constructor(private prisma: PrismaService) {}
  async create(createPersonaDto: CreatePersonaDto, empresa_id: string) {
    try {
      // buscara por ruc o nro de documento para retornar la persona creada o la que ya existe
      const orFilters: Prisma.personasWhereInput[] = [];
      if (createPersonaDto.ruc) {
        orFilters.push({ ruc: createPersonaDto.ruc, empresa_id });
      }
      if (createPersonaDto.nro_documento) {
        orFilters.push({ nro_documento: createPersonaDto.nro_documento, empresa_id });
      }
      const where = {
        OR: orFilters,
      };
      // Si ya existe una persona con ese RUC/documento, NO se duplica: se reutiliza.
      // Antes se retornaba sin tocar, y los datos provistos ahora (dirección, contacto,
      // geo, etc.) se perdían en silencio. Ahora COMPLETAMOS los campos que la persona
      // tenga vacíos con los valores provistos (merge no destructivo: no pisa datos ya
      // cargados). Así, p.ej., registrar un transportista/cliente con un RUC ya existente
      // le agrega la dirección faltante sin sobrescribir lo que ya tenía.
      if (orFilters.length > 0) {
        const personaFind = await this.findFirst(where);
        if (personaFind && !personaFind.deleted) {
          const completar: Prisma.personasUpdateInput = {};
          const setSiVacio = (campo: keyof typeof personaFind, valor: unknown) => {
            const actual = personaFind[campo];
            const vacioActual = actual === null || actual === undefined || actual === '' || actual === '0';
            const traeValor = valor !== null && valor !== undefined && valor !== '';
            if (vacioActual && traeValor) (completar as Record<string, unknown>)[campo] = valor;
          };
          setSiVacio('direccion', createPersonaDto.direccion);
          setSiVacio('nro_casa', createPersonaDto.nro_casa);
          setSiVacio('celular', createPersonaDto.celular);
          setSiVacio('telefono', createPersonaDto.telefono);
          setSiVacio('email', createPersonaDto.email);
          setSiVacio('pais_id', createPersonaDto.pais_id);
          setSiVacio('ciudad_id', createPersonaDto.ciudad_id);
          if (Object.keys(completar).length > 0) {
            return this.prisma.personas.update({ where: { id: personaFind.id }, data: completar });
          }
          return personaFind;
        }
      }

      const empresa = await this.prisma.empresas.findUnique({ where: { id: empresa_id } });
      if (!empresa) throw new NotFoundException('La empresa a vincular no existe');
      // Validaciones adionales antes de registrar
      await this.validatePersonaInput(createPersonaDto);
      const naturaleza = await this.prisma.naturaleza_receptor.findUnique({
        where: { id: createPersonaDto.naturaleza_id },
      });
      if (!naturaleza) throw new NotFoundException('La naturaleza no existe');
      console.log(createPersonaDto);

      const persona = await this.prisma.personas.create({
        data: {
          empresa_id,
          tipo_documento_id: naturaleza.codigo === 2 ? createPersonaDto.tipo_documento_id : null,
          naturaleza_id: createPersonaDto.naturaleza_id ?? null,
          tipo_contribuyente_id: naturaleza.codigo === 1 ? createPersonaDto.tipo_contribuyente_id : null,
          pais_id: createPersonaDto.pais_id ?? null,
          ciudad_id: createPersonaDto.ciudad_id ?? null,
          razon_social: createPersonaDto.razon_social,
          direccion: createPersonaDto.direccion ?? null,
          nro_casa: createPersonaDto.nro_casa,
          celular: createPersonaDto.celular,
          telefono: createPersonaDto.telefono,
          email: createPersonaDto.email,
          ruc: naturaleza.codigo === 1 ? createPersonaDto.ruc : null,
          dv: naturaleza.codigo === 1 ? createPersonaDto.dv?.toString() : null,
          nro_documento: naturaleza.codigo === 2 ? createPersonaDto.nro_documento : null,
          otro_tipo_documento: naturaleza.codigo === 2 ? createPersonaDto.otro_tipo_documento : null,
          email_adicional: createPersonaDto.email_adicional,
          email_copia: createPersonaDto.email_copia ?? null,
        },
      });
      return persona;
    } catch (error) {
      if (error instanceof ConflictException) throw error;
      if (error instanceof NotFoundException) throw error;
      const message = error instanceof Error ? error.message : 'Error desconocido';
      throw new Error(`Error al crear persona: ${message}`);
    }
  }
  async update(id: string, updatePersonaDto: UpdatePersonaDto, empresa_id: string) {
    try {
      const naturaleza = await this.prisma.naturaleza_receptor.findUnique({
        where: { id: updatePersonaDto.naturaleza_id },
      });
      if (!naturaleza) throw new NotFoundException('La naturaleza no existe');
      const personaFind = await this.prisma.personas.findUnique({ where: { id, empresa_id } });
      if (!personaFind || personaFind.deleted) throw new NotFoundException('La persona no existe');
      await this.validatePersonaInput(updatePersonaDto);

      const persona = await this.prisma.personas.update({
        where: { id, empresa_id },
        data: {
          empresa_id,
          tipo_documento_id: naturaleza.codigo === 2 ? updatePersonaDto.tipo_documento_id : null,
          naturaleza_id: updatePersonaDto.naturaleza_id ?? null,
          tipo_contribuyente_id: naturaleza.codigo === 1 ? updatePersonaDto.tipo_contribuyente_id : null,
          pais_id: updatePersonaDto.pais_id ?? null,
          ciudad_id: updatePersonaDto.ciudad_id ?? null,
          razon_social: updatePersonaDto.razon_social,
          direccion: updatePersonaDto.direccion ?? null,
          nro_casa: updatePersonaDto.nro_casa,
          celular: updatePersonaDto.celular,
          telefono: updatePersonaDto.telefono,
          email: updatePersonaDto.email,
          ruc: naturaleza.codigo === 1 ? updatePersonaDto.ruc : null,
          dv: naturaleza.codigo === 1 ? updatePersonaDto.dv?.toString() : null,
          nro_documento: naturaleza.codigo === 2 ? updatePersonaDto.nro_documento : null,
          otro_tipo_documento: naturaleza.codigo === 2 ? updatePersonaDto.otro_tipo_documento : null,
          email_adicional: updatePersonaDto.email_adicional,
          email_copia: updatePersonaDto.email_copia ?? null,
        },
      });
      return persona;
    } catch (error) {
      if (error instanceof ConflictException) throw error;
      if (error instanceof NotFoundException) throw error;
      const message = error instanceof Error ? error.message : 'Error desconocido';
      throw new Error(`Error al actualizar persona: ${message}`);
    }
  }
  findAll() {
    return `This action returns all personas`;
  }

  findOne(id: number) {
    return `This action returns a #${id} persona`;
  }
  async findFirst(where: Prisma.personasWhereInput) {
    const persona = await this.prisma.personas.findFirst({ where });
    return persona;
  }

  /**
   * Busca una persona ya registrada por RUC dentro de la empresa, para que el
   * formulario de alta de Cliente/Proveedor pueda autocompletar sus datos en
   * vez de obligar a retipear todo cuando el RUC ya existe con el otro rol
   * (cliente y proveedor son roles independientes sobre la misma `personas`).
   */
  async buscarPorRuc(ruc: string, empresaId: string) {
    const rucNormalizado = String(ruc || '').replace(/\D/g, '');
    if (rucNormalizado.length < 3) {
      return { encontrado: false as const };
    }

    const persona = await this.prisma.personas.findFirst({
      where: { empresa_id: empresaId, ruc: rucNormalizado, deleted: false },
      select: {
        id: true,
        razon_social: true,
        ruc: true,
        dv: true,
        naturaleza_receptor: true,
        tipo_contribuyente: true,
        tipo_documento_identidad: true,
        nro_documento: true,
        otro_tipo_documento: true,
        direccion: true,
        nro_casa: true,
        telefono: true,
        celular: true,
        email: true,
        pais_id: true,
        ciudad_id: true,
        paises: { select: { id: true, codigo: true, descripcion: true } },
        ciudades: { select: { id: true, codigo: true, descripcion: true } },
      },
    });
    if (!persona) {
      return { encontrado: false as const };
    }

    const [cliente, proveedor] = await Promise.all([
      this.prisma.clientes.findFirst({
        where: { persona_id: persona.id, deleted: false },
        select: { id: true },
      }),
      this.prisma.proveedores.findFirst({
        where: { persona_id: persona.id, empresa_id: empresaId, activo: true },
        select: { id: true },
      }),
    ]);

    return {
      encontrado: true as const,
      persona,
      es_cliente: !!cliente,
      es_proveedor: !!proveedor,
    };
  }

  remove(id: number) {
    return `This action removes a #${id} persona`;
  }

  /**
   * Valida una persona ya almacenada (típico caso: cliente importado desde Excel
   * sin pasar por las validaciones del formulario del ERP). Acumula TODOS los
   * errores en vez de cortar al primero, para que el usuario pueda corregirlos
   * en una sola pasada antes de emitir factura electrónica.
   *
   * Retorna lista de mensajes de error. Vacía → persona válida.
   */
  async validatePersonaById(
    personaId: string,
    empresa_id: string,
    opts?: {
      tipoOperacionCodigo?: number | null;
      /**
       * ID de la `cliente_direcciones` que la factura va a usar (viene en el
       * payload como `cabecera.cliente_direccion_id`). Si se pasa, la validación
       * de ubicación se aplica solo a esa dirección específica. Si es null/undefined,
       * se hace fallback a la geo de la persona.
       */
      clienteDireccionId?: string | null;
      /**
       * Si es true, no se exige `pais_id` en la persona (se asume país por
       * defecto). Lo usa la nota de remisión, que hoy opera solo dentro de
       * Paraguay (`cPaisRec` fijo en 'PRY'). Igual se valida la consistencia
       * de ciudad/distrito/departamento. Factura/NC no lo pasan.
       */
      omitirValidacionPais?: boolean;
    },
  ): Promise<string[]> {
    const persona = await this.prisma.personas.findFirst({
      where: { id: personaId, empresa_id },
    });
    if (!persona) return ['La persona del cliente no existe en la empresa'];

    const errors: string[] = [];
    const emailRe = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

    // ── Razón social: obligatoria, 4-255 (CreatePersonaDto) ─────────
    const razonSocial = (persona.razon_social ?? '').trim();
    if (!razonSocial) {
      errors.push('Razón social es obligatoria');
    } else if (razonSocial.length < 4 || razonSocial.length > 255) {
      errors.push('Razón social debe tener entre 4 y 255 caracteres');
    }

    // ── Dirección: opcional, pero si está debe ser 4-255 ────────────
    if (persona.direccion != null && persona.direccion.trim() !== '') {
      const d = persona.direccion.trim();
      if (d.length < 4 || d.length > 255) {
        errors.push('Dirección debe tener entre 4 y 255 caracteres');
      }
    }

    // ── Celular: opcional, 10-20 ────────────────────────────────────
    if (persona.celular != null && persona.celular.trim() !== '') {
      const v = persona.celular.trim();
      if (v.length < 10 || v.length > 20) {
        errors.push('Celular debe tener mínimo 10 y máximo 20 caracteres');
      }
    }

    // ── Teléfono: opcional, 6-20 ────────────────────────────────────
    if (persona.telefono != null && persona.telefono.trim() !== '') {
      const v = persona.telefono.trim();
      if (v.length < 6 || v.length > 20) {
        errors.push('Teléfono debe tener entre 6 y 20 caracteres');
      }
    }

    // ── Email principal / adicional / copia: opcional, formato + 3-80
    const validarEmail = (campo: string, label: string) => {
      const raw = (persona as any)[campo] as string | null | undefined;
      if (raw == null || raw.trim() === '') return;
      const v = raw.trim();
      if (v.length < 3 || v.length > 80) {
        errors.push(`${label} debe tener entre 3 y 80 caracteres`);
      }
      if (!emailRe.test(v)) {
        errors.push(`${label} debe tener un formato válido`);
      }
    };
    validarEmail('email', 'Email');
    validarEmail('email_adicional', 'Email adicional');
    validarEmail('email_copia', 'Email copia');

    // ── Naturaleza receptor ─────────────────────────────────────────
    const naturaleza = persona.naturaleza_id
      ? await this.prisma.naturaleza_receptor.findUnique({ where: { id: persona.naturaleza_id } })
      : null;
    if (!naturaleza) {
      errors.push('La naturaleza del receptor no está definida o no existe');
      return errors;
    }

    // ── Tipo de operación del cliente (B2B/B2C/B2G/B2F) ──────────────
    // Reglas (mismas del formulario ERP — ClienteFormDialog):
    //   • Tarjeta Diplomática (tipo_doc=6) → solo B2F (cód 4)
    //   • Contribuyente (naturaleza=1)     → B2B (1) o B2F (4)
    //   • No contribuyente (naturaleza=2)  → B2B (1) o B2C (2)
    // Se aplica solo si el caller proporciona el código de tipo_operacion del cliente.
    if (opts?.tipoOperacionCodigo != null) {
      const tOp = Number(opts.tipoOperacionCodigo);
      // Necesitamos saber tipoDocumento.codigo para la regla de Tarjeta Diplomática
      let tipoDocCodigo: number | null = null;
      if (naturaleza.codigo === 2 && persona.tipo_documento_id) {
        const td = await this.prisma.tipo_documento_identidad.findUnique({
          where: { id: persona.tipo_documento_id },
          select: { codigo: true },
        });
        tipoDocCodigo = td?.codigo ?? null;
      }

      if (tipoDocCodigo === 6) {
        if (tOp !== 4) {
          errors.push('Tipo de operación debe ser B2F (Tarjeta Diplomática solo admite B2F)');
        }
      } else if (naturaleza.codigo === 1) {
        if (tOp !== 1 && tOp !== 3) {
          errors.push('Tipo de operación inválido para contribuyente: debe ser B2B o B2G');
        }
      } else if (naturaleza.codigo === 2) {
        if (tOp !== 2 && tOp !== 4) {
          errors.push('Tipo de operación inválido para no contribuyente: debe ser B2C o B2F');
        }
      }
    }

    if (naturaleza.codigo === 1) {
      // ── Contribuyente ─────────────────────────────────────────────
      if (!persona.tipo_contribuyente_id) {
        errors.push('Tipo de contribuyente es obligatorio');
      } else {
        const tipoContribuyente = await this.prisma.tipo_contribuyente.findUnique({
          where: { id: persona.tipo_contribuyente_id },
        });
        if (!tipoContribuyente) errors.push('El tipo de contribuyente referenciado no existe');
      }

      // RUC: 3-8 dígitos
      if (!persona.ruc || !persona.ruc.trim()) {
        errors.push('RUC es obligatorio');
      } else {
        const r = persona.ruc.trim();
        if (r.length < 3 || r.length > 8) {
          errors.push('RUC debe tener entre 3 y 8 dígitos');
        }
        if (!/^\d+$/.test(r)) {
          errors.push('RUC debe contener solo dígitos');
        }
      }

      // DV: 0-9
      if (persona.dv == null || String(persona.dv).trim() === '') {
        errors.push('Dígito verificador (DV) es obligatorio');
      } else {
        const dvStr = String(persona.dv).trim();
        const dvNum = Number(dvStr);
        if (!/^\d+$/.test(dvStr) || Number.isNaN(dvNum)) {
          errors.push('DV debe ser un número');
        } else if (dvNum < 0 || dvNum > 9) {
          errors.push('DV debe ser un número entre 0 y 9');
        }
      }
    }

    if (naturaleza.codigo === 2) {
      // ── No contribuyente ──────────────────────────────────────────
      if (!persona.tipo_documento_id) {
        errors.push('Tipo de documento de identidad es obligatorio');
      }

      let tipoDocumento: { codigo: number } | null = null;
      if (persona.tipo_documento_id) {
        tipoDocumento = await this.prisma.tipo_documento_identidad.findUnique({
          where: { id: persona.tipo_documento_id },
          select: { codigo: true },
        });
        if (!tipoDocumento) errors.push('El tipo de documento de identidad referenciado no existe');
      }

      // Nro. documento: 1-20
      if (!persona.nro_documento || !persona.nro_documento.trim()) {
        errors.push('Nro. de documento es obligatorio');
      } else {
        const n = persona.nro_documento.trim();
        if (n.length < 1 || n.length > 20) {
          errors.push('Nro. documento debe tener entre 1 y 20 caracteres');
        }
      }

      // Otro tipo documento: 9-41 si tipoDoc=Otro (cód 9)
      if (tipoDocumento?.codigo === 9) {
        if (!persona.otro_tipo_documento || !persona.otro_tipo_documento.trim()) {
          errors.push('Descripción del tipo de documento es obligatoria cuando el tipo es "Otro"');
        } else {
          const o = persona.otro_tipo_documento.trim();
          if (o.length < 9 || o.length > 41) {
            errors.push('Otro tipo documento debe tener entre 9 y 41 caracteres');
          }
        }
      }

      // Tarjeta diplomática (cód 6): dirección + país ≠ PRY
      if (tipoDocumento?.codigo === 6) {
        if (!persona.direccion || persona.direccion.trim() === '') {
          errors.push('Dirección es obligatoria para Tarjeta Diplomática de exoneración fiscal');
        }
        if (!persona.pais_id) {
          errors.push('País es obligatorio para Tarjeta Diplomática de exoneración fiscal');
        } else {
          const pais = await this.prisma.paises.findUnique({
            where: { id: persona.pais_id },
            select: { codigo: true },
          });
          if (!pais) {
            errors.push('El país referenciado no existe');
          } else if (pais.codigo === 'PRY') {
            errors.push('País debe ser diferente a Paraguay (PRY) para Tarjeta Diplomática de exoneración fiscal');
          }
        }
      }
    }

    // ── Ubicación geográfica (SIFEN gDatRec) ────────────────────────
    // SIFEN exige `cPaisRec` en el receptor. La factura envía
    // `cabecera.cliente_direccion_id` cuando el cajero eligió una dirección
    // específica del cliente; si viene, se valida ESA dirección. Si no viene,
    // se valida la geo default de la persona.
    // El texto de dirección concreto (`ddirrec`) lo maneja la factura por
    // separado, así que no lo repetimos acá — solo verificamos que la cadena
    // pais / depto / distrito / ciudad esté consistente.
    if (opts?.clienteDireccionId) {
      const d = await this.prisma.cliente_direcciones.findUnique({
        where: { id: opts.clienteDireccionId },
        select: {
          id: true,
          label: true,
          pais_id: true,
          departamento_id: true,
          distrito_id: true,
          ciudad_id: true,
          paises: { select: { codigo: true, descripcion: true } },
          distritos: { select: { id: true, departamento_id: true } },
          ciudades: { select: { id: true, distrito_id: true } },
        },
      });
      if (!d) {
        errors.push('La dirección seleccionada para la factura no existe.');
      } else {
        const etiqueta = d.label ? `"${d.label}"` : 'seleccionada';
        if (!d.pais_id) {
          errors.push(`La dirección ${etiqueta} no tiene país definido. SIFEN exige el país del receptor.`);
        } else {
          const esPYD =
            d.paises?.codigo === 'PRY' ||
            (d.paises?.descripcion || '').toLowerCase() === 'paraguay';
          if (esPYD) {
            const alguno = !!d.departamento_id || !!d.distrito_id || !!d.ciudad_id;
            if (alguno) {
              if (!d.departamento_id) {
                errors.push(`Falta el departamento en la dirección ${etiqueta}. Deben ir juntos departamento / distrito / ciudad.`);
              }
              if (!d.distrito_id) {
                errors.push(`Falta el distrito en la dirección ${etiqueta}. Elegilo después del departamento.`);
              }
              if (!d.ciudad_id) {
                errors.push(`Falta la ciudad en la dirección ${etiqueta}. Elegila después del distrito.`);
              }
              if (d.distrito_id && d.departamento_id && d.distritos?.departamento_id !== d.departamento_id) {
                errors.push(`Inconsistencia en la dirección ${etiqueta}: el distrito no pertenece al departamento seleccionado.`);
              }
              if (d.ciudad_id && d.distrito_id && d.ciudades?.distrito_id !== d.distrito_id) {
                errors.push(`Inconsistencia en la dirección ${etiqueta}: la ciudad no pertenece al distrito seleccionado.`);
              }
            }
          }
        }
      }
    } else if (opts?.omitirValidacionPais) {
      // Remisión (solo Paraguay): país por defecto, no se exige pais_id.
      // Igual se valida la consistencia de ciudad/distrito/departamento.
      await this.validarGeoCiudad(persona.ciudad_id, errors);
    } else {
      // Fallback: validar la geo default de la persona.
      if (!persona.pais_id) {
        // La dirección del cliente es OPCIONAL. Si el cliente NO tiene ninguna dirección
        // registrada (cliente_direcciones), no exigimos país: se asume Paraguay por defecto
        // para el receptor. Solo cuando tiene direcciones cargadas (y no eligió una al
        // facturar) pedimos país en la ficha o elegir una dirección específica.
        const tieneDirecciones = await this.prisma.cliente_direcciones.count({
          where: { empresa_id, clientes: { persona_id: personaId } },
        });
        if (tieneDirecciones > 0) {
          errors.push(
            'El cliente no tiene país registrado en su ficha. SIFEN exige el país del receptor (o elegí una dirección específica del cliente al facturar).',
          );
        }
      } else {
        const pais = await this.prisma.paises.findUnique({
          where: { id: persona.pais_id },
          select: { codigo: true },
        });
        if (!pais) errors.push('El país referenciado en la persona no existe.');
        await this.validarGeoCiudad(persona.ciudad_id, errors);
      }
    }

    return errors;
  }

  /** Valida la consistencia de la ciudad/distrito/departamento de la persona. */
  private async validarGeoCiudad(ciudadId: string | null, errors: string[]): Promise<void> {
    if (!ciudadId) return;
    const ciudad = await this.prisma.ciudades.findUnique({
      where: { id: ciudadId },
      select: {
        id: true,
        distrito_id: true,
        distritos: { select: { id: true, departamento_id: true } },
      },
    });
    if (!ciudad) {
      errors.push('La ciudad del cliente ya no existe en el catálogo — actualizá la dirección.');
    } else if (!ciudad.distrito_id) {
      errors.push('La ciudad del cliente no tiene distrito asociado en el catálogo — contactá soporte.');
    } else if (!ciudad.distritos?.departamento_id) {
      errors.push('El distrito de la ciudad no tiene departamento asociado — contactá soporte.');
    }
  }

  private async validatePersonaInput(input: PersonaValidationInput): Promise<void> {
    const { naturaleza_id, tipo_contribuyente_id } = input;

    const naturaleza = await this.prisma.naturaleza_receptor.findUnique({ where: { id: naturaleza_id } });
    if (!naturaleza) throw new ConflictException('La naturaleza no existe');

    if (naturaleza.codigo === 1) {
      if (!tipo_contribuyente_id) {
        throw new ConflictException('El tipo de contribuyente es obligatorio para un contribuyente');
      }
      const tipoContribuyente = await this.prisma.tipo_contribuyente.findUnique({
        where: { id: tipo_contribuyente_id },
      });
      if (!tipoContribuyente) throw new NotFoundException('El tipo de contribuyente no existe');

      if (!input.ruc || input.dv == null) {
        throw new ConflictException('El RUC y el DV son obligatorios');
      }
    }

    if (naturaleza.codigo === 2) {
      if (!input.tipo_documento_id) {
        throw new ConflictException('El tipo de documento de identidad es obligatorio');
      }
      const tipo_documento_identidad = await this.prisma.tipo_documento_identidad.findUnique({
        where: { id: input.tipo_documento_id },
      });
      if (!tipo_documento_identidad) throw new NotFoundException('El tipo de documento de identidad no existe');

      if (!input.nro_documento) {
        throw new ConflictException('El Nro. documento es obligatorio');
      }

      if (tipo_documento_identidad.codigo === 6) {
        if (!input.direccion || input.direccion.trim() === '') {
          throw new ConflictException(
            'La dirección es obligatoria para el tipo de documento de identidad "Tarjeta Diplomática de exoneración fiscal"',
          );
        }

        if (!input.pais_id) {
          throw new ConflictException(
            'El país es obligatorio para el tipo de documento de identidad "Tarjeta Diplomática de exoneración fiscal"',
          );
        }

        const pais = await this.prisma.paises.findUnique({
          where: { id: input.pais_id },
          select: {
            codigo: true,
          },
        });
        if (!pais) throw new NotFoundException('El pais no existe');

        const paisCodigo = pais.codigo;
        if (paisCodigo === 'PRY') {
          throw new ConflictException(
            'El pais debe ser diferente a  Paraguay (PRY) cuando el tipo de documento de identidad es Tarjeta Diplomática de exoneración fiscal',
          );
        }
      }

      if (tipo_documento_identidad.codigo === 9) {
        if (!input.otro_tipo_documento) {
          throw new ConflictException(
            'La descripcion del tipo de documento es obligatorio para el tipo de documento de identidad "Otro"',
          );
        }
      }
    }
  }
}
