import { describe, it, expect } from "vitest";
import { ARCAResult } from "../types";
import { searchLandline, searchMobile } from "./ARCAFunctions.helper";

describe("searchMobile", () => {
  describe("CU-001: Búsqueda exitosa de teléfono móvil", () => {
    it("debe retornar el primer teléfono no fijo encontrado", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [
          {
            direccion: "maria@email.com",
            estado: "activo",
            tipoEmail: "personal",
          },
        ],
        telefonos: [
          { numero: "1155551234", tipoLinea: "FIJO", tipoTelefono: "hogar" },
          { numero: "1166665678", tipoLinea: "CELULAR", tipoTelefono: "móvil" },
        ],
      };

      const resultado = searchMobile(arcaInfo);

      expect(resultado).toEqual({
        number: "1166665678",
        type: "móvil",
      });
    });
  });

  describe("CU-002: No se encuentran teléfonos móviles", () => {
    it("debe retornar objeto vacío cuando solo hay teléfonos fijos", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          { numero: "1155551234", tipoLinea: "FIJO", tipoTelefono: "hogar" },
        ],
      };

      const resultado = searchMobile(arcaInfo);

      expect(resultado).toEqual({
        number: "",
        type: "",
      });
    });
  });

  describe("CU-003: Objeto ARCAResult sin teléfonos", () => {
    it("debe retornar objeto vacío cuando telefonos es undefined", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: undefined as any,
      };

      const resultado = searchMobile(arcaInfo);

      expect(resultado).toEqual({
        number: "",
        type: "",
      });
    });

    it("debe retornar objeto vacío cuando telefonos es null", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: null as any,
      };

      const resultado = searchMobile(arcaInfo);

      expect(resultado).toEqual({
        number: "",
        type: "",
      });
    });
  });

  describe("CU-004: Múltiples teléfonos móviles", () => {
    it("debe retornar solo el primer teléfono móvil encontrado", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          {
            numero: "1166665678",
            tipoLinea: "CELULAR",
            tipoTelefono: "personal",
          },
          { numero: "1177778901", tipoLinea: "MOVIL", tipoTelefono: "trabajo" },
        ],
      };

      const resultado = searchMobile(arcaInfo);

      expect(resultado).toEqual({
        number: "1166665678",
        type: "personal",
      });
    });
  });

  describe("CU-009: Manejo de datos inválidos (aplicable a searchMobile)", () => {
    it("debe retornar objeto vacío cuando arcaInfo es undefined", () => {
      const resultado = searchMobile(undefined as any);

      expect(resultado).toEqual({
        number: "",
        type: "",
      });
    });

    it("debe retornar objeto vacío cuando arcaInfo es null", () => {
      const resultado = searchMobile(null as any);

      expect(resultado).toEqual({
        number: "",
        type: "",
      });
    });
  });

  describe("CU-010: Teléfono con formato de número no estándar (aplicable a searchMobile)", () => {
    it("debe convertir el número a string correctamente", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          {
            numero: 1144445678 as any,
            tipoLinea: "CELULAR",
            tipoTelefono: "hogar",
          },
        ],
      };

      const resultado = searchMobile(arcaInfo);

      expect(resultado).toEqual({
        number: "1144445678",
        type: "hogar",
      });
      expect(typeof resultado.number).toBe("string");
    });
  });
});

