import requests
import traceback
import os
from dotenv import load_dotenv
from zenpy import Zenpy
from zenpy.lib.api_objects import CustomField, Ticket, Comment, User
from zenpy.lib.exception import APIException
from typing import Optional, Dict, Any, Iterable, List

load_dotenv()

# Reutilizando a sessão global se necessário
session = requests.Session()
session.verify = True

class Zendesk_Zenpy:
    """Destinada a facilitar as automações via zenpy na zendesk."""
    def __init__(self, instancia, zlogin=None, zpass=None):
        self.instancia = instancia
        self.zenpy_client = None
        if self.instancia == 'atendimentomagazineluiza':
            self.zlogin = zlogin or os.getenv('ZENPY_EMAIL')
            self.zpass = zpass or os.getenv('ZENPY_TOKEN')

        elif self.instancia == 'epocacosmeticos':
            self.zlogin = zlogin or os.getenv('ZENPY_EMAIL_EPOCA')
            self.zpass = zpass or os.getenv('ZENPY_TOKEN_EPOCA')

        self.auth_zenpy()


    def auth_zenpy(self):
        """Realiza a autenticação na API."""
        creds = {
            'email': self.zlogin,
            'token': self.zpass,
            'subdomain': self.instancia
        }
        try:
            print("Autenticando cliente Zenpy...")
            self.zenpy_client = Zenpy(session=session, **creds)
            print("Cliente Zenpy autenticado com sucesso.")
        except Exception as e:
            print(f"Erro na autenticação do Zenpy: {e}")

    def _zenpy_client(self):
        return self.zenpy_client
            
    def pegar_tickets(self, fila:int, minimo=1, invertido=False):
        """Captura todos os tickets dentro de uma visualização na zendesk.

        Args:
            fila (int): ID da visualização.
            minimo (int, optional): Minimo de casos que a visualização precisa para retornar. Padrão setado em 1.
            invertido (bool, optional): False para retornar os pedidos em ordem crescente, True para retornar os pedidos em ordem decrescente. Padrão setado em False.

        Returns:
            None em casos de erros ou quantidade minima não atingida. Lista com todos os tickets para caso de sucesso.
        """
        print('Verificando tickets na fila...')
        
        if not self.zenpy_client:
            print("Erro: Cliente Zenpy não foi autenticado. Verifique as credenciais.")
            return None
        
        todos_os_tickets = []
        try:
            for ticket in self.zenpy_client.views.tickets(view=fila):
                todos_os_tickets.append(ticket.id)
            if len(todos_os_tickets) >= minimo:
                print(f'A visualização conta com {len(todos_os_tickets)} tickets.')
                todos_os_tickets = sorted(todos_os_tickets, reverse=invertido)
                return todos_os_tickets
            else:
                print(f'A visualização não tem o minimo de tickets para inicializar. (Minimo: {minimo} Fila: {len(todos_os_tickets)})')
                return None
        except Exception as e:
            print(f"Erro ao buscar tickets: {str(e)}")
            return None
        
    def _valores_customfield(self, ticket: Any) -> Dict[int, Any]:
        
        if not hasattr(ticket, 'custom_fields') or not ticket.custom_fields:
            return {}

        field_objects: Iterable[Any]
        if hasattr(ticket.custom_fields, 'values'):
            field_objects = ticket.custom_fields.values()
        else:
            field_objects = ticket.custom_fields

        parsed_fields = {}
        for field in field_objects:
            field_id = None
            field_value = None

            if isinstance(field, dict):
                field_id = field.get('id')
                field_value = field.get('value')
            elif hasattr(field, 'id') and hasattr(field, 'value'):
                field_id = field.id
                field_value = field.value
            
            if field_id is not None:
                parsed_fields[field_id] = field_value
        
        return parsed_fields
    
    def extrair_customfields(self, ticket_id:int, lista_campos: Dict[str, int]) -> Optional[Dict[str, Any]]:
        try:
            ticket = self.zenpy_client.tickets(id=ticket_id)

            todos_os_valores = self._valores_customfield(ticket)

            resultado = {}
            for nome, id_campo in lista_campos.items():
                valor = todos_os_valores.get(id_campo)
                resultado[nome] = valor

            return resultado
        except APIException as e:
            print(f"Erro de API ao buscar ticket {ticket_id}: {e}")
            return None
        except Exception:
            print(f"Erro inesperado ao processar ticket {ticket_id}:")
            traceback.print_exc()
            return None