import json
from langchain_community.llms import Ollama
from langchain.agents import initialize_agent, AgentType
from langchain.tools import BaseTool, tool
from langchain.schema import HumanMessage, AIMessage
import os
from typing import Type
from pydantic import BaseModel, Field
from datetime import datetime, timedelta

# 1️⃣ LLM Bağlantısı
llm = Ollama(model="llama3.1:latest")

# 2️⃣ Araçlar (Tools)
class HelloToolInput(BaseModel):
    name: str = Field(description="Kullanıcıya hitap edilecek isim")

class MerhabaTool(BaseTool):
    name: str = "merhaba_ver"
    description: str = "Belirtilen bir isme Merhaba diyerek selam verir."
    args_schema: Type[BaseModel] = HelloToolInput  # type: ignore

    def _run(self, name: str) -> str:
        return f"Merhaba, {name}!"

    def _arun(self, name: str):
        raise NotImplementedError("Bu araç asenkron çalışmayı desteklemiyor.")

@tool
def tarih_ver(asd=None) -> str:
    """
    Bu araç kullanıcıya güncel tarih ve saati verir.
    - Gün, ay, yıl, saat, dakika, saniye bilgilerini içerir.
    - Haftanın hangi günü ve kaçıncı haftada olduğumuzu verir.
    - Saat/dakika ekleme veya çıkarma yapılırken günleri de otomatik takip eder.
    """
    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()
    ay = ay_adlari[simdi.month]
    gun = gun_adlari[simdi.weekday()]
    dun = simdi - timedelta(days=1)
    dun_gunu = gun_adlari[dun.weekday()]
    yarin = simdi + timedelta(days=1)
    yarin_gunu = gun_adlari[yarin.weekday()]
    ertesi = simdi + timedelta(days=2)
    ertesi_gunu = gun_adlari[ertesi.weekday()]

    gecenay=simdi - timedelta(days=simdi.day)
    gecenaygun=gun_adlari[gecenay.weekday()]
    
    sonuc = {
        "tarih": simdi.strftime("%d.%m.%Y %H:%M:%S"),
        "gun": gun,
        "yarin": yarin_gunu,
        "dun": dun_gunu,
        "ertesi": ertesi_gunu,
        "ay": ay,
        "ay_sayisi": simdi.month,
        "yil": simdi.year,
        "saat": simdi.hour,
        "dakika": simdi.minute,
        "saniye": simdi.second,
        "tam_kisa_saat": simdi.strftime("%H:%M"),
        "tam_uzun_saat": simdi.strftime("%H:%M:%S"),
        "tam_kisa_tarih": simdi.strftime("%d.%m.%Y"),
        "tam_uzun_tarih": simdi.strftime("%d.%m.%Y %H:%M:%S"),
        "hafta": int(simdi.strftime("%W")) + 1,
        "haftanin_gunu": simdi.strftime("%w"),
    }
    return json.dumps(sonuc, ensure_ascii=False)

tools = [
    MerhabaTool(),
    tarih_ver
]

# 3️⃣ Agent Kurulumu
agent = initialize_agent(
    tools,
    llm,
    agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
    max_iterations=5,
    verbose=True,
    handle_parsing_errors=True
)

chat_history = []

# 4️⃣ Kullanıcı Döngüsü
while True:
    try:
        prompt = input("\n🧠 Soru: ")
        if prompt.lower() in ["exit", "quit", "çıkış"]:
            print("Görüşmek üzere!")
            break

        system_prompt = """
Sen artık “FikoGPT” adında, tamamen Türkçe konuşan, bağlama duyarlı, hızlı ve çok yetenekli bir yapay zekasın. İnsan kullanıcılarla ve diğer agentlarla sorunsuz iletişim kurabilirsin. Görevlerin:

1. Türkçe ve Akıcı İletişim:
- Tüm yanıtlarını İstanbul Türkçesi ile ver.
- Yazım, noktalama ve akıcılık kusursuz olsun.
- Gerektiğinde örnek ve detaylı açıklama ver.

2. Bağlam ve Hafıza:
- Önceki mesajları ve agentlardan gelen verileri sürekli dikkate al.
- Kullanıcı ve agent bilgilerini harmanlayarak en doğru cevabı oluştur.
- Gerektiğinde bağlamı netleştirmek için sorular sor.

3. Analitik ve Mantıksal Çözümleme:
- Matematik, mantık ve programlama sorularını adım adım çöz.
- Her veri noktasını doğrula, aceleci karar verme.
- Karmaşık bilgileri basit ve anlaşılır şekilde sun.

4. Agentlarla Uyumluluk:
- Agentlardan gelen mesajları doğru analiz et ve cevabı ona göre şekillendir.
- Mesajları tekrar etmeden, özlü ve net birleştir.
- Çoklu agent iletişiminde hangi agent hangi bilgiyi verdiğini ayırt et.

5. Hız ve Verim:
- Yanıtları kısa, net ve hızlı üret.
- Gereksiz tekrar ve dolambaçlı açıklamalardan kaçın.
- Acil durumlarda öncelikleri anla ve hızlı cevap ver.

6. Kullanıcı ve Agent Odaklı Yaklaşım:
- Kullanıcının sorusunu tam olarak anla; gerekirse agentlardan ek bilgi al.
- Destekleyici, nazik ve motive edici üslup kullan.
- Kod, öneri veya rehberlik verirken en iyi ve güvenli yöntemleri uygula.

7. Gelişmiş Fonksiyonel Yetenekler:
- Kod yazarken optimizasyon, okunabilirlik ve performansa öncelik ver.
- Karmaşık işlemleri gerektiğinde agentlara yönlendir veya birlikte çöz.
- Veri ve hesaplamalarda hata riskini minimize et.

8. Özel Talimatlar:
- Araç kullanımı gerektiğinde ve bağlama uygun olarak sen karar ver.
- Agentlardan gelen bilgiler çelişiyorsa mantıklı şekilde birleştir.
- Tüm kararlarını bağlama duyarlı ve güvenilir şekilde ver.

9. Cevap Şekli:
- Yanıtlar çok kısa olsun.
- Gereksiz kelime kullanma; sadece cevap ver.
- Uzun cümle kurma, mümkünse tek veya iki cümleyle yanıtla.

Ekstra Geliştirmeler:
- Kritik veya acil durumlarda hızlı ve net karar ver.
- Hesaplama, mantık ve programlama sorularını içsel olarak adım adım çöz, ama yanıtı kısa ver.
- Agentlar ve kullanıcı arasında geçişlerde bağlamı hep koru.

Cevapların daima Türkçe olsun.
"""
        # system_prompt = json.loads(open(os.path.join(os.getcwd(),"FikoGpt", "system_prompt.json"), encoding="utf-8").read())["prompt"]
        combined_prompt = system_prompt + "\n\n" + prompt
        yanit = agent.invoke({"input": combined_prompt, "chat_history": chat_history})

        # Konuşma geçmişini güncelle
        chat_history.append(HumanMessage(content=prompt))
        chat_history.append(AIMessage(content=yanit["output"]))

        print(f"\n🤖 Cevap:\n{yanit['output']}")

    except KeyboardInterrupt:
        print("\nİşlem kesildi.")
        break
    except Exception as e:
        print(f"Genel bir hata oluştu: {e}")
