import axios from "axios";

import { buildCommanderHeaders, resolveCommanderBaseUrl } from "./commanderHttp";

export type FechamentoTarefaItem = {
  id: string;
  fechamentoId: string;
  asanaTaskGid?: string | null;
  tipo: string;
  numeroTicket: string | null;
  descricao: string;
  cliente: string | null;
  linkAsana: string | null;
  etiquetas: { gid: string; name: string }[] | null;
  tempoMinutos: number | null;
  pontuacao: number;
  pontuacaoOriginal: number;
  estaRevisada: boolean;
  dataInicio: string | null;
  dataVencimento: string | null;
  dataConclusao: string | null;
  editadoEm: string | null;
  editadoPorId: string | null;
  criadoEm: string;
};

type ListarTarefasResponse = {
  data: FechamentoTarefaItem[];
};

type PatchTarefaResponse = {
  data: FechamentoTarefaItem;
};

type CriarLancamentoResponse = {
  data: FechamentoTarefaItem;
};

export type FechamentoFechadoResponse = {
  id: string;
  competenciaId: string;
  parceiroId: string;
  status: "fechado";
  versao: number;
  pontuacaoTotalEntregue: number;
  pontuacaoMeta: number;
  pontuacaoPaga: number;
  pontuacaoBanco: number;
  exportadoFinanceiro: boolean;
  fechadoPorId: string | null;
  fechadoEm: string | null;
  criadoEm: string;
  atualizadoEm: string;
};

export type FechamentoReabertoResponse = {
  id: string;
  competenciaId: string;
  parceiroId: string;
  status: "em_aberto";
  versao: number;
  pontuacaoTotalEntregue: number;
  pontuacaoMeta: number;
  pontuacaoPaga: number;
  pontuacaoBanco: number;
  exportadoFinanceiro: boolean;
  fechadoPorId: string | null;
  fechadoEm: string | null;
  criadoEm: string;
  atualizadoEm: string;
};

type ConcluirFechamentoResponse = {
  data: FechamentoFechadoResponse;
};

type ReabrirFechamentoResponse = {
  data: FechamentoReabertoResponse;
};

type ReprocessarAsanaResponse = {
  data: {
    fechamentoId: string;
    tarefasRecebidas: number;
    tarefasImportadas: number;
    tarefasIgnoradasSemParceiro: number;
    chamadasSubtarefasAsana: number;
  };
};

export type ExportarPlanilhaResponse = {
  buffer: ArrayBuffer;
  filename: string | null;
};

type ApiErrorShape = {
  error?: {
    message?: string;
  };
};

class FechamentoFechamentosService {
  private normalizeEtiquetas(
    value: FechamentoTarefaItem["etiquetas"] | undefined,
    tarefaId: string,
  ): { gid: string; name: string }[] | null {
    if (!Array.isArray(value) || value.length === 0) {
      return null;
    }
    const out: { gid: string; name: string }[] = [];
    for (let i = 0; i < value.length; i += 1) {
      const item = value[i];
      const name = typeof item?.name === "string" ? item.name.trim() : "";
      if (!name) continue;
      const gidRaw = typeof item?.gid === "string" ? item.gid.trim() : "";
      out.push({ gid: gidRaw || `${tarefaId}-etiqueta-${i}`, name });
    }
    return out.length > 0 ? out : null;
  }

