from fastapi import APIRouter, Depends, HTTPException, Request, Body, Query
from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
from datetime import datetime, timezone
import uuid
import re
import os
import jwt
import asyncio
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

router = APIRouter(prefix="/news", tags=["News"])

def now_iso():
    return datetime.now(timezone.utc).isoformat()

security = HTTPBearer(auto_error=False)
JWT_SECRET = os.environ.get('JWT_SECRET', 'idg_forum_super_secret_key_2026')

async def get_current_user(request: Request, creds: HTTPAuthorizationCredentials = Depends(security)):
    if not creds:
        return None
    try:
        payload = jwt.decode(creds.credentials, JWT_SECRET, algorithms=["HS256"])
        user_id = payload.get("sub")
        if not user_id: return None
        db = request.app.state.db
        user = await db.users.find_one({"id": user_id})
        return user
    except Exception:
        return None

async def require_auth(user = Depends(get_current_user)):
    if not user:
        raise HTTPException(status_code=401, detail="Trebuie să fii autentificat.")
    return user

async def require_admin(user = Depends(require_auth)):
    if user.get("role") not in ["admin", "root"]:
        raise HTTPException(status_code=403, detail="Acces interzis. Doar staff-ul poate efectua această acțiune.")
    return user

class NewsCreateReq(BaseModel):
    title: str
    summary: str
    content: str
    category: str = "cs2_updates"  # cs2_updates, esports, community, tech, tournaments
    tags: Optional[List[str]] = []
    cover_image: Optional[str] = ""
    is_featured: Optional[bool] = False
    source_url: Optional[str] = ""
    source_name: Optional[str] = ""

class NewsUpdateReq(BaseModel):
    title: Optional[str] = None
    summary: Optional[str] = None
    content: Optional[str] = None
    category: Optional[str] = None
    tags: Optional[List[str]] = None
    cover_image: Optional[str] = None
    is_featured: Optional[bool] = None
    source_url: Optional[str] = None
    source_name: Optional[str] = None

class NewsCommentReq(BaseModel):
    content: str

def slugify(text: str) -> str:
    text = text.lower().strip()
    text = re.sub(r'[^\w\s-]', '', text)
    text = re.sub(r'[\s_-]+', '-', text)
    text = re.sub(r'^-+|-+$', '', text)
    return text or str(uuid.uuid4())[:8]

import urllib.request
import json
import html

def clean_steam_bbcode(text: str) -> (str, Optional[str]):
    """Convert Steam BBCode to clean Markdown and extract cover image."""
    cover_image = None
    
    # Check for Steam Clan image
    clan_img_match = re.search(r'\{STEAM_CLAN_IMAGE\}([\w\/\.]+)', text)
    if clan_img_match:
        cover_image = f"https://clan.fastly.steamstatic.com/images/{clan_img_match.group(1)}"
    elif re.search(r'https:\/\/[^\s"\']+\.(?:png|jpg|jpeg|webp)', text):
        img_match = re.search(r'(https:\/\/[^\s"\']+\.(?:png|jpg|jpeg|webp))', text)
        if img_match:
            cover_image = img_match.group(1)

    # Convert BBCode to Markdown
    text = re.sub(r'\{STEAM_CLAN_IMAGE\}', 'https://clan.fastly.steamstatic.com/images/', text)
    text = re.sub(r'\[h1\](.*?)\[/h1\]', r'# \1\n', text, flags=re.DOTALL)
    text = re.sub(r'\[h2\](.*?)\[/h2\]', r'## \1\n', text, flags=re.DOTALL)
    text = re.sub(r'\[h3\](.*?)\[/h3\]', r'### \1\n', text, flags=re.DOTALL)
    text = re.sub(r'\[b\](.*?)\[/b\]', r'**\1**', text, flags=re.DOTALL)
    text = re.sub(r'\[i\](.*?)\[/i\]', r'*\1*', text, flags=re.DOTALL)
    text = re.sub(r'\[u\](.*?)\[/u\]', r'_\1_', text, flags=re.DOTALL)
    text = re.sub(r'\[list\]', '', text)
    text = re.sub(r'\[/list\]', '', text)
    text = re.sub(r'\[\*\]', '• ', text)
    text = re.sub(r'\[url=(.*?)\](.*?)\[/url\]', r'[\2](\1)', text)
    text = re.sub(r'\[img\](.*?)\[/img\]', r'![](\1)', text)
    
    # Format line breaks
    text = re.sub(r'\\([A-Z])', r'\n\n### \1', text)
    text = html.unescape(text).strip()
    return text, cover_image

