 # -*- coding: utf-8 -*-
import sys
import os
import csv
import re
import json
import requests
import urllib3
import shutil
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
from dotenv import load_dotenv
sys.stdout.reconfigure(encoding='utf-8')
load_dotenv()
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")


def init_driver_and_load_page(ean):
    try:
        options = Options()
        options.add_argument("--headless=new")
        options.add_argument("--disable-gpu")
        options.add_argument("--no-sandbox")
        options.add_argument("--disable-dev-shm-usage")
        options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
        options.add_experimental_option("excludeSwitches", ["enable-automation"])
        options.add_experimental_option('useAutomationExtension', False)

        driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
        driver.get(f"https://www.barcodelookup.com/{ean}")
        return driver
    except Exception as e:
        print(f"[!] Erreur ouverture page BarcodeLookup : {e}", file=sys.stderr)
        return None


# --------- Scraping BarcodeLookup ---------
def scrape_barcode_lookup(ean):
    driver = init_driver_and_load_page(ean)
    if not driver:
        return {"title": "", "image_url": "", "description": "", "mpn": "", "model": ""}

    try:
        wait = WebDriverWait(driver, 10)

        try:
            nom_produit = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "h4"))).text.strip()
        except:
            nom_produit = ""

        try:
            image_url = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#largeProductImage img"))).get_attribute("src")
        except:
            image_url = ""

        try:
             soup = BeautifulSoup(driver.page_source, 'html.parser')
    
    # 1. Récupérer tous les blocs de texte potentiels
             all_text_blocks = soup.find_all("span", class_="product-text")
    
             full_description = ""
             for block in all_text_blocks:
                 text = block.get_text(strip=True)
                 full_description += text + "\n"

             description = full_description.strip()
        except Exception as e:
             print(f"[DEBUG] Erreur parsing description : {e}", file=sys.stderr)
             description = ""

        mpn, model = "", ""
        try:
            soup = BeautifulSoup(driver.page_source, 'html.parser')
            specs = soup.find_all("li", class_="product-text")
            for item in specs:
                txt = item.get_text(strip=True)
                if txt.startswith("MPN:"):
                    mpn = txt.replace("MPN:", "").strip()
                elif txt.startswith("Model:"):
                    model = txt.replace("Model:", "").strip()
        except:
            pass

        driver.quit()
        return {
            "title": nom_produit,
            "image_url": image_url,
            "description": description,
            "mpn": mpn,
            "model": model
        }

    except Exception as e:
        print(f"[!] Erreur scraping : {e}", file=sys.stderr)
        driver.quit()
        return {"title": "", "image_url": "", "description": "", "mpn": "", "model": ""}
    


