import os
import json
import re
import time
import asyncio
import aiohttp

SHOP_LINK = "emde-b2b.myshopify.com"
API_VERSION = "2025-01"

# --- RateLimiter pour gérer la limite de 2 appels par seconde par token ---
class RateLimiter:
    def __init__(self, max_calls, period):
        self.max_calls = max_calls
        self.period = period
        self.calls = []
        self.lock = asyncio.Lock()

    async def acquire(self):
        async with self.lock:
            now = time.monotonic()
            # Nettoyer les appels trop anciens
            self.calls = [t for t in self.calls if now - t < self.period]
            if len(self.calls) >= self.max_calls:
                sleep_time = self.period - (now - self.calls[0])
                await asyncio.sleep(sleep_time)
                now = time.monotonic()
                self.calls = [t for t in self.calls if now - t < self.period]
            self.calls.append(now)

# --- Gestion des tokens et création des rate limiters par token ---
_tokens = None
_rate_limiters = {}

def load_tokens():
    global _tokens, _rate_limiters
    base_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
    tokens_file = os.path.join(base_dir, 'tokens.json')
    with open(tokens_file, 'r', encoding='utf-8') as f:
        _tokens = json.load(f)
    # Créer un rate limiter pour chaque token
    for key in _tokens.keys():
        _rate_limiters[key] = RateLimiter(max_calls=2, period=1.0)

def get_access_token(token_index=0):
    global _tokens
    if _tokens is None:
        load_tokens()
    token_keys = list(_tokens.keys())
    selected_key = token_keys[token_index % len(token_keys)]
    return _tokens[selected_key], selected_key

# --- Fonctions API asynchrones ---

async def create_customer(customer_data, token_index=0):
    access_token, token_key = get_access_token(token_index)
    await _rate_limiters[token_key].acquire()
    url = f"https://{SHOP_LINK}/admin/api/{API_VERSION}/customers.json"
    headers = {
        "Content-Type": "application/json",
        "X-Shopify-Access-Token": access_token
    }
    payload = json.dumps(customer_data)
    async with aiohttp.ClientSession() as session:
        try:
            async with session.post(url, headers=headers, data=payload) as response:
                response_text = await response.text()
                if response.status >= 400:
                    company_id = "Non défini"
                    tags = customer_data.get("customer", {}).get("tags", [])
                    if isinstance(tags, list):
                        for tag in tags:
                            if tag.startswith("Company Id:"):
                                company_id = tag.split(":", 1)[1].strip()
                                break
                    print("HTTP Error:", response.status, response_text)
                    return {"error": response_text, "companyId": company_id}
                print("Client créé avec succès.")
                return await response.json()
        except Exception as e:
            print("Exception during create_customer:", e)
    return None


async def update_customer(shopify_customer_id, updated_data, token_index=0):
    access_token, token_key = get_access_token(token_index)
    await _rate_limiters[token_key].acquire()
    url = f"https://{SHOP_LINK}/admin/api/{API_VERSION}/customers/{shopify_customer_id}.json"
    headers = {
        "Content-Type": "application/json",
        "X-Shopify-Access-Token": access_token
    }
    payload = json.dumps(updated_data)
    async with aiohttp.ClientSession() as session:
        try:
            async with session.put(url, headers=headers, data=payload) as response:
                response.raise_for_status()
                print(f"Client {shopify_customer_id} mis à jour avec succès.")
                return await response.json()
        except aiohttp.ClientResponseError as e:
            # On affiche directement le status et le message sans tenter d'accéder à e.response
            print("HTTP Error (PUT):", e.status, e.message)
        except Exception as e:
            print("Exception during update_customer:", e)
    return None


async def get_all_customers(token_index=0):
    access_token, token_key = get_access_token(token_index)
    await _rate_limiters[token_key].acquire()
    url = f"https://{SHOP_LINK}/admin/api/{API_VERSION}/customers.json?limit=250"
    headers = {
        "Content-Type": "application/json",
        "X-Shopify-Access-Token": access_token
    }
    customers = []
    async with aiohttp.ClientSession() as session:
        while url:
            await _rate_limiters[token_key].acquire()
            try:
                async with session.get(url, headers=headers) as response:
                    response.raise_for_status()
                    data = await response.json()
                    customers.extend(data.get("customers", []))
                    link_header = response.headers.get("Link")
                    if link_header:
                        match = re.search(r'<([^>]+)>;\s*rel="next"', link_header)
                        url = match.group(1) if match else None
                    else:
                        url = None
            except Exception as e:
                print("Exception during get_all_customers:", e)
                break
    return customers