  private extractFilenameFromContentDisposition(value: string | undefined): string | null {
    if (!value) return null;
    const utf8Match = value.match(/filename\*=UTF-8''([^;]+)/i);
    if (utf8Match?.[1]) {
      try {
        return decodeURIComponent(utf8Match[1]);
      } catch {
        return utf8Match[1];
      }
    }
    const regularMatch = value.match(/filename="?([^";]+)"?/i);
    return regularMatch?.[1] ?? null;
  }

  private handleAxiosError(error: unknown, fallback: string): never {
    if (axios.isAxiosError(error)) {
      if (!error.response) {
        throw new Error(
          "Não foi possível conectar na API do Commander. Verifique VITE_API_BASE_URL_COMMANDER e se o backend está acessível.",
        );
      }
      const message = ((error.response.data as ApiErrorShape | undefined)?.error?.message ??
        error.message ??
        fallback) as string;
      throw new Error(message);
    }
    throw new Error(fallback);
  }

  async listarTarefas(fechamentoId: string): Promise<FechamentoTarefaItem[]> {
    try {
      const headers = await buildCommanderHeaders();
      const baseUrl = resolveCommanderBaseUrl();
      const response = await axios.get<ListarTarefasResponse>(`${baseUrl}/fechamentos/${fechamentoId}/tarefas`, {
        headers,
      });
      const tarefas = response.data.data ?? [];
      return tarefas.map((tarefa) => ({
        ...tarefa,
        etiquetas: this.normalizeEtiquetas(tarefa.etiquetas, tarefa.id),
      }));
    } catch (error) {
      this.handleAxiosError(error, "Erro ao listar tarefas do fechamento.");
    }
  }

  async patchTarefa(
    fechamentoId: string,
    tarefaId: string,
    input: {
      estaRevisada?: boolean;
      pontuacao?: number;
      numeroTicket?: string | null;
      descricao?: string;
      cliente?: string | null;
      tempoMinutos?: number | null;
      editadoPorId: string;
    },
  ): Promise<FechamentoTarefaItem> {
    try {
      const headers = await buildCommanderHeaders();
      const baseUrl = resolveCommanderBaseUrl();
      const response = await axios.patch<PatchTarefaResponse>(
        `${baseUrl}/fechamentos/${fechamentoId}/tarefas/${tarefaId}`,
        {
          ...(input.estaRevisada !== undefined ? { esta_revisada: input.estaRevisada } : {}),
          ...(input.pontuacao !== undefined ? { pontuacao: input.pontuacao } : {}),
          ...(input.numeroTicket !== undefined ? { numero_ticket: input.numeroTicket } : {}),
          ...(input.descricao !== undefined ? { descricao: input.descricao } : {}),
          ...(input.cliente !== undefined ? { cliente: input.cliente } : {}),
          ...(input.tempoMinutos !== undefined ? { tempo_minutos: input.tempoMinutos } : {}),
          editado_por_id: input.editadoPorId,
        },
        { headers },
      );
      return response.data.data;
    } catch (error) {
      this.handleAxiosError(error, "Erro ao atualizar aprovação da tarefa.");
    }
  }

  async criarLancamento(
    fechamentoId: string,
    input: { tipo: "bonus" | "desconto"; descricao: string; pontuacao: number },
  ): Promise<FechamentoTarefaItem> {
    try {
      const headers = await buildCommanderHeaders();
      const baseUrl = resolveCommanderBaseUrl();
      const response = await axios.post<CriarLancamentoResponse>(
        `${baseUrl}/fechamentos/${fechamentoId}/tarefas`,
        {
          tipo: input.tipo,
          descricao: input.descricao,
          pontuacao: input.pontuacao,
        },
        { headers },
      );
      return response.data.data;
    } catch (error) {
      this.handleAxiosError(error, "Erro ao criar lançamento no fechamento.");
    }
  }

  async excluirLancamento(fechamentoId: string, tarefaId: string): Promise<FechamentoTarefaItem> {
    try {
      const headers = await buildCommanderHeaders();
      const baseUrl = resolveCommanderBaseUrl();
      const response = await axios.delete<PatchTarefaResponse>(
        `${baseUrl}/fechamentos/${fechamentoId}/tarefas/${tarefaId}`,
        { headers },
      );
      return response.data.data;
    } catch (error) {
      this.handleAxiosError(error, "Erro ao excluir lançamento.");
    }
  }

  async concluirFechamento(
    fechamentoId: string,
    input: { pontuacaoPaga: number; fechadoPorId?: string; motivoAjuste?: string },
  ): Promise<FechamentoFechadoResponse> {
    try {
      const headers = await buildCommanderHeaders();
      const baseUrl = resolveCommanderBaseUrl();
      const response = await axios.post<ConcluirFechamentoResponse>(
        `${baseUrl}/fechamentos/${fechamentoId}/concluir`,
        {
          pontuacao_paga: input.pontuacaoPaga,
          ...(input.fechadoPorId ? { fechado_por_id: input.fechadoPorId } : {}),
          ...(input.motivoAjuste?.trim() ? { motivo_ajuste: input.motivoAjuste.trim() } : {}),
        },
        { headers },
      );
      return response.data.data;
    } catch (error) {
      this.handleAxiosError(error, "Erro ao concluir fechamento.");
    }
  }

  async exportarPlanilha(fechamentoId: string): Promise<ExportarPlanilhaResponse> {
    try {
      const headers = await buildCommanderHeaders();
      const baseUrl = resolveCommanderBaseUrl();
      const response = await axios.get<ArrayBuffer>(`${baseUrl}/fechamentos/${fechamentoId}/exportar`, {
        headers,
        responseType: "arraybuffer",
      });
      return {
        buffer: response.data,
        filename: this.extractFilenameFromContentDisposition(response.headers["content-disposition"]),
      };
    } catch (error) {
      this.handleAxiosError(error, "Erro ao exportar planilha do fechamento.");
    }
  }

  async reabrirFechamento(
    fechamentoId: string,
    input: { reabertoPorId: string; motivo?: string },
  ): Promise<FechamentoReabertoResponse> {
    try {
      const headers = await buildCommanderHeaders();
      const baseUrl = resolveCommanderBaseUrl();
      const response = await axios.post<ReabrirFechamentoResponse>(
        `${baseUrl}/fechamentos/${fechamentoId}/reabrir`,
        {
          reaberto_por_id: input.reabertoPorId,
          ...(input.motivo?.trim() ? { motivo: input.motivo.trim() } : {}),
        },
        { headers },
      );
      return response.data.data;
    } catch (error) {
      this.handleAxiosError(error, "Erro ao reabrir fechamento.");
    }
  }

  async reprocessarAsana(fechamentoId: string): Promise<ReprocessarAsanaResponse["data"]> {
    try {
      const headers = await buildCommanderHeaders();
      const baseUrl = resolveCommanderBaseUrl();
      const response = await axios.post<ReprocessarAsanaResponse>(
        `${baseUrl}/fechamentos/${fechamentoId}/reprocessar-asana`,
        {},
        { headers },
      );
      return response.data.data;
    } catch (error) {
      this.handleAxiosError(error, "Erro ao reprocessar tarefas do Asana.");
    }
  }
}

export const fechamentoFechamentosService = new FechamentoFechamentosService();