def detecter_compatibilite_cartouche(nom_produit, description_scrape, mpn="", modele=""):
    #print(f"[DEBUG] Appel detecter_compatibilite_cartouche avec mpn='{mpn}', modele='{modele}'")

    mots_cles_cartouche = ["toner", "epson", "cartouche", "encre", "drum", "ink", "hp", "dell"]
    is_cartouche = any(mot in nom_produit.lower() for mot in mots_cles_cartouche)

    if not is_cartouche:
        #print("[DEBUG] Produit non détecté comme cartouche.")
        return ""

    # Extraction depuis description (inchangé)
    pattern = re.compile(r'compatible printers:\s*(.+?)(?:\n\n|\Z)', re.IGNORECASE | re.DOTALL)
    match = pattern.search(description_scrape)
    if match:
        compatibles_text = match.group(1).strip()
        #print("Texte récupéré après 'compatible printers:' :")
        #print(compatibles_text)
        
        # On découpe sur points ou retours à la ligne (au cas où)
        models_raw = re.split(r'[.\n]', compatibles_text)

        def nettoyer_modele(m):
            return re.sub(r'\s+', ' ', m.strip())

        models = [nettoyer_modele(m) for m in models_raw if m.strip()]

        # Supprimer doublons en gardant l'ordre
        seen = set()
        models_clean = []
        for m in models:
            if m.lower() not in seen:
                seen.add(m.lower())
                models_clean.append(m)

        if models_clean:
            bloc = "**Compatibilité :**\n\n"
            bloc += "\n".join(f"- {m}" for m in models_clean)
            return bloc

    def nettoyer(val):
        return val.strip().lower().replace(" ", "").replace("-", "").replace("\r", "").replace("\u200b", "")

    try:
        #print(f"[DEBUG] Lecture CSV avec modèle/MPN = '{modele}' / '{mpn}'")
        with open("Toner2Printers.csv", encoding="cp1252") as f:
            headers = None
            for i, line in enumerate(f):
                line = line.strip().strip('"')  # Supprime guillemets entourant la ligne
                if not line:
                    continue
                fields = line.split('\t')
                if i == 0:
                    headers = fields
                    #print(f"[DEBUG] En-têtes CSV : {headers}")
                    continue

                ligne_nettoyee = nettoyer(" ".join(fields))
                modele_nettoye = nettoyer(modele)
                mpn_nettoye = nettoyer(mpn)

                if modele_nettoye in ligne_nettoyee or mpn_nettoye in ligne_nettoyee:
                    #print(f"[DEBUG] Contenu de la ligne entière : {fields}")

                    compatibilites = fields[4:]  # colonnes compatibilité
                    compatibilites = [c.strip() for c in compatibilites if c.strip()]
                    bloc = "**Compatibilité :**\n\n"
                    bloc += "\n".join(f"- {c}" for c in compatibilites)
                    print(f"[DEBUG] LIGNE TROUVÉE => Compatibilité détectée: {compatibilites}", file=sys.stderr)
                    return bloc

            print("[DEBUG] Aucune ligne correspondante trouvée dans le CSV." , file=sys.stderr)

    except Exception as e:
        print(f"[!] Erreur lecture CSV : {e}", file=sys.stderr)

    return ""


# --------- Génération description ---------
def generer_description_courte_longue(product_name, description_scrape="", brand="", mpn="", model=""):
    compatibilite_text = detecter_compatibilite_cartouche(product_name, description_scrape, mpn, model)
    include_compatibilite = bool(compatibilite_text)


    prompt = f"""
Tu es un expert en rédaction marketing spécialisé en e-commerce.

Voici les informations extraites d’un produit :

Nom : "{product_name}"  
Marque : "{brand}"  
Description brute : "{description_scrape}"

---

Objectif : Générer une fiche produit structurée et **strictement conforme** au format suivant :

---

### **Description courte :**  
- Résume en 1 ou 2 phrases ce qu’est le produit et pourquoi il est intéressant.  
- **Ne jamais copier ni reformuler la description longue.**  
- Le ton doit être vendeur, professionnel et clair.  
- Aucune mention de compatibilité.

---

### **Description longue :**

**Titre :**  
- Une phrase synthétique valorisant le produit.

**Phrase d’accroche :**  
- Une phrase marketing engageante, incitant à acheter.

**Description :**  
- Paragraphe détaillé expliquant le produit (fonctionnalité, utilité, avantages, public ciblé).  
- Contenu unique : ne pas dupliquer la description courte.  
- Apporter des précisions ou informations nouvelles.

**Points forts :**  
- Liste de 3 à 5 avantages **clairs, concrets et distincts**.  
- **Aucune mention de compatibilité, de modèles ou de références.**

**Conseils d’utilisation :**  
- Conseils pratiques ou recommandations d’usage.  
- **Pas de mention de compatibilité.**

**Caractéristiques :**  
- Liste synthétique avec des données précises (exemple : couleur, dimensions, poids, numéro de modèle, etc.).

- {compatibilite_text if include_compatibilite else ""}
 *(c’est-à-dire :  
   - Si et seulement si le produit est une cartouche, ajouter ici la mention sur la compatibilité.  
   - Sinon, ne jamais évoquer la compatibilité.)*

**Emballage :**  
- Décris succinctement ce que contient le pack ou l'emballage.

---

 Consignes strictes :
- Chaque section doit être unique, non redondante et autonome.

- Ne jamais dupliquer une phrase d’une section à l’autre.

- Les mots “compatible”, “compatibilité”, “convient à” sont strictement interdits hors de la section Caractéristiques et seulement si le produit est une cartouche.

- Le ton doit être toujours professionnel, vendeur, clair, fluide et précis.

- Respect strict de la structure et des intitulés de sections.

- Ne jamais ajouter de sections non demandées ni d’informations superflues.

"""

    url = "https://openrouter.ai/api/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer {OPENROUTER_API_KEY}",
        "Content-Type": "application/json",
    }
    data = {
        "model": "openai/gpt-3.5-turbo",
        "messages": [{"role": "user", "content": prompt}],
        "max_tokens": 500,
        "temperature": 0.3,
        "top_p": 0.9,
    }

    try:
        response = requests.post(url, headers=headers, json=data)
        if response.status_code == 200:
            return response.json()['choices'][0]['message']['content'].strip()
        else:
            print(f"[ERREUR OpenRouter] {response.status_code} : {response.text}", file=sys.stderr)
    except Exception as e:
        print(f"[ERREUR requête OpenRouter] : {e}", file=sys.stderr)

    return None


