/**
 * Serviço para gerenciar entregas via BFF
 * Integração com https://bff-dev.saveinmed.com.br/api/v1/entregas
 */

const BFF_BASE_URL = process.env.NEXT_PUBLIC_BFF_API_URL!;

/**
 * Interface para entrega da API BFF
 */
export interface EntregaBff {
  id: string;
  entregadorId: string;
  empresaId: string;
  enderecoEntrega: string;
  cidadeEntrega: string;
  estadoEntrega: string;
  cepEntrega: string;
  paisEntrega: string;
  bairroEntrega: string;
  numeroEntrega: string;
  complementoEntrega: string;
  nomeDestinatario: string;
  telefoneDestinatario: string;
  emailDestinatario: string;
  status: "pendente" | "em_transito" | "entregue" | "cancelado";
  codigoRastreamento: string;
  dataEntregaEstimativa: string;
  dataEntregaReal: string | null;
  dataColeta: string;
  dataAtribuicao: string;
  dataCriacao: string;
  dataAtualizacao: string;
  taxaEntrega: number;
  distancia: number;
  observacoesEntrega: string | null;
  urlComprovanteEntrega: string | null;
  assinaturaEntrega: string | null;
  motivoFalha: string | null;
  motivoCancelamento: string | null;
  createdAt: string;
  updatedAt: string;
}

/**
 * Interface para resposta paginada da API BFF
 */
export interface EntregasBffResponse {
  page: number;
  limit: number;
  total: number;
  items: EntregaBff[];
}

/**
 * Interface para parâmetros de busca
 */
export interface EntregasBffParams {
  page?: number;
  limit?: number;
  search?: string;
  status?: string;
}

/**
 * Configuração de status para entregas
 */
export const statusConfig = {
  pendente: {
    label: "Pendente",
    color: "bg-yellow-100 text-yellow-800",
    bgColor: "bg-yellow-300 text-yellow-900 font-semibold",
  },
  em_transito: {
    label: "Em Trânsito",
    color: "bg-blue-100 text-blue-800",
    bgColor: "bg-blue-300 text-blue-900 font-semibold",
  },
  entregue: {
    label: "Entregue",
    color: "bg-green-100 text-green-800",
    bgColor: "bg-green-300 text-green-900 font-semibold",
  },
  cancelado: {
    label: "Cancelado",
    color: "bg-red-100 text-red-800",
    bgColor: "bg-red-300 text-red-900 font-semibold",
  },
};

/**
 * Serviço de entregas via BFF
 */