async def sync_steam_cs2_news(db) -> int:
    """Fetch live CS2 patch notes and news from Steam News Web API."""
    url = "https://api.steampowered.com/ISteamNews/GetNewsForApp/v0002/?appid=730&count=10&maxlength=4000&format=json"
    
    def _fetch():
        req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"})
        with urllib.request.urlopen(req, timeout=10) as r:
            return json.loads(r.read().decode("utf-8"))
            
    try:
        data = await asyncio.to_thread(_fetch)
        items = data.get("appnews", {}).get("newsitems", [])
        synced = 0
        
        fallback_covers = [
            "https://images.unsplash.com/photo-1542751371-adc38448a05e?auto=format&fit=crop&w=1200&q=80",
            "https://images.unsplash.com/photo-1538481199705-c710c4e965fc?auto=format&fit=crop&w=1200&q=80",
            "https://images.unsplash.com/photo-1511512578047-dfb367046420?auto=format&fit=crop&w=1200&q=80",
            "https://images.unsplash.com/photo-1550745165-9bc0b252726f?auto=format&fit=crop&w=1200&q=80"
        ]
        
        for item in items:
            gid = str(item.get("gid", ""))
            if not gid:
                continue
                
            exists = await db.idg_news.find_one({"$or": [{"source_id": gid}, {"title": item.get("title")}]})
            if exists:
                continue
                
            raw_content = item.get("contents", "")
            cleaned_md, cover_img = clean_steam_bbcode(raw_content)
            
            raw_title = item.get("title", "Counter-Strike 2 Update")
            # Format clean Romanian title and summary
            title = f"Valve Patch Notes: {raw_title}" if "Update" in raw_title else raw_title
            
            # Generate summary snippet
            first_lines = [line.strip() for line in cleaned_md.split("\n") if line.strip() and not line.startswith(("#", "!"))]
            summary_snippet = " ".join(first_lines[:3])[:280]
            summary = f"Actualizare oficială Counter-Strike 2 lansată de Valve. {summary_snippet}..." if summary_snippet else "Valve a publicat o nouă serie de modificări și optimizări pentru CS2."
            
            cover = cover_img or fallback_covers[synced % len(fallback_covers)]
            news_id = f"steam-cs2-{gid}"
            
            doc = {
                "id": news_id,
                "source_id": gid,
                "title": title,
                "slug": slugify(title) + f"-{gid[-6:]}",
                "summary": summary,
                "content": f"## Actualizare Oficială Counter-Strike 2\n\n{cleaned_md}\n\n---\n\n> [!NOTE]\n> *Știre preluată și sincronizată automat din fluxul oficial Valve Steam Community de către **INDUNGI @BOT**.*",
                "category": "cs2_updates",
                "tags": ["CS2", "Valve", "Patch Notes", "Steam", "Oficial"],
                "cover_image": cover,
                "is_featured": False,
                "views": 50,
                "likes": [],
                "author_id": "bot_indungi",
                "author_name": "INDUNGI @BOT",
                "author_avatar": "https://api.dicebear.com/7.x/bottts/svg?seed=IndungiBot&backgroundColor=0b0e14",
                "source_name": "Valve Steam Official",
                "source_url": item.get("url", "https://store.steampowered.com/news/app/730"),
                "created_at": datetime.fromtimestamp(item.get("date", int(datetime.now(timezone.utc).timestamp())), timezone.utc).isoformat(),
                "updated_at": now_iso()
            }
            
            await db.idg_news.insert_one(doc)
            synced += 1
            
        return synced
    except Exception as e:
        print("Error syncing Steam CS2 news:", e)
        return 0

