import os
import re
import requests
from datetime import datetime
from bs4 import BeautifulSoup
from newspaper import Article as NewspaperArticle
from newspaper import Config as NewspaperConfig
import ollama
from langdetect import detect
from difflib import SequenceMatcher
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Preformatted
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.pagesizes import letter
from concurrent.futures import ThreadPoolExecutor
import threading
import unicodedata
import zipfile
import io


# Configurare newspaper
config = NewspaperConfig()
config.browser_user_agent = 'Mozilla/5.0'
config.request_timeout = 20

# Surse suspecte
SURSE_FALS = ["clickbait.ro", "fake-news-site.com"]

# --- FUNCȚII UTILE ---

def remove_diacritics(text):
    return ''.join(
        c for c in unicodedata.normalize('NFKD', text) if not unicodedata.combining(c)
    )

def similaritate(a, b):
    return SequenceMatcher(None, a.lower(), b.lower()).ratio()

def traduce_en_ro(text):
    try:
        from argostranslate.package import update_package_index, install_from_path, get_available_packages
        from argostranslate.translate import translate as argo_translate

        update_package_index()
        available_pkgs = get_available_packages()
        pkg = next((p for p in available_pkgs if p.from_code == 'en' and p.to_code == 'ro'), None)
        if not pkg:
            raise Exception("Pachetul EN->RO nu este disponibil.")

        install_from_path(pkg.download())
        translated_text = argo_translate(text, from_code='en', to_code='ro')
        return remove_diacritics(translated_text)
    except Exception as e:
        print(f"[EROARE TRADUCERE] {e}")
        return "[Traducere indisponibilă]"

# --- FUNCȚII PRINCIPALE ---

def extrage_articol(url):
    try:
        article = NewspaperArticle(url, config=config)
        article.download()
        article.parse()

        headers = {'User-Agent': 'Mozilla/5.0'}
        r = requests.get(url, headers=headers, timeout=10)
        soup = BeautifulSoup(r.text, 'html.parser')

        data = None

        # Din meta tags obișnuiți
        for meta in soup.find_all('meta'):
            if 'name' in meta.attrs and meta.attrs['name'].lower() == 'date':
                data = meta.attrs.get('content')
            elif 'property' in meta.attrs and meta.attrs['property'] == 'article:published_time':
                data = meta.attrs.get('content')

        # Din URL
        if not data:
            match = re.search(r'(\d{4})[/-]?(\d{2})[/-]?(\d{2})', url)
            if match:
                year, month, day = match.groups()
                data = f"{year}-{month}-{day}"

        date_str = None
        if data:
            try:
                date_str = datetime.strptime(data[:10], "%Y-%m-%d").strftime("%Y%m%d")
            except:
                pass

        autor = None
        for byline in soup.select('.author, .byline, .author-name'):
            if byline:
                autor = byline.get_text().strip()
                break

        authors_clean = [a for a in article.authors if isinstance(a, str)]
        if not authors_clean and autor:
            authors_clean = [autor]
        if not authors_clean:
            authors_clean = ["Autor necunoscut"]

        return {
            "url": url,
            "title": article.title,
            "text": article.text,
            "authors": authors_clean,
            "publish_date": date_str,
            "lang": detect(article.text) if article.text else 'necunoscut'
        }

    except Exception as e:
        print(f"Eroare la extragere: {e}")
        return None


def genereaza_rezumat(text):
    prompt = f"Rezumă următorul articol în maxim 5 propoziții:\n\n{text[:2048]}"
    response = ollama.generate(model="llama3", prompt=prompt)
    return response["response"].strip()


def analiza_fact_check(text):
    prompt = f"""
Ai primit următorul articol. Analizează-l și răspunde doar cu un verdict între 0 și 100 despre cât de probabil este real, explicând foarte scurt de ce:
0 = Foarte probabil fals
100 = Foarte probabil real

Articol:
{text[:2048]}
"""
    response = ollama.generate(model="llama3", prompt=prompt)
    return response["response"].strip()


def calculeaza_scor(articol):
    scor_total = 50
    if len(articol["title"]) < 30 and "!" in articol["title"][-2:]:
        scor_total -= 15
    if not articol["authors"] or articol["authors"][0] == "Autor necunoscut":
        scor_total -= 10
    if articol["lang"] == "necunoscut":
        scor_total -= 10
    extracted = os.path.splitext(os.path.basename(articol["url"]))[0].split('.')
    domeniu = '.'.join(extracted[-2:])
    if domeniu in SURSE_FALS:
        scor_total -= 30
    scor_final = max(0, min(100, scor_total))
    return {"scor": scor_final, "verdict": 
           "Probabil real" if scor_final >= 75 else 
           "Necesită verificare suplimentară" if scor_final >= 50 else 
           "Probabil fals" if scor_final >= 25 else 
           "Foarte probabil fals"}