export const entregasApiService = {
  /**
   * Lista entregas com paginação
   * @param params - Parâmetros de busca e paginação
   * @returns Lista paginada de entregas
   */
  listar: async (params: EntregasBffParams = {}): Promise<EntregasBffResponse> => {
    try {
      const token = localStorage.getItem('access_token');

      if (!token) {
        throw new Error('Token de autenticação não encontrado');
      }

      // Construir query params
      const queryParams = new URLSearchParams();
      if (params.page !== undefined) queryParams.append('page', params.page.toString());
      if (params.limit !== undefined) queryParams.append('limit', params.limit.toString());
      if (params.search) queryParams.append('search', params.search);
      if (params.status && params.status !== 'todos') queryParams.append('status', params.status);

      const url = `${BFF_BASE_URL}/entregas${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;


      const response = await fetch(url, {
        method: 'GET',
        headers: {
          'accept': 'application/json',
          'Authorization': `Bearer ${token}`,
        },
      });

      if (!response.ok) {
        const errorText = await response.text();
        console.error('❌ Erro na resposta da API:', {
          status: response.status,
          statusText: response.statusText,
          body: errorText,
        });

        if (response.status === 401) {
          throw new Error('Token de autenticação inválido ou expirado');
        }

        throw new Error(`Erro ao buscar entregas: ${response.status} ${response.statusText}`);
      }

      const data: EntregasBffResponse = await response.json();

      return data;

    } catch (error) {
      console.error('❌ Erro ao buscar entregas:', error);
      throw error;
    }
  },

  /**
   * Busca entrega por ID
   * @param entregaId - ID da entrega
   * @returns Dados da entrega
   */
  buscarPorId: async (entregaId: string): Promise<EntregaBff | null> => {
    try {
      const token = localStorage.getItem('access_token');

      if (!token) {
        throw new Error('Token de autenticação não encontrado');
      }


      const response = await fetch(`${BFF_BASE_URL}/entregas/${entregaId}`, {
        method: 'GET',
        headers: {
          'accept': 'application/json',
          'Authorization': `Bearer ${token}`,
        },
      });

      if (!response.ok) {
        if (response.status === 404) {
          console.warn(`⚠️ Entrega não encontrada: ${entregaId}`);
          return null;
        }

        const errorText = await response.text();
        console.error('❌ Erro na resposta da API:', {
          status: response.status,
          statusText: response.statusText,
          body: errorText,
        });

        if (response.status === 401) {
          throw new Error('Token de autenticação inválido ou expirado');
        }

        throw new Error(`Erro ao buscar entrega: ${response.status} ${response.statusText}`);
      }

      const entrega: EntregaBff = await response.json();

      return entrega;

    } catch (error) {
      console.error('❌ Erro ao buscar entrega:', error);
      throw error;
    }
  },

  /**
   * Tenta descobrir o schema da API de entregas
   */
  testarSchema: async (): Promise<void> => {
    try {
      const token = localStorage.getItem('access_token');
      if (!token) return;

      // Tentar OPTIONS para ver se retorna schema
      const optionsResponse = await fetch(`${BFF_BASE_URL}/entregas`, {
        method: 'OPTIONS',
        headers: {
          'Authorization': `Bearer ${token}`,
        },
      });


    } catch (error) {
      throw error;
    }
  },

  /**
   * Cria uma nova entrega
   * @param dadosEntrega - Dados da entrega a ser criada
   * @returns Entrega criada
   */
  criar: async (dadosEntrega: any): Promise<{ success: boolean; data?: EntregaBff; error?: string }> => {
    try {
      const token = localStorage.getItem('access_token');

      if (!token) {
        throw new Error('Token de autenticação não encontrado');
      }


      // Formato correto da API BFF - precisa do documentId
      const payload = {
        documentId: "unique()",
        data: dadosEntrega
      };


      const response = await fetch(`${BFF_BASE_URL}/entregas`, {
        method: 'POST',
        headers: {
          'accept': 'application/json',
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`,
        },
        body: JSON.stringify(payload),
      });

      if (!response.ok) {
        let errorDetails;
        try {
          errorDetails = await response.json();
          console.error('❌ Erro detalhado da API:', JSON.stringify(errorDetails, null, 2));
        } catch {
          errorDetails = await response.text();
          console.error('❌ Erro de texto da API:', errorDetails);
        }

        console.error('❌ Erro na resposta da API:', {
          status: response.status,
          statusText: response.statusText,
          body: errorDetails,
        });

        if (response.status === 401) {
          return { success: false, error: 'Token de autenticação inválido ou expirado' };
        }

        // Se o erro contém detalhes de validação, incluir na mensagem
        if (errorDetails && errorDetails.detail) {
          const validationErrors = errorDetails.detail.map((err: any) => `${err.loc.join('.')}: ${err.msg}`).join(', ');
          return { success: false, error: `Erro de validação: ${validationErrors}` };
        }

        return { success: false, error: `Erro ao criar entrega: ${response.status} ${response.statusText}` };
      }

      const entrega: EntregaBff = await response.json();

      return { success: true, data: entrega };

    } catch (error) {
      console.error('❌ Erro ao criar entrega:', error);
      const errorMessage = error instanceof Error ? error.message : 'Erro desconhecido ao criar entrega';
      return { success: false, error: errorMessage };
    }
  },

  /**
   * Atualiza status de uma entrega
   * @param entregaId - ID da entrega
   * @param novoStatus - Novo status da entrega
   * @returns Entrega atualizada
   */
  atualizarStatus: async (entregaId: string, novoStatus: EntregaBff['status']): Promise<EntregaBff> => {
    try {
      const token = localStorage.getItem('access_token');

      if (!token) {
        throw new Error('Token de autenticação não encontrado');
      }


      const response = await fetch(`${BFF_BASE_URL}/entregas/${entregaId}`, {
        method: 'PATCH',
        headers: {
          'accept': 'application/json',
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`,
        },
        body: JSON.stringify({ status: novoStatus }),
      });

      if (!response.ok) {
        const errorText = await response.text();
        console.error('❌ Erro na resposta da API:', {
          status: response.status,
          statusText: response.statusText,
          body: errorText,
        });

        if (response.status === 401) {
          throw new Error('Token de autenticação inválido ou expirado');
        }

        throw new Error(`Erro ao atualizar status da entrega: ${response.status} ${response.statusText}`);
      }

      const entrega: EntregaBff = await response.json();

      return entrega;

    } catch (error) {
      console.error('❌ Erro ao atualizar status da entrega:', error);
      throw error;
    }
  },

  /**
   * Busca coordenadas (latitude e longitude) a partir do CEP
   * @param cep - CEP para busca (apenas números)
   */
  buscarCoordenadas: async (cep: string): Promise<{ lat: string, lng: string } | null> => {
    try {
      const cepLimpo = cep.replace(/\D/g, '');
      // Token fornecido pelo usuário
      const token = '9426cdf7a6f36931f5afba5a3c4e7bf29974fec6d2662ebcb6d7a1b237ffacdc';

      const response = await fetch(`https://cep.awesomeapi.com.br/json/${cepLimpo}?token=${token}`);

      if (!response.ok) {
        console.warn(`⚠️ Erro ao buscar coordenadas para CEP ${cep}: ${response.status}`);
        return null;
      }

      const data = await response.json();

      if (data && data.lat && data.lng) {
        return {
          lat: data.lat,
          lng: data.lng
        };
      }

      return null;
    } catch (error) {
      console.error('❌ Erro ao buscar coordenadas:', error);
      return null;
    }
  },

  /**
   * Realiza cotação de frete
   * @param dadosCotacao - Dados para cotação
   */
  cotacao: async (dadosCotacao: {
    empresaId: string;
    destino: {
      enderecoEntrega: string;
      numeroEntrega: string;
      bairroEntrega: string;
      cidadeEntrega: string;
      estadoEntrega: string;
      cepEntrega: string;
      paisEntrega: string;
      latitude: number;
      longitude: number;
    };
    origem?: { // Adicionando suporte opcional a origem, caso a API aceite
      latitude: number;
      longitude: number;
    }
  }): Promise<{ tipoFrete: string; valor: number; prazo?: string } | null> => {
    try {
      const token = localStorage.getItem('access_token');

      if (!token) {
        throw new Error('Token de autenticação não encontrado');
      }

      const fazerRequisicao = async (dados: any) => {
        return await fetch(`${BFF_BASE_URL}/entregas/cotacao`, {
          method: 'POST',
          headers: {
            'accept': 'application/json',
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`,
          },
          body: JSON.stringify(dados),
        });
      };

      let response = await fazerRequisicao(dadosCotacao);

      // Tratamento específico para erro de falta de coordenadas da empresa
      if (!response.ok) {
        let errorData;
        try {
          // Tenta clonar a resposta para não consumir o body se falhar
          errorData = await response.clone().json();
        } catch (e) {
          try {
            errorData = { detail: await response.clone().text() };
          } catch (e2) {
            errorData = { detail: "Erro ao ler corpo da resposta" };
          }
        }

        console.warn('⚠️ [Cotacao] Erro na primeira tentativa. Status:', response.status);
        console.warn('⚠️ [Cotacao] Payload do erro:', JSON.stringify(errorData, null, 2));

        // Converter tudo para string minúscula para facilitar a busca
        const errorString = JSON.stringify(errorData).toLowerCase();

        // Verificação super ampla: se mencionar latitude ou longitude, tenta recuperar
        if (errorString.includes("latitude") || errorString.includes("longitude")) {
          console.warn('⚠️ [Cotacao] Detectado erro de coordenadas (match amplo). Iniciando fluxo de recuperação...');

          // Importação dinâmica para evitar dependência circular se houver
          const { empresaApiService } = await import('./empresaApiService');

          // 1. Buscar dados da empresa para pegar o CEP
          console.log('1️⃣ [Cotacao] Buscando dados da empresa:', dadosCotacao.empresaId);
          const empresa = await empresaApiService.buscarPorId(dadosCotacao.empresaId);

          if (empresa && empresa.cep) {
            console.log('✅ [Cotacao] Empresa encontrada. CEP:', empresa.cep);

            // 2. Buscar coordenadas do CEP da empresa
            const coords = await entregasApiService.buscarCoordenadas(empresa.cep);

            if (coords) {
              console.log(`✅ [Cotacao] Coordenadas encontradas: ${coords.lat}, ${coords.lng}`);

              // 3. Tentar atualizar a empresa (melhor esforço)
              console.log('3️⃣ [Cotacao] Atualizando empresa com novas coordenadas...');

              // Converter para número conforme exemplo do usuário
              const latNum = parseFloat(coords.lat);
              const lngNum = parseFloat(coords.lng);

              const atualizou = await empresaApiService.atualizar(dadosCotacao.empresaId, {
                latitude: latNum as any, // Forçando number mesmo que a interface diga string, para testar se o backend aceita number
                longitude: lngNum as any
              });

              if (atualizou) {
                console.log('✅ [Cotacao] Empresa atualizada com sucesso.');

                // Pequeno delay para garantir que o backend processou a atualização
                await new Promise(resolve => setTimeout(resolve, 1000));
              } else {
                console.warn('⚠️ [Cotacao] Falha ao atualizar empresa, mas tentando cotação com origem explícita...');
              }

              // 4. Tentar cotação novamente, passando origem explícita
              const novosDados = {
                ...dadosCotacao,
                origem: {
                  latitude: latNum,
                  longitude: lngNum
                }
              };

              console.log('4️⃣ [Cotacao] Tentando cotação novamente com origem explícita...');
              response = await fazerRequisicao(novosDados);

              if (response.ok) {
                console.log('✅ [Cotacao] Segunda tentativa realizada com SUCESSO!');
              } else {
                const errorRetry = await response.json().catch(() => ({}));
                console.error('❌ [Cotacao] Segunda tentativa FALHOU:', response.status, errorRetry);
              }
            } else {
              console.error('❌ [Cotacao] Não foi possível obter coordenadas para o CEP:', empresa.cep);
            }
          } else {
            console.error('❌ [Cotacao] Empresa não encontrada ou sem CEP.');
          }
        } else {
          // Se não for o erro específico, logar e retornar null
          // Se não for o erro específico, mas tiver detalhe, lançar erro
          if (errorData && errorData.detail) {
            throw new Error(errorData.detail);
          }
          console.error(`❌ [Cotacao] Erro na cotação de frete (não recuperável): ${response.status}`, errorData);
          return null;
        }
      }

      if (!response.ok) {
        console.error(`❌ Erro na cotação de frete (após tentativa): ${response.status}`);
        return null;
      }

      const data = await response.json();
      return data;
    } catch (error) {
      console.error('❌ Erro ao realizar cotação:', error);
      return null;
    }
  }
};