import json
from django.http import HttpResponse
from rest_framework.views import APIView
from rest_framework import status
from django.views.decorators.csrf import csrf_exempt
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
import pdfplumber
import requests
import csv
from langchain_groq import ChatGroq
from langchain_groq.chat_models import SystemMessage, HumanMessage
from nltk import download as nltk_download, word_tokenize
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from docx import Document
import openpyxl
from openai import OpenAI
from bs4 import BeautifulSoup
import logging
import os

API_KEY = os.environ.get('GROQ_API_KEY')
OPENAI_API_KEY = os.environ.get('OPENAI_API_KEY')

nltk_download('punkt')
nltk_download('wordnet')
nltk_download('stopwords')

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

def clean_text(text):
    tokens = word_tokenize(text.lower())
    stop_words = set(stopwords.words('french'))
    cleaned_tokens = [WordNetLemmatizer().lemmatize(token) for token in tokens if token.isalpha() and not token in stop_words]
    return ' '.join(cleaned_tokens)

def analyze_and_clean_url(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
    }
    response = requests.get(url, headers=headers)
    
    if response.status_code != 200:
        raise Exception(f"Erreur lors de l'accès à l'URL : {response.status_code}")

    soup = BeautifulSoup(response.content, 'html.parser')
    
    texts = soup.stripped_strings
    clean_text = ' '.join(texts)

    clean_text = clean_text.replace('\n', ' ').replace('\r', '')
    clean_text = ' '.join(clean_text.split())

    max_length = 5000
    if len(clean_text) > max_length:
        clean_text = clean_text[:max_length] + '...'

    return clean_text

def split_prompt(prompt, max_tokens):
    words = prompt.split()
    current_chunk = []
    chunks = []
    current_length = 0

    for word in words:
        if current_length + len(word) + 1 > max_tokens:
            chunks.append(" ".join(current_chunk))
            current_chunk = []
            current_length = 0
        current_chunk.append(word)
        current_length += len(word) + 1  # +1 pour l'espace

    if current_chunk:
        chunks.append(" ".join(current_chunk))

    return chunks

def truncate_conversation_history(conversation_history, max_tokens):
    while sum(len(message["content"]) for message in conversation_history) > max_tokens:
        conversation_history.pop(0)
    return conversation_history

