import os
import asyncio
from typing import Type, Optional, List, Dict, Any
from datetime import datetime, timedelta
from pydantic import BaseModel, Field
from langchain.tools import BaseTool, tool
from bs4 import BeautifulSoup
import requests
from bson import json_util
import json
from motor.motor_asyncio import AsyncIOMotorClient

from .config import get_config
from .db import get_collections, get_db_client

config = get_config()
MAX_HISTORY_LIMIT = config.get("MAX_HISTORY_LIMIT")

# Pydantic modelleri
class MongoChatHistoryToolInput(BaseModel):
    thread_id: str = Field(description="Hangi konuşma/oturum ID'sinin geçmişi çekilecek")
    limit: int = Field(default=10, description="Kaç mesaj getirileceği (max 200)")

class MongoDBToolInput(BaseModel):
    name: str = Field(default="all", description="Sorgu bilgisi. 'all' ile tüm kullanıcılar listelenir. 'alan:değer' ile filtrelenir.")

class WebAraToolInput(BaseModel):
    konu: str

class SiteIncelemeToolInput(BaseModel):
    url: str

# MongoDB sohbet geçmişi aracı
class MongoChatHistoryTool(BaseTool):
    name: str = "mongodb_sohbet_gecmisi"
    description: str = "MongoDB'den belirtilen thread_id için eski sohbet geçmişini getirir."
    args_schema: Type[BaseModel] = MongoChatHistoryToolInput

    async def _arun(self, thread_id: str, limit: int = 10) -> str:
        chat_col, _ = get_collections()
        limit = min(max(limit, 1), MAX_HISTORY_LIMIT)
        cursor = chat_col.find({"thread_id": thread_id}, projection={"_id": 0}).sort("timestamp", -1).limit(limit).max_time_ms(3000)
        docs = [doc async for doc in cursor]
        for d in docs:
            if "timestamp" in d and hasattr(d["timestamp"], "isoformat"):
                d["timestamp"] = d["timestamp"].isoformat()
        docs.reverse()
        return json.dumps(docs, ensure_ascii=False, indent=2)

# MongoDB kullanıcı sorgulama aracı
class MongoDBTool(BaseTool):
    name: str = "mongodb_kullanici_sorgula"
    description: str = "MongoDB'den belirtilen kritere göre kullanıcı sorgular."
    args_schema: Type[BaseModel] = MongoDBToolInput

    async def _arun(self, name: str = "all") -> str:
        _, users_col = get_collections()
        if not name or name.lower() in {"all", "hepsi", "tamamı"}:
            cursor = users_col.find({}, projection={"_id": 0}).max_time_ms(3000)
        elif ":" in name:
            field, value = map(str.strip, name.split(":", 1))
            cursor = users_col.find({field: value}, projection={"_id": 0}).max_time_ms(3000)
        else:
            cursor = users_col.find({"isim": name}, projection={"_id": 0}).max_time_ms(3000)
        data = [doc async for doc in cursor.limit(1000)]
        return json_util.dumps(data, ensure_ascii=False)

# Web arama aracı
class WebAraTool(BaseTool):
    name: str = "web_ara"
    description: str = "Verilen konu ile ilgili web araması yapar ve linkleri toplar."
    args_schema: type[BaseModel] = WebAraToolInput

    async def _arun(self, *, konu: str) -> list[dict]:
        try:
            url = f"https://www.google.com/search?q={konu}"
            headers = {"User-Agent": "Mozilla/5.0"}
            res = requests.get(url, headers=headers, timeout=5)
            soup = BeautifulSoup(res.text, "html.parser")
            results = []
            for item in soup.select("div.BNeawe.vvjwJb.AP7Wnd")[:5]:
                parent = item.find_parent("a")
                link = parent["href"] if parent else ""
                results.append({"title": item.get_text(), "link": link})
            if not results:
                return [{"title": "Sonuç bulunamadı", "link": ""}]
            return results
        except Exception as e:
            return [{"title": f"Hata: {e}", "link": ""}]

# Tarih aracı
@tool
async def tarih_ver(_: Optional[str] = None) -> str:
    ay_adlari = {1:"Ocak",2:"Şubat",3:"Mart",4:"Nisan",5:"Mayıs",6:"Haziran",7:"Temmuz",8:"Ağustos",9:"Eylül",10:"Ekim",11:"Kasım",12:"Aralık"}
    gun_adlari = {0:"Pazartesi",1:"Salı",2:"Çarşamba",3:"Perşembe",4:"Cuma",5:"Cumartesi",6:"Pazar"}
    simdi = datetime.now()

    def gun_bilgisi(t: datetime):
        return {
            "tarih": t.strftime("%d.%m.%Y %H:%M:%S"),
            "gun": gun_adlari[t.weekday()],
            "ay": ay_adlari[t.month],
            "yil": t.year,
        }

    sonuc = gun_bilgisi(simdi)
    sonuc.update({
        "dun": gun_bilgisi(simdi - timedelta(days=1)),
        "yarin": gun_bilgisi(simdi + timedelta(days=1))
    })
    return json.dumps(sonuc, ensure_ascii=False)