# --------- Parsing description ---------
def parse_descriptions(full_text):
    short_desc = ""
    long_desc = ""

    try:
        # On cherche les titres markdown exacts
        start_short = full_text.find("### **Description courte :**")
        start_long = full_text.find("### **Description longue :**")

        if start_short != -1 and start_long != -1:
            # extrait description courte entre start_short + len(titre) et start_long
            short_desc_raw = full_text[start_short + len("### **Description courte :**"):start_long].strip()
            # extrait description longue à partir de start_long + len(titre) jusqu'à la fin
            long_desc_raw = full_text[start_long + len("### **Description longue :**"):].strip()

            # Nettoyer la description courte : enlever séparateur --- s'il existe
            if '---' in short_desc_raw:
                short_desc_raw = short_desc_raw.split('---')[0].strip()

            # Pareil pour la description longue : enlever --- s'il existe à la fin
            if '---' in long_desc_raw:
                long_desc_raw = long_desc_raw.split('---')[0].strip()

            short_desc = short_desc_raw
            long_desc = long_desc_raw

        else:
            # Cas fallback, prendre les 200 premiers caractères comme courte
            short_desc = full_text.strip()[:200] + "..."
            long_desc = full_text.strip()
    except Exception as e:
        print(f"[!] Erreur lors du parsing des descriptions : {e}", file=sys.stderr)

    return short_desc, long_desc



# --------- Fonction principale ---------
def main(ean):
    product = scrape_barcode_lookup(ean)
    if not product or not product.get("title"):
        print(json.dumps({"error": "Produit introuvable."}, ensure_ascii=False))
        return

    product_name = product.get("title", "Nom non trouvé")
    image_url = product.get("image_url", "")
    description_scrape = product.get("description", "")
    mpn = product.get("mpn", "")
    model = product.get("model", "")

    contenu_genere = generer_description_courte_longue(product_name, description_scrape, mpn=mpn, model=model)

    if not contenu_genere:
        print(json.dumps({"error": "Erreur lors de la génération du contenu via Python."}, ensure_ascii=False))
        return

    description_courte, description_longue = parse_descriptions(contenu_genere)

    resultat = {
        "name": product_name,
        "description_short": description_courte,
        "description": description_longue,
        "image_url": image_url,
    }

    print(json.dumps(resultat, ensure_ascii=False))


# --------- Lancement ---------
if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(json.dumps({"error": "Pas d'EAN fourni en argument."}, ensure_ascii=False))
        sys.exit(1)

    ean_input = sys.argv[1].strip()
    main(ean_input)