# ----------------- SEED INITIAL NEWS IF EMPTY -----------------
async def seed_news_if_empty(db):
    count = await db.idg_news.count_documents({})
    if count > 0:
        return
        
    initial_articles = [
        {
            "id": "news-cs2-major-update-2026",
            "title": "Valve a lansat Noul Update CS2: Modificări Masive la Hărți și Tickrate Sub-tick",
            "slug": "valve-update-cs2-modificari-harti-subtick",
            "summary": "Valve a publicat un nou patch major pentru Counter-Strike 2 aducând optimizări esențiale de performanță, ajustări pe de_dust2 și de_inferno, precum și îmbunătățiri la înregistrarea gloanțelor.",
            "content": """## Modificări Generale și Performanță

Valve continuă perfecționarea motorului Source 2 pentru **Counter-Strike 2**. În cel mai recent pachet de actualizări, echipa de dezvoltare s-a concentrat pe feedback-ul comunității competitive.

### 🎮 Principalele Noutăți din Patch:
1. **Sistemul Sub-Tick & Hit Registration:**
   - A fost redus delay-ul la feedback-ul vizual și sonor la fiecare împușcătură.
   - Corecții majore la hitbox-urile în săritură și la deplasarea pe scări.

2. **Ajustări pe Hărți:**
   - **de_inferno:** Zona Banana a primit mici modificări de iluminare pentru a îmbunătăți vizibilitatea modelelor Terrorist.
   - **de_dust2:** Cutia de pe catwalk a fost ajustată pentru a preveni pixel-walking-ul.
   - **de_nuke:** Optimizare a reflexiilor de lumină pe rampa spre B.

3. **Optimizări FPS și Grafică:**
   - Reducerea utilizării VRAM cu până la 12% pe plăcile video din seria Nvidia RTX și AMD Radeon.
   - Corectarea crash-urilor ocazionale la comutarea rezoluțiilor 4:3 stretched.

---

> [!TIP]
> *Recomandarea Staff-ului INDUNGI:* Pentru o fluiditate maximă după acest update, adăugați `-novid +fps_max 0` în opțiunile de lansare Steam și actualizați driverul GPU!""",
            "category": "cs2_updates",
            "tags": ["CS2", "Valve", "Patch Notes", "Optimizare", "Update"],
            "cover_image": "https://images.unsplash.com/photo-1542751371-adc38448a05e?auto=format&fit=crop&w=1200&q=80",
            "is_featured": True,
            "views": 432,
            "likes": ["user-1", "user-2", "user-3"],
            "author_id": "bot_indungi",
            "author_name": "INDUNGI @BOT",
            "author_avatar": "https://api.dicebear.com/7.x/bottts/svg?seed=IndungiBot&backgroundColor=0b0e14",
            "source_name": "Valve Official CS Blog",
            "source_url": "https://www.counter-strike.net/news",
            "created_at": now_iso(),
            "updated_at": now_iso()
        },
        {
            "id": "news-indungi-championship-2026",
            "title": "Turneul Național INDUNGI 5v5 CS2: Înscrierile sunt Deschise!",
            "slug": "turneul-national-indungi-5v5-cs2-inscrieri",
            "summary": "Pregătește-ți echipa! Dăm startul înscrierilor pentru Cupa Comunității INDUNGI ROMANIA cu premii în bani, pachete VIP și grade exclusive de Campioni.",
            "content": """## Campionatul Comunității INDUNGI ROMANIA

Suntem mândri să anunțăm deschiderea oficială a înscrierilor pentru **Cupa INDUNGI 5v5**. Meciurile se vor juca pe serverele noastre oficiale de 128-tick protejate de noul sistem anti-cheat.

### 🏆 Premii & Beneficii:
- **Locul 1:** Premiu în bani + 1 An Statut VIP Gold pentru toată echipa + Banner personalizat pe forum.
- **Locul 2:** 6 Luni Statut VIP Silver + Ecusoane animate exclusive pe profil.
- **Locul 3:** 3 Luni Statut VIP Bronze + 15.000 Puncte de Comunitate.

### 📋 Regulament de Înscriere:
- Echipele trebuie să fie formate din minim 5 jucători titulari și 1 rezervă.
- Toți jucătorii trebuie să aibă cont activ pe forumul INDUNGI.
- Înscrierile se fac direct din tab-ul **CLANS & ECHIPE** sau la secțiunea dedicată din forum.""",
            "category": "esports",
            "tags": ["Turneu", "Campionat", "Esports", "INDUNGI", "Premii"],
            "cover_image": "https://images.unsplash.com/photo-1538481199705-c710c4e965fc?auto=format&fit=crop&w=1200&q=80",
            "is_featured": False,
            "views": 298,
            "likes": ["user-1"],
            "author_id": "bot_indungi",
            "author_name": "INDUNGI Staff",
            "author_avatar": "https://api.dicebear.com/7.x/bottts/svg?seed=Admin&backgroundColor=0b0e14",
            "source_name": "INDUNGI Events",
            "source_url": "",
            "created_at": now_iso(),
            "updated_at": now_iso()
        },
        {
            "id": "news-cs16-server-update",
            "title": "Upgrade Major pe Serverele [CS 1.6] NUMAI DD2 și Furien",
            "slug": "upgrade-major-servere-cs16-dd2-furien",
            "summary": "Performanță sporită, protecție anti-DDoS de 10Gbps și noi skin-uri exclusive adăugate pe serverele clasice ale comunității.",
            "content": """## Noutăți pe Servere Clasice CS 1.6

Comunitatea INDUNGI își respectă rădăcinile de legendă! Am finalizat migrarea serverelor noastre pe o nouă infrastructură hardware cu procesoare Ryzen de ultimă generație pentru un tickrate 1000 FPS impecabil.

### 🛡️ Îmbunătățiri pe Serverul NUMAI DD2 (`209.38.247.243:27015`):
- Ping scăzut la nivel național (sub 15ms pentru majoritatea furnizorilor).
- Sistem ReHLDS actualizat la cea mai nouă versiune stabilă.
- Anti-Cheat automatizat actualizat împotriva noilor tipuri de scripturi și alias-uri.
- Adăugate skin-uri VIP personalizate la cererea jucătorilor.""",
            "category": "community",
            "tags": ["CS 1.6", "Servere", "NUMAI DD2", "Furien", "Hardware"],
            "cover_image": "https://images.unsplash.com/photo-1551103782-8ab07afd45c1?auto=format&fit=crop&w=1200&q=80",
            "is_featured": False,
            "views": 185,
            "likes": [],
            "author_id": "bot_indungi",
            "author_name": "INDUNGI @BOT",
            "author_avatar": "https://api.dicebear.com/7.x/bottts/svg?seed=IndungiBot&backgroundColor=0b0e14",
            "source_name": "INDUNGI Server Staff",
            "source_url": "",
            "created_at": now_iso(),
            "updated_at": now_iso()
        }
    ]
    await db.idg_news.insert_many(initial_articles)

