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

export type ImageSize = '1024x1024' | '1024x1792' | '1792x1024';

export interface ImageGenerationResponse {
  success: boolean;
  image_url?: string;
  image_generation_id?: string;
  message: string;
  code?: string;
}

export interface ImageRecord {
  id: string;
  user_email: string;
  estabelecimento_id: number;
  description: string;
  model: string;
  image_url: string;
  size: ImageSize;
  cost_usd: string;
  total_tokens: number;
  input_tokens: number;
  output_tokens: number;
  created_at: string;
}

export interface GetImagesResponse {
  images: ImageRecord[];
  total: number;
  page: number;
  per_page: number;
  total_pages: number;
}

export interface ImageGenerationRequest {
  description: string;
  size: ImageSize;
  userEmail?: string;
  estabelecimentoId?: number;
}

export const IMAGE_SIZE_OPTIONS = {
  '1024x1024': {
    label: 'Quadrado',
    dimensions: '1024x1024',
    aspectRatio: '1:1',
    description: 'Ideal para avatares, ícones e posts em redes sociais',
  },
  '1024x1792': {
    label: 'Retrato',
    dimensions: '1024x1792',
    aspectRatio: '9:16',
    description: 'Perfeito para stories, wallpapers verticais e reels',
  },
  '1792x1024': {
    label: 'Paisagem',
    dimensions: '1792x1024',
    aspectRatio: '16:9',
    description: 'Ótimo para banners, capas e thumbnails de vídeos',
  },
} as const;

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

class ImageGenerationService {
  private readonly IMAGE_GENERATION_ENDPOINT = '/webhook/codex/image_generator';
  private readonly GET_IMAGES_ENDPOINT = '/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/get_images';
  private readonly DELETE_IMAGE_ENDPOINT = '/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/delete_images';

  private resolveEmail(userEmail?: string): string {
    return userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
  }

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

  private extractArray<T>(data: unknown, keys: string[]): T[] {
    if (Array.isArray(data)) return data as T[];
    if (data && typeof data === 'object') {
      for (const key of keys) {
        const candidate = (data as Record<string, unknown>)[key];
        if (Array.isArray(candidate)) return candidate as T[];
      }
    }
    return [];
  }

  isValidSize(size: string): size is ImageSize {
    return Object.keys(IMAGE_SIZE_OPTIONS).includes(size);
  }

  getSizeInfo(size: ImageSize) {
    return IMAGE_SIZE_OPTIONS[size];
  }

  getAllSizes() {
    return Object.entries(IMAGE_SIZE_OPTIONS).map(([key, info]) => ({
      value: key as ImageSize,
      ...info,
    }));
  }

  validateDescription(description: string, minLength = 3, maxLength = 1000): { valid: boolean; error?: string } {
    if (!description?.trim()) return { valid: false, error: 'A descrição não pode estar vazia' };
    if (description.trim().length < minLength) return { valid: false, error: `A descrição deve ter pelo menos ${minLength} caracteres` };
    if (description.length > maxLength) return { valid: false, error: `A descrição é muito longa. Máximo: ${maxLength} caracteres` };
    return { valid: true };
  }

  async generateImage(request: ImageGenerationRequest): Promise<ImageGenerationResponse> {
    const { description, size } = request;

    if (!description?.trim()) {
      throw { success: false, message: 'A descrição não pode estar vazia' };
    }
    if (!this.isValidSize(size)) {
      throw { success: false, message: `Tamanho inválido. Opções disponíveis: ${Object.keys(IMAGE_SIZE_OPTIONS).join(', ')}` };
    }

    const email = GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
    const estabId = GlobalFunctions.getTransferProperty(TransferAreaProperties.EstabelecimentoCodigo);

    try {
      const response = await apiService.post<ImageGenerationResponse>(
        this.IMAGE_GENERATION_ENDPOINT,
        { estabelecimento_id: estabId, user_email: email, description, size }
      );

      if (!response.data.success) {
        throw { success: false, message: response.data.message || 'Erro ao gerar imagem', code: response.data.code };
      }

      return response.data;
    } catch (error: unknown) {
      const e = error as ApiErrorShape;
      if (e?.success === false && e?.message) throw error;
      console.error('Erro na geração de imagem:', error);
      this.toApiError(error, 'Erro ao gerar imagem. Tente novamente.');
    }
  }

  async downloadImage(imageUrl: string, filename?: string): Promise<void> {
    try {
      const response = await fetch(imageUrl);
      const blob = await response.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = filename || `imagem_${Date.now()}.png`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    } catch {
      throw new Error('Não foi possível baixar a imagem');
    }
  }

  async getImages(userEmail?: string, page = 1, perPage = 10): Promise<ImageRecord[]> {
    const email = this.resolveEmail(userEmail);

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

    try {
      const response = await apiService.get<unknown>(
        `${this.GET_IMAGES_ENDPOINT}/${email}`,
        { params: { page: page.toString(), per_page: perPage.toString() } }
      );
      return this.extractArray<ImageRecord>(response.data, ['images', 'data']);
    } catch (error: unknown) {
      console.error('Erro ao buscar imagens:', error);
      this.toApiError(error, 'Erro ao buscar imagens');
    }
  }

  async deleteImage(imageId: string, userEmail?: string): Promise<{ success: boolean; message?: string }> {
    const email = this.resolveEmail(userEmail);

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

    try {
      const response = await apiService.delete<{ success: boolean; message?: string } | Array<{ success: boolean; message?: string }>>(
        `${this.DELETE_IMAGE_ENDPOINT}/${email}/${imageId}`
      );
      const result = Array.isArray(response.data) ? response.data[0] : response.data;
      return { success: result.success ?? true, message: result.message || 'Imagem deletada com sucesso' };
    } catch (error: unknown) {
      console.error('Erro ao deletar imagem:', error);
      this.toApiError(error, 'Erro ao deletar imagem');
    }
  }
}

export const imageGenerationService = new ImageGenerationService();
