# core.py

import csv
import json
import os

import requests
import streamlit as st

from config import DEPOT_FICHES, ENV, GITEA_TOKEN, GITEA_URL, ORGANISATION
from utils.translations import _


def gitea_request(method, url, **kwargs):
    """Execute une requete HTTP vers l'API Gitea avec authentification automatique.

    Args:
        method: Methode HTTP (get, post, patch, delete, etc.).
        url: URL complete de l'endpoint API Gitea.
        **kwargs: Arguments passes a requests.request (params, data, json, etc.).

    Returns:
        requests.Response | None: Objet Response si succes, None si erreur.
    """
    headers = kwargs.pop("headers", {})
    headers["Authorization"] = f"token {GITEA_TOKEN}"
    try:
        response = requests.request(method, url, headers=headers, timeout=10, **kwargs)
        response.raise_for_status()
        return response
    except requests.RequestException as e:
        st.error(f"{str(_('errors.gitea_error'))} ({method.upper()}): {e}")
        return None


def charger_fiches_et_labels():
    """Charge la correspondance entre fiches et labels depuis le fichier CSV.

    Lit le fichier assets/fiches_labels.csv et construit un dictionnaire associant
    chaque fiche a ses labels (operations et item).

    Returns:
        dict: Dictionnaire au format {nom_fiche: {"operations": [str], "item": str}}.
              Retourne un dict vide en cas d'erreur.
    """
    chemin_csv = os.path.join("assets", "fiches_labels.csv")
    dictionnaire_fiches = {}

    try:
        with open(chemin_csv, encoding="utf-8") as fichier_csv:
            lecteur = csv.DictReader(fichier_csv)
            for ligne in lecteur:
                fiche = ligne.get("Fiche")
                operations = ligne.get("Label opération")
                item = ligne.get("Label item")

                if fiche and operations and item:
                    dictionnaire_fiches[fiche.strip()] = {
                        "operations": [op.strip() for op in operations.split("/")],
                        "item": item.strip()
                    }
    except FileNotFoundError:
        st.error(f"❌ {str(_('errors.file_not_found'))} {chemin_csv} {str(_('errors.is_missing'))}")
    except Exception as e:
        st.error(f"❌ {str(_('errors.file_loading'))} {str(e)}")

    return dictionnaire_fiches


def rechercher_tickets_gitea(fiche_selectionnee):
    """Recherche les tickets Gitea ouverts associes a une fiche specifique.

    Filtre les issues ouvertes du depot DEPOT_FICHES par branche (ENV) et par
    labels correspondant a la fiche selectionnee.

    Args:
        fiche_selectionnee: Nom de la fiche pour laquelle chercher les tickets.

    Returns:
        list[dict]: Liste des issues Gitea correspondantes (format JSON Gitea).
    """
    params = {"state": "open"}
    url = f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/issues"

    reponse = gitea_request("get", url, params=params)
    if not reponse:
        return []

    try:
        issues = reponse.json()
    except Exception as e:
        st.error(f"{str(_('errors.json_decode'))} {e}")
        return []

    correspondances = charger_fiches_et_labels()
    cible = correspondances.get(fiche_selectionnee)
    if not cible:
        return []

    labels_cibles = set([cible["item"]])
    tickets_associes = []

    for issue in issues:
        if issue.get("ref") != f"refs/heads/{ENV}":
            continue
        issue_labels = set(label.get("name", "") for label in issue.get("labels", []))
        if labels_cibles.issubset(issue_labels):
            tickets_associes.append(issue)

    return tickets_associes


def get_labels_existants():
    """Recupere tous les labels existants dans le depot Gitea.

    Returns:
        dict: Dictionnaire {nom_label: id_label}. Retourne un dict vide en cas d'erreur.
    """
    url = f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/labels"
    reponse = gitea_request("get", url)
    if not reponse:
        return {}

    try:
        return {label['name']: label['id'] for label in reponse.json()}
    except Exception as e:
        st.error(f"{str(_('errors.label_parsing'))} {e}")
        return {}


def nettoyer_labels(labels):
    """Nettoie et deduplique une liste de labels.

    Args:
        labels: Liste de labels (peut contenir des non-strings, espaces, doublons).

    Returns:
        list[str]: Liste triee de labels uniques et non vides.
    """
    return sorted(set(l.strip() for l in labels if isinstance(l, str) and l.strip()))


def construire_corps_ticket_markdown(reponses):
    """Construit le corps markdown d'un ticket a partir des reponses utilisateur.

    Args:
        reponses: Dictionnaire {nom_section: texte_reponse}.

    Returns:
        str: Corps du ticket en format markdown avec sections de niveau 2.
    """
    return "\n\n".join(f"## {section}\n{texte}" for section, texte in reponses.items())


def creer_ticket_gitea(titre, corps, labels):
    """Cree un nouveau ticket (issue) dans le depot Gitea.

    Args:
        titre: Titre du ticket.
        corps: Corps du ticket en markdown.
        labels: Liste d'IDs de labels a associer au ticket.

    Returns:
        bool: True si creation reussie, False sinon.
    """
    data = {
        "title": titre,
        "body": corps,
        "labels": labels,
        "ref": f"refs/heads/{ENV}"
    }
    url = f"{GITEA_URL}/repos/{ORGANISATION}/{DEPOT_FICHES}/issues"

    reponse = gitea_request("post", url, headers={"Content-Type": "application/json"}, data=json.dumps(data))
    if not reponse:
        return False
    return True