def extract_urls(content):
    """Extrage URL-urile din conținutul CSV"""
    url_pattern = re.compile(
        r'https?://(?:www\.)?(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(?:/[^\s"]*)?'
    )
    return list(set(url_pattern.findall(content)))


def cauta_in_gdelt_articol(articol, output_file="linkuri_similare.txt"):
    """
    Caută în arhiva GDELT pe data articolului.
    Returnează toate articolele similare și le salvează într-un fișier TXT.
    Rulează în paralel pentru viteză.
    """
    if not articol["publish_date"]:
        print("⚠️ Nu s-a putut determina data → nu se poate căuta în GDELT.")
        return []

    date_str = articol["publish_date"]
    filename_zip = f"{date_str}.export.CSV.zip"
    url_zip = f"http://data.gdeltproject.org/events/{filename_zip}"

    try:
        print(f"⬇️ Descărcăm arhiva GDELT pentru {date_str}...")
        response = requests.get(url_zip, timeout=30)
        if response.status_code != 200:
            print("❌ Fișierul GDELT nu există pentru această dată.")
            return []

        with zipfile.ZipFile(io.BytesIO(response.content)) as zip_ref:
            csv_name = zip_ref.namelist()[0]
            with zip_ref.open(csv_name) as csv_file:
                content = csv_file.read().decode('utf-8', errors='ignore')

        urls = extract_urls(content)
        print(f"🔍 Găsite {len(urls)} URL-uri în arhiva GDELT pentru această zi.")

        target_title = articol["title"]
        rezultate_similare = []

        def proceseaza_url(url):
            try:
                a = NewspaperArticle(url, config=config)
                a.download()
                a.parse()
                if not a.title:
                    return None
                score = similaritate(target_title, a.title.strip())
                if score > 0.6:
                    return {"url": url, "title": a.title.strip(), "score": score}
            except:
                return None

        MAX_THREADS = 20

        print(f"🔄 Se compară titlul nostru cu primele 100 URL-uri din GDELT...")

        with ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
            futures = [executor.submit(proceseaza_url, url) for url in urls[:100]]
            for future in futures:
                result = future.result()
                if result:
                    rezultate_similare.append(result)

        print(f"✅ Găsite {len(rezultate_similare)} potriviri în GDELT.")

        # Salvăm linkurile găsite
        with open(output_file, "w", encoding="utf-8") as f:
            f.write("🔗 Articole similare găsite în GDELT:\n")
            for item in rezultate_similare:
                f.write(f"- {item['url']} | Scor: {item['score']:.2f}\n")

        print(f"💾 Linkurile GDELT salvate în: {output_file}")
        return output_file

    except Exception as e:
        print(f"❌ Eroare la descărcarea arhivei GDELT: {e}")
        return []


def genereaza_raport_pdf(articol, rezumat_ai, verdict_ai):
    pdf_filename = f"raport_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf"
    doc = SimpleDocTemplate(pdf_filename, pagesize=letter)
    styles = getSampleStyleSheet()
    flowables = []

    flowables.append(Paragraph(remove_diacritics("Raport de Verificare al unei Stiri"), styles['Title']))
    flowables.append(Spacer(1, 12))

    flowables.append(Paragraph(f"<b>Titlu:</b> {remove_diacritics(articol['title'])}", styles['Normal']))
    flowables.append(Paragraph(f"<b>URL:</b> {articol['url']}", styles['Normal']))
    flowables.append(Paragraph(f"<b>Data publicării:</b> {articol['publish_date'] or 'Necunoscută'}", styles['Normal']))
    flowables.append(Paragraph(f"<b>Autor(i):</b> {', '.join(articol['authors'])}", styles['Normal']))
    flowables.append(Paragraph(f"<b>Limbă:</b> {articol['lang']}", styles['Normal']))

    flowables.append(Spacer(1, 12))
    flowables.append(Paragraph("<b>Rezumat (Original)</b>", styles['Heading2']))
    flowables.append(Paragraph(rezumat_ai, styles['Normal']))

    flowables.append(Spacer(1, 6))
    flowables.append(Paragraph("<b>Rezumat (Română)</b>", styles['Heading2']))
    rezumat_ro = traduce_en_ro(rezumat_ai)
    flowables.append(Paragraph(rezumat_ro, styles['Normal']))

    flowables.append(Spacer(1, 12))
    flowables.append(Paragraph("<b>Verdict AI (Original)</b>", styles['Heading2']))
    flowables.append(Paragraph(verdict_ai, styles['Normal']))

    flowables.append(Spacer(1, 6))
    flowables.append(Paragraph("<b>Verdict AI (Română)</b>", styles['Heading2']))
    verdict_ro = traduce_en_ro(verdict_ai)
    flowables.append(Paragraph(verdict_ro, styles['Normal']))

    scor_info = calculeaza_scor(articol)

    flowables.append(Spacer(1, 12))
    flowables.append(Paragraph(f"<b>Scor estimat:</b> {scor_info['scor']}%", styles['Normal']))
    flowables.append(Paragraph(f"<b>Verdict final:</b> {scor_info['verdict']}", styles['Normal']))

    doc.build(flowables)
    print(f"\n📄 Raportul inițial a fost salvat: {pdf_filename}")
    return pdf_filename