describe("searchLandline", () => {
  describe("CU-005: Búsqueda exitosa de teléfono fijo", () => {
    it("debe retornar el primer teléfono fijo encontrado", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          { numero: "1144445678", tipoLinea: "FIJO", tipoTelefono: "hogar" },
          { numero: "1155551234", tipoLinea: "CELULAR", tipoTelefono: "móvil" },
        ],
      };

      const resultado = searchLandline(arcaInfo);

      expect(resultado).toEqual({
        type: "hogar",
        number: "1144445678",
      });
    });
  });

  describe("CU-006: No se encuentran teléfonos fijos", () => {
    it("debe retornar objeto vacío cuando solo hay teléfonos móviles", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          { numero: "1166665678", tipoLinea: "CELULAR", tipoTelefono: "móvil" },
        ],
      };

      const resultado = searchLandline(arcaInfo);

      expect(resultado).toEqual({
        type: "",
        number: "",
      });
    });
  });

  describe("CU-007: Objeto ARCAResult sin teléfonos", () => {
    it("debe retornar objeto vacío cuando telefonos es undefined", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: undefined as any,
      };

      const resultado = searchLandline(arcaInfo);

      expect(resultado).toEqual({
        type: "",
        number: "",
      });
    });

    it("debe retornar objeto vacío cuando telefonos es null", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: null as any,
      };

      const resultado = searchLandline(arcaInfo);

      expect(resultado).toEqual({
        type: "",
        number: "",
      });
    });
  });

  describe("CU-008: Teléfono fijo con tipoLinea en mayúsculas/minúsculas", () => {
    it("debe encontrar teléfono fijo independientemente del formato de escritura", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          { numero: "1144445678", tipoLinea: "Fijo", tipoTelefono: "hogar" },
          { numero: "1144445679", tipoLinea: "fijo", tipoTelefono: "oficina" },
        ],
      };

      const resultado = searchLandline(arcaInfo);

      expect(resultado).toEqual({
        type: "hogar",
        number: "1144445678",
      });
    });

    it("debe encontrar teléfono fijo con tipoLinea en minúsculas", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          { numero: "1144445679", tipoLinea: "fijo", tipoTelefono: "oficina" },
        ],
      };

      const resultado = searchLandline(arcaInfo);

      expect(resultado).toEqual({
        type: "oficina",
        number: "1144445679",
      });
    });
  });

  describe("CU-009: Manejo de datos inválidos (aplicable a searchLandline)", () => {
    it("debe retornar objeto vacío cuando arcaInfo es undefined", () => {
      const resultado = searchLandline(undefined as any);

      expect(resultado).toEqual({
        type: "",
        number: "",
      });
    });

    it("debe retornar objeto vacío cuando arcaInfo es null", () => {
      const resultado = searchLandline(null as any);

      expect(resultado).toEqual({
        type: "",
        number: "",
      });
    });
  });

  describe("CU-010: Teléfono con formato de número no estándar (aplicable a searchLandline)", () => {
    it("debe convertir el número a string correctamente", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          {
            numero: 1144445678 as any,
            tipoLinea: "FIJO",
            tipoTelefono: "hogar",
          },
        ],
      };

      const resultado = searchLandline(arcaInfo);

      expect(resultado).toEqual({
        type: "hogar",
        number: "1144445678",
      });
      expect(typeof resultado.number).toBe("string");
    });
  });
});

// Casos de prueba adicionales para cubrir edge cases
describe("Casos de prueba adicionales", () => {
  describe("searchMobile - Edge cases", () => {
    it("debe manejar tipoLinea con espacios en blanco", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          {
            numero: "1166665678",
            tipoLinea: "  CELULAR  ",
            tipoTelefono: "móvil",
          },
        ],
      };

      const resultado = searchMobile(arcaInfo);

      // Nota: esto fallaría porque no se hace trim, es un edge case a considerar
      expect(resultado).toEqual({
        number: "1166665678",
        type: "móvil",
      });
    });

    it("debe manejar lista de teléfonos vacía", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [],
      };

      const resultado = searchMobile(arcaInfo);

      expect(resultado).toEqual({
        number: "",
        type: "",
      });
    });
  });

  describe("searchLandline - Edge cases", () => {
    it("debe manejar tipoLinea con espacios en blanco", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          {
            numero: "1144445678",
            tipoLinea: "  FIJO  ",
            tipoTelefono: "hogar",
          },
        ],
      };

      const resultado = searchLandline(arcaInfo);

      // Nota: esto fallaría porque no se hace trim, es un edge case a considerar
      expect(resultado).toEqual({
        type: "hogar",
        number: "1144445678",
      });
    });

    it("debe manejar lista de teléfonos vacía", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [],
      };

      const resultado = searchLandline(arcaInfo);

      expect(resultado).toEqual({
        type: "",
        number: "",
      });
    });
  });

  describe("Pruebas de integración", () => {
    it("searchMobile y searchLandline deben funcionar independientemente en el mismo objeto", () => {
      const arcaInfo: ARCAResult = {
        cuit: "20-12345678-9",
        apellido: "González",
        nombre: "María",
        emails: [],
        telefonos: [
          { numero: "1144445678", tipoLinea: "FIJO", tipoTelefono: "hogar" },
          { numero: "1166665678", tipoLinea: "CELULAR", tipoTelefono: "móvil" },
        ],
      };

      const mobileResult = searchMobile(arcaInfo);
      const landlineResult = searchLandline(arcaInfo);

      expect(mobileResult).toEqual({
        number: "1166665678",
        type: "móvil",
      });

      expect(landlineResult).toEqual({
        type: "hogar",
        number: "1144445678",
      });

      // Verificar que son diferentes
      expect(mobileResult.number).not.toBe(landlineResult.number);
    });
  });
});