# ----------------- ENDPOINTS -----------------

@router.get("")
async def list_news(
    request: Request,
    category: Optional[str] = Query(None),
    tag: Optional[str] = Query(None),
    q: Optional[str] = Query(None),
    page: int = Query(1, ge=1),
    limit: int = Query(10, ge=1, le=50)
):
    db = request.app.state.db
    await seed_news_if_empty(db)
    
    query: Dict[str, Any] = {}
    if category and category != "all":
        query["category"] = category
    if tag:
        query["tags"] = {"$in": [tag]}
    if q:
        query["$or"] = [
            {"title": {"$regex": q, "$options": "i"}},
            {"summary": {"$regex": q, "$options": "i"}},
            {"tags": {"$in": [q]}}
        ]
        
    total = await db.idg_news.count_documents(query)
    skip = (page - 1) * limit
    
    cursor = db.idg_news.find(query, {"_id": 0}).sort("created_at", -1).skip(skip).limit(limit)
    items = await cursor.to_list(limit)
    
    return {
        "articles": items,
        "total": total,
        "page": page,
        "pages": (total + limit - 1) // limit,
        "limit": limit
    }

@router.get("/featured")
async def get_featured_news(request: Request):
    db = request.app.state.db
    await seed_news_if_empty(db)
    
    featured = await db.idg_news.find_one({"is_featured": True}, {"_id": 0})
    if not featured:
        featured = await db.idg_news.find_one({}, {"_id": 0}, sort=[("created_at", -1)])
        
    recent = await db.idg_news.find(
        {"id": {"$ne": featured.get("id") if featured else ""}},
        {"_id": 0}
    ).sort("created_at", -1).limit(4).to_list(4)
    
    return {
        "hero": featured,
        "recent": recent
    }

@router.get("/{id_or_slug}")
async def get_news_article(id_or_slug: str, request: Request):
    db = request.app.state.db
    await seed_news_if_empty(db)
    
    article = await db.idg_news.find_one(
        {"$or": [{"id": id_or_slug}, {"slug": id_or_slug}]},
        {"_id": 0}
    )
    if not article:
        raise HTTPException(status_code=404, detail="Articolul nu a fost găsit.")
        
    # Increment views
    await db.idg_news.update_one({"id": article["id"]}, {"$inc": {"views": 1}})
    article["views"] = article.get("views", 0) + 1
    
    # Related articles
    related = await db.idg_news.find(
        {"id": {"$ne": article["id"]}, "category": article.get("category")},
        {"_id": 0}
    ).limit(3).to_list(3)
    
    return {
        "article": article,
        "related": related
    }