def calculeaza_scor(articol):
    scor_total = 50
    if len(articol["title"]) < 30 and "!" in articol["title"][-2:]:
        scor_total -= 15
    if not articol["authors"] or articol["authors"][0] == "Autor necunoscut":
        scor_total -= 10
    if articol["lang"] == "necunoscut":
        scor_total -= 10
    extracted = os.path.splitext(os.path.basename(articol["url"]))[0].split('.')
    domeniu = '.'.join(extracted[-2:])
    if domeniu in SURSE_FALS:
        scor_total -= 30
    scor_final = max(0, min(100, scor_total))
    return {"scor": scor_final, "verdict": 
           "Probabil real" if scor_final >= 75 else 
           "Necesită verificare suplimentară" if scor_final >= 50 else 
           "Probabil fals" if scor_final >= 25 else 
           "Foarte probabil fals"}


# --- MAIN ---
if __name__ == "__main__":
    url = input("Introduceți link-ul articolului: ")
    articol = extrage_articol(url)

    if not articol:
        print("❌ Nu s-a putut procesa articolul.")
    else:
        print("\n--- INFORMAȚII EXTRASE ---")
        print(f"Titlu: {articol['title']}")
        print(f"Autor(i): {', '.join(articol['authors'])}")
        print(f"Limbă detectată: {articol['lang']}")

        # Dacă nu avem data automat, întrebăm utilizatorul
        data_man = None
        if articol["publish_date"]:
            print(f"Data publicării: {articol['publish_date']}")
        else:
            data_input = input("📅 Introduceți data manual (YYYYMMDD) sau apăsați Enter pentru a ignora GDELT: ").strip()
            if data_input:
                try:
                    data_man = datetime.strptime(data_input, "%Y%m%d").strftime("%Y%m%d")
                    articol["publish_date"] = data_man
                except ValueError:
                    print("📅 Data introdusă nu este validă. Ignorăm GDELT.")

        print("\n--- REZUMAT AUTOMAT ---")
        rezumat = genereaza_rezumat(articol["text"])
        print(f"🔹 EN: {rezumat}")
        print(f"🔹 RO: {traduce_en_ro(rezumat)}")

        print("\n--- ANALIZĂ IA (LLM) ---")
        verdict_ai = analiza_fact_check(articol["text"])
        print(f"🔹 EN: {verdict_ai}")
        print(f"🔹 RO: {traduce_en_ro(verdict_ai)}")

        print("\n--- CALCUL SCOR GENERAL ---")
        scor_info = calculeaza_scor(articol)
        print(f"🔹 Scor: {scor_info['scor']}%")
        print(f"🔹 Verdict: {scor_info['verdict']}")

        print("\n--- GENERARE RAPORT PDF ---")
        raport_pdf = genereaza_raport_pdf(articol, rezumat, verdict_ai)

        print("\n--- CAUTARE ÎN FUNDAL ÎN GDELT ---")
        def ruleaza_cautare():
            txt_salvat = cauta_in_gdelt_articol(articol)
            print(f"📄 Linkurile GDELT sunt salvate în: {txt_salvat}")

        if articol["publish_date"]:
            gdelt_thread = threading.Thread(target=ruleaza_cautare, daemon=True)
            gdelt_thread.start()
        else:
            print("🚫 Cautarea în GDELT omisă (nu am determinat data)")

        print("\n📌 Acum poți folosi liber consola. Analiza GDELT continuă în fundal.")