class OpenAIView(APIView):
    def post(self, request, *args, **kwargs):
        try:
            prompt_user = request.POST.get('prompt')
            model_choice = request.POST.get('model_choice')
            formData = request.POST.copy()
            formData.pop('csrfmiddlewaretoken')
            file = request.FILES.get('file')
            url = formData.get('url')
            conversation_file = request.FILES.get('conversation_file')

            if not prompt_user and not conversation_file:
                return HttpResponse('<p>Erreur : Aucun prompt fourni.</p>', status=status.HTTP_400_BAD_REQUEST)

            # Réimporter la conversation à partir du fichier JSON téléchargé
            if conversation_file:
                conversation_history = json.load(conversation_file)
                request.session['conversation_history'] = conversation_history
                return HttpResponse("<div>Conversation réimportée avec succès.</div>", content_type="text/html")

            # Récupérer l'historique des messages de la session de l'utilisateur
            conversation_history = request.session.get('conversation_history', [])
            if prompt_user:
                conversation_history.append({"role": "user", "content": prompt_user})

            max_context_tokens = 5000  # Ajustez cette valeur selon la limite du modèle

            conversation_history = truncate_conversation_history(conversation_history, max_context_tokens - 500)  # Ajout d'une marge de sécurité

            request.session['conversation_history'] = conversation_history

            response_html = ""

            if model_choice == 'groq':
                if not API_KEY:
                    return HttpResponse('<p>Erreur : Clé API GROQ non définie.</p>', status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                headers = {'Authorization': f'Bearer {API_KEY}', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
                data = ''

                if file:
                    file_extension = file.name.split('.')[-1].lower()
                    if file_extension in ['pdf', 'txt', 'doc', 'docx', 'xls', 'xlsx', 'csv']:
                        file_path = default_storage.save(file.name, ContentFile(file.read()))
                        try:
                            if file_extension == 'pdf':
                                with pdfplumber.open(default_storage.path(file_path)) as pdf:
                                    data = '\n'.join(page.extract_text() for page in pdf.pages if page.extract_text())
                            elif file_extension == 'txt':
                                data = file.read().decode("utf-8")
                            elif file_extension in ['doc', 'docx']:
                                doc = Document(file)
                                for paragraph in doc.paragraphs:
                                    data += paragraph.text
                            elif file_extension in ['xls', 'xlsx']:
                                wb = openpyxl.load_workbook(file)
                                for sheet_name in wb.sheetnames:
                                    sheet = wb[sheet_name]
                                    for row in sheet.iter_rows(values_only=True):
                                        for cell in row:
                                            if cell:
                                                data += str(cell) + ' '
                            elif file_extension == 'csv':
                                with open(default_storage.path(file_path), newline='', encoding='utf-8') as csvfile:
                                    reader = csv.reader(csvfile)
                                    for row in reader:
                                        data += ' '.join(row) + ' '
                        finally:
                            default_storage.delete(file_path)
                    else:
                        return HttpResponse('<p>Erreur : Format de fichier non pris en charge.</p>', status=status.HTTP_400_BAD_REQUEST)

                elif url:
                    try:
                        data = analyze_and_clean_url(url)
                    except Exception as e:
                        return HttpResponse(f'<p>Erreur lors de l\'analyse de l\'URL fournie : {str(e)}</p>', status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                if data:
                    data = clean_text(data.replace('\n', ' ').replace('\r', ''))

                full_text = f"{prompt_user} {data}".strip()

                chat = ChatGroq(groq_api_key=API_KEY, model_name="llama3-8b-8192")
                system_message = SystemMessage(content="Tu es un assistant bienveillant, tu es là pour aider des personnes. Tu réponds toujours en français et utilises le contexte de la conversation puis tu réponds avec des titres, sous titres, liste avec des balises html...")
                human_message = HumanMessage(content=full_text)

                result = chat.invoke([system_message, human_message])

                response_html = (
                    f'<div class="user-response"><strong>✅  Votre demande :</strong> {prompt_user}</div>'
                    f'<div class="gpt-response"><strong>Résultat de l\'analyse IA Facile 👇 :</strong> {result.content}</div>'
                )

                return HttpResponse(response_html, content_type="text/html")

            elif model_choice == 'openai':
                if not OPENAI_API_KEY:
                    return HttpResponse('<p>Erreur : Clé API OpenAI non définie.</p>', status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                data = ''

                if file:
                    file_extension = file.name.split('.')[-1].lower()
                    if file_extension in ['pdf', 'txt', 'doc', 'docx', 'xls', 'xlsx', 'csv']:
                        file_path = default_storage.save(file.name, ContentFile(file.read()))
                        try:
                            if file_extension == 'pdf':
                                with pdfplumber.open(default_storage.path(file_path)) as pdf:
                                    data = '\n'.join(page.extract_text() for page in pdf.pages if page.extract_text())
                            elif file_extension == 'txt':
                                data = file.read().decode("utf-8")
                            elif file_extension in ['doc', 'docx']:
                                doc = Document(file)
                                for paragraph in doc.paragraphs:
                                    data += paragraph.text
                            elif file_extension in ['xls', 'xlsx']:
                                wb = openpyxl.load_workbook(file)
                                for sheet_name in wb.sheetnames:
                                    sheet = wb[sheet_name]
                                    for row in sheet.iter_rows(values_only=True):
                                        for cell in row:
                                            if cell:
                                                data += str(cell) + ' '
                            elif file_extension in ['csv']:
                                with open(default_storage.path(file_path), newline='', encoding='utf-8') as csvfile:
                                    reader = csv.reader(csvfile)
                                    for row in reader:
                                        data += ' '.join(row) + ' '
                        finally:
                            default_storage.delete(file_path)
                    else:
                        return HttpResponse('<p>Erreur : Format de fichier non pris en charge.</p>', status=status.HTTP_400_BAD_REQUEST)

                elif url:
                    try:
                        data = analyze_and_clean_url(url)
                    except Exception as e:
                        return HttpResponse(f'<p>Erreur lors de l\'analyse de l\'URL fournie : {str(e)}</p>', status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                if data:
                    data = clean_text(data.replace('\n', ' ').replace('\r', ''))

                full_text = f"{prompt_user} {data}".strip()

                client = OpenAI(api_key=OPENAI_API_KEY)

                try:
                    response_text = ""
                    chunks = split_prompt(full_text, 3000)

                    for chunk in chunks:
                        conversation_history.append({"role": "user", "content": chunk})
                        completion = client.chat.completions.create(
                            model="gpt-3.5-turbo",
                            messages=[
                                {"role": "system", "content": "Bonjour, je suis votre assistant GPT-3.5. Comment puis-je vous aider aujourd'hui ? tu réponds toujours en français et tu formates tes réponses en html avec liste,tableau, titre, sous titre éventuellement des couleurs pour des éléments importants."}
                            ] + conversation_history
                        )

                        if completion.choices:
                            assistant_response = completion.choices[0].message.content
                            response_text += assistant_response
                            conversation_history.append({"role": "assistant", "content": assistant_response})
                        else:
                            return HttpResponse("<div class='message assistant'>Aucune réponse de l'assistant.</div>", content_type="text/html")

                    request.session['conversation_history'] = conversation_history

                    response_html = (
                        f'<div class="user-response"><strong>✅Votre demande :</strong> {prompt_user}</div>'
                        f'<div class="gpt-response"><strong>📌  Réponse de l\'IA Facile 👇 :</strong> {response_text}</div>'
                    )

                    return HttpResponse(response_html, content_type="text/html")
                except Exception as e:
                    logger.error(f"Erreur lors du contact avec OpenAI : {str(e)}")
                    return HttpResponse(f"<div class='message error'>Erreur lors du contact avec OpenAI : {str(e)}</div>", status=500, content_type="text/html")
            else:
                return HttpResponse('<p>Erreur : Choix de modèle invalide.</p>', status=400, content_type="text/html")
        except Exception as e:
            logger.error(f"Erreur lors du traitement de la requête : {str(e)}")
            return HttpResponse(f"<div class='message error'>Erreur lors du traitement de la requête : {str(e)}</div>", status=500, content_type="text/html")

class ClearCacheView(APIView):
    @csrf_exempt
    def post(self, request, *args, **kwargs):
        try:
            request.session['conversation_history'] = []
            return HttpResponse('<div>Cache de la conversation vidé avec succès.</div>', content_type="text/html")
        except Exception as e:
            logger.error(f"Erreur lors du vidage du cache : {str(e)}")
            return HttpResponse(f"<div class='message error'>Erreur lors du vidage du cache : {str(e)}</div>", status=500, content_type="text/html")
