import { GlobalFunctions, TransferAreaProperties } from '@/GlobalFunctions';
import { apiService } from './api';

export interface CreateOpinionResponse {
  success: boolean;
  id?: string;
  file_url?: string;
  file_url_melhoria?: string;
}

export interface CreateOpinionRequest {
  titulo: string;
  categoria: string;
  instrucoes: string;
  userEmail?: string;
  estabelecimentoId?: number;
}

export type OpinionStatus = 'processando' | 'concluido' | 'erro';

export interface OpinionRecord {
  id: string;
  estabelecimento_id: number;
  user_email: string;
  titulo: string;
  categoria: string;
  instrucoes: string;
  file_url: string;
  created_at: string;
  file_url_melhoria: string;
  status?: OpinionStatus;
  isLocalPending?: boolean;
}

export interface GetOpinionsParams {
  page?: number;
  per_page?: number;
  search?: string;
  userEmail?: string;
  estabelecimentoId?: number;
}

export interface GetOpinionsResponse {
  data: OpinionRecord[];
  total: number;
  page: number;
  per_page: number;
}

type ApiErrorShape = { message?: string; status?: number };

class AgentService {
  private readonly CREATE_ENDPOINT = '/webhook/codex/gepam/parecer-tecnico';
  private readonly OPINIONS_BASE = '/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex';

  private resolveUserContext(userEmail?: string, estabelecimentoId?: number) {
    const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
    const estabId = estabelecimentoId || GlobalFunctions.getTransferProperty(TransferAreaProperties.EstabelecimentoCodigo);
    return { email, estabId };
  }

  private assertUserContext(email: unknown, estabId: unknown) {
    if (!email) {
      throw { success: false, message: 'Email do usuário não fornecido' };
    }
    if (!estabId) {
      throw { success: false, message: 'ID do estabelecimento não fornecido' };
    }
  }

  private toApiError(error: unknown): never {
    const e = error as ApiErrorShape;
    throw {
      success: false,
      message: e?.message || 'Erro desconhecido',
      status: e?.status,
    };
  }

  async createOpinion(request: CreateOpinionRequest): Promise<CreateOpinionResponse> {
    const { titulo, categoria, instrucoes, userEmail, estabelecimentoId } = request;

    if (!titulo?.trim()) {
      throw { success: false, message: 'Título do parecer é obrigatório' };
    }

    if (!instrucoes?.trim()) {
      throw { success: false, message: 'Instruções são obrigatórias' };
    }

    const { email, estabId } = this.resolveUserContext(userEmail, estabelecimentoId);
    this.assertUserContext(email, estabId);

    try {
      const response = await apiService.post<CreateOpinionResponse>(
        this.CREATE_ENDPOINT,
        {
          user_email: email,
          estabelecimento_id: estabId,
          titulo: titulo.trim(),
          categoria: categoria.trim(),
          instrucoes: instrucoes.trim(),
        },
        { timeout: 600_000 }
      );

      return response.data;
    } catch (error: unknown) {
      console.error('Erro ao criar parecer:', error);
      this.toApiError(error);
    }
  }

  async getOpinions(params?: GetOpinionsParams): Promise<OpinionRecord[]> {
    const { page = 1, per_page = 10, search = '', userEmail, estabelecimentoId } = params || {};

    const { email, estabId } = this.resolveUserContext(userEmail, estabelecimentoId);
    this.assertUserContext(email, estabId);

    try {
      const url = `${this.OPINIONS_BASE}/get_parecer/${email}/${estabId}`;

      const response = await apiService.get<OpinionRecord[] | GetOpinionsResponse>(url, {
        params: { page, per_page, search },
      });

      const raw = response.data;

      if (Array.isArray(raw)) return raw;

      if (raw && typeof raw === 'object') {
        if (Array.isArray((raw as GetOpinionsResponse).data)) return (raw as GetOpinionsResponse).data;
        if (Array.isArray((raw as { opinions?: OpinionRecord[] }).opinions)) {
          return (raw as unknown as { opinions: OpinionRecord[] }).opinions;
        }
      }

      return [];
    } catch (error: unknown) {
      console.error('Erro ao buscar pareceres:', error);
      this.toApiError(error);
    }
  }

  async downloadOpinion(fileUrl: string, fileName: string): Promise<void> {
    if (!fileUrl) {
      throw { success: false, message: 'URL do arquivo não fornecida' };
    }

    const triggerDownload = (href: string) => {
      const link = document.createElement('a');
      link.href = href;
      link.download = fileName;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    };

    try {
      const response = await fetch(fileUrl, { method: 'GET', mode: 'cors', cache: 'no-cache' });

      if (!response.ok) {
        throw new Error(`Erro HTTP: ${response.status}`);
      }

      const blob = await response.blob();
      const blobUrl = URL.createObjectURL(blob);
      triggerDownload(blobUrl);
      URL.revokeObjectURL(blobUrl);
    } catch {
      const url = new URL(fileUrl);
      url.searchParams.set('response-content-disposition', `attachment; filename="${encodeURIComponent(fileName)}"`);
      triggerDownload(url.toString());
    }
  }

  async deleteOpinion(opinionId: string, userEmail?: string): Promise<{ success: boolean }> {
    if (!opinionId) {
      throw { success: false, message: 'ID do parecer não fornecido' };
    }

    const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);

    if (!email) {
      throw { success: false, message: 'Email do usuário não fornecido' };
    }

    try {
      const url = `${this.OPINIONS_BASE}/delete_parecer/${email}/${opinionId}`;
      const response = await apiService.delete<{ success: boolean }[]>(url);

      if (Array.isArray(response.data) && response.data.length > 0) {
        return response.data[0];
      }

      return { success: true };
    } catch (error: unknown) {
      console.error('Erro ao excluir parecer:', error);
      this.toApiError(error);
    }
  }
}

export const agentService = new AgentService();
