# Ubicación: src/App/services/business_central_service.py

import requests
import os
import time  # <--- 1. Importa el módulo 'time'
from dotenv import load_dotenv

# Cargar variables de entorno desde un archivo .env
load_dotenv()

class BusinessCentralService:
    def __init__(self):
        # --- Configuración Inicial ---
        self.tenant_id = os.getenv("BC_TENANT_ID", "b16d289b-fa4c-4578-accd-b308f19bbeb5")
        self.client_id = os.getenv("BC_CLIENT_ID", "9956717e-890f-4c61-864a-363ae9e025a9")
        self.client_secret = os.getenv("BC_CLIENT_SECRET", "yUT8Q~OZSBa5Dl9GJkoksoPAvzwwsfC2vHDQuadt")
        self.scope = "https://api.businesscentral.dynamics.com/.default"
        self.token_url = f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token"

        # --- URLs Base de la API ---
        self.company_id = "9eb89615-5f45-f011-be59-000d3a5efc08"
        self.environment = "IGSA-CRM-SB-Des"
        self.base_api_url = (
            f"https://api.businesscentral.dynamics.com/v2.0/{self.tenant_id}/"
            f"{self.environment}/api/IGSA/integration/v1.0/companies({self.company_id})"
        )
        self.base_web_api_url = (
            f"https://api.businesscentral.dynamics.com/v2.0/{self.tenant_id}/"
            f"{self.environment}/api/IGSA/Webintegration/v1.0/companies({self.company_id})"
        )
        
        # --- Variables para manejar el ciclo de vida del token ---
        self.access_token = None
        self.token_expiry_time = 0  # <--- 2. Guarda el tiempo de expiración (en segundos epoch)

    def get_token(self):
        """
        Obtiene un token de acceso válido, solicitando uno nuevo si el actual
        no existe o ha expirado.
        """
        # --- 3. Comprueba si el token existe Y si no ha expirado ---
        # Le damos un margen de 60 segundos por si acaso.
        if self.access_token and time.time() < self.token_expiry_time - 60:
            print("INFO: Reutilizando token existente.")
            return self.access_token

        print("INFO: Token no existe o ha expirado. Solicitando uno nuevo...")
        payload = {
            'grant_type': 'client_credentials',
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'scope': self.scope
        }
        response = requests.post(self.token_url, data=payload)
        response.raise_for_status()
        
        token_data = response.json()
        
        # --- 4. Guarda el nuevo token y calcula su tiempo de expiración ---
        self.access_token = token_data.get('access_token')
        expires_in_seconds = token_data.get('expires_in', 3600) # Duración en segundos
        self.token_expiry_time = time.time() + expires_in_seconds
        
        print("INFO: Nuevo token obtenido exitosamente.")
        return self.access_token

    def _make_request(self, method, url, **kwargs):
        """Método genérico para realizar solicitudes a la API."""
        token = self.get_token()
        headers = {
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }
        if 'headers' in kwargs:
            headers.update(kwargs['headers'])
        
        kwargs.pop('headers', None)

        try:
            response = requests.request(method, url, headers=headers, **kwargs)
            # Esto lanzará una excepción (HTTPError) para respuestas 4xx o 5xx
            response.raise_for_status()
            # Devuelve JSON si hay contenido, de lo contrario un string vacío (para respuestas 204)
            return response.json() if response.content else ""
        except requests.exceptions.HTTPError as err:
            # Es útil imprimir el error para depurar qué está fallando exactamente
            print(f"ERROR: Falló la solicitud HTTP: {err}")
            print(f"ERROR: Cuerpo de la respuesta: {err.response.text}")
            raise err # Vuelve a lanzar la excepción para que el controller la maneje

    # --- El resto de tus métodos (get_customers, create_item, etc.) permanecen igual ---
    # --- ... (no es necesario copiarlos de nuevo) ---
    def get_customers(self):
        url = f"{self.base_api_url}/customerImports"
        return self._make_request("GET", url)

    def create_customer(self, data):
        url = f"{self.base_api_url}/customerImports"
        return self._make_request("POST", url, json=data)

    def modify_customer(self, customer_id, data):
        url = f"{self.base_api_url}/customerImports({customer_id})"
        return self._make_request("PATCH", url, json=data, headers={'If-Match': '*'})

    def delete_customer(self, customer_id):
        url = f"{self.base_api_url}/customerImports({customer_id})"
        return self._make_request("DELETE", url, headers={'If-Match': '*'})
    
    def get_items(self):
        url = f"{self.base_api_url}/itemImports"
        return self._make_request("GET", url)
        
    def create_item(self, data):
        url = f"{self.base_api_url}/itemImports"
        return self._make_request("POST", url, json=data)

    def get_contacts(self):
        url = f"{self.base_api_url}/contactsImports"
        return self._make_request("GET", url)
        
    def get_salespersons(self):
        url = f"{self.base_api_url}/salespersonImports"
        return self._make_request("GET", url)

    def get_quote_lines(self):
        url = f"{self.base_api_url}/quoteImports"
        return self._make_request("GET", url)

    def create_quote(self, data):
        url = f"{self.base_api_url}/quoteImports"
        return self._make_request("POST", url, json=data)

    def delete_quote_line(self, system_id, quote_no, line_no):
        url = f"{self.base_api_url}/quoteImports({system_id},'{quote_no}',{line_no})"
        return self._make_request("DELETE", url, headers={'If-Match': '*'})
        
    def get_contact_buffer(self):
        url = f"{self.base_web_api_url}/contactsBuffer"
        return self._make_request("GET", url)

    def create_contact_buffer(self, data):
        url = f"{self.base_web_api_url}/contactsBuffer"
        return self._make_request("POST", url, json=data)

    def get_opportunities(self):
        url = f"{self.base_api_url}/opportunities"
        return self._make_request("GET", url)