@router.post("")
async def create_news(request: Request, body: NewsCreateReq, user = Depends(require_admin)):
    db = request.app.state.db
    
    slug = slugify(body.title)
    existing = await db.idg_news.find_one({"slug": slug})
    if existing:
        slug = f"{slug}-{str(uuid.uuid4())[:6]}"
        
    news_id = str(uuid.uuid4())
    doc = {
        "id": news_id,
        "title": body.title,
        "slug": slug,
        "summary": body.summary,
        "content": body.content,
        "category": body.category,
        "tags": body.tags or [],
        "cover_image": body.cover_image or "https://images.unsplash.com/photo-1542751371-adc38448a05e?auto=format&fit=crop&w=1200&q=80",
        "is_featured": body.is_featured or False,
        "views": 0,
        "likes": [],
        "author_id": user.get("id"),
        "author_name": user.get("username", "Admin Staff"),
        "author_avatar": user.get("avatar_url") or "https://api.dicebear.com/7.x/bottts/svg?seed=Staff",
        "source_name": body.source_name or "INDUNGI News",
        "source_url": body.source_url or "",
        "created_at": now_iso(),
        "updated_at": now_iso()
    }
    
    if body.is_featured:
        await db.idg_news.update_many({}, {"$set": {"is_featured": False}})
        
    await db.idg_news.insert_one(doc)
    doc.pop("_id", None)
    return doc

@router.patch("/{id}")
async def update_news(id: str, request: Request, body: NewsUpdateReq, user = Depends(require_admin)):
    db = request.app.state.db
    
    article = await db.idg_news.find_one({"id": id})
    if not article:
        raise HTTPException(status_code=404, detail="Articolul nu a fost găsit.")
        
    update_data = {k: v for k, v in body.model_dump(exclude_unset=True).items() if v is not None}
    update_data["updated_at"] = now_iso()
    
    if update_data.get("is_featured"):
        await db.idg_news.update_many({}, {"$set": {"is_featured": False}})
        
    await db.idg_news.update_one({"id": id}, {"$set": update_data})
    updated = await db.idg_news.find_one({"id": id}, {"_id": 0})
    return updated

@router.delete("/{id}")
async def delete_news(id: str, request: Request, user = Depends(require_admin)):
    db = request.app.state.db
    res = await db.idg_news.delete_one({"id": id})
    if res.deleted_count == 0:
        raise HTTPException(status_code=404, detail="Articolul nu a fost găsit.")
    await db.idg_news_comments.delete_many({"news_id": id})
    return {"message": "Articolul a fost șters cu succes."}

@router.post("/{id}/like")
async def toggle_like_news(id: str, request: Request, user = Depends(require_auth)):
    db = request.app.state.db
    article = await db.idg_news.find_one({"id": id})
    if not article:
        raise HTTPException(status_code=404, detail="Articolul nu a fost găsit.")
        
    likes = article.get("likes", [])
    uid = user["id"]
    if uid in likes:
        likes.remove(uid)
    else:
        likes.append(uid)
        
    await db.idg_news.update_one({"id": id}, {"$set": {"likes": likes}})
    return {"likes_count": len(likes), "user_liked": uid in likes}

@router.get("/{id}/comments")
async def get_comments(id: str, request: Request):
    db = request.app.state.db
    comments = await db.idg_news_comments.find({"news_id": id}, {"_id": 0}).sort("created_at", 1).to_list(100)
    return {"comments": comments}

@router.post("/{id}/comments")
async def add_comment(id: str, request: Request, body: NewsCommentReq, user = Depends(require_auth)):
    db = request.app.state.db
    article = await db.idg_news.find_one({"id": id})
    if not article:
        raise HTTPException(status_code=404, detail="Articolul nu a fost găsit.")
        
    comment_id = str(uuid.uuid4())
    doc = {
        "id": comment_id,
        "news_id": id,
        "user_id": user["id"],
        "username": user["username"],
        "user_avatar": user.get("avatar_url") or f"https://api.dicebear.com/7.x/bottts/svg?seed={user['username']}",
        "user_role": user.get("role", "user"),
        "vip_tier": user.get("vip_tier", "none"),
        "content": body.content.strip(),
        "created_at": now_iso()
    }
    await db.idg_news_comments.insert_one(doc)
    doc.pop("_id", None)
    return doc

@router.post("/sync-steam")
async def manual_sync_steam(request: Request, user = Depends(require_admin)):
    db = request.app.state.db
    synced_count = await sync_steam_cs2_news(db)
    return {"message": f"Sincronizare completă. S-au adăugat {synced_count} articole noi de la Valve Steam CS2.", "synced": synced_count}
