import time
import os
import json
import psutil
import cpuinfo
from pathlib import Path 

class EcoTrace:
    def __init__(self, region_code="TR", carbon_limit=None):
        # JSON dosyasının yolunu bul (Modern ve hatasız yol)
        # Bu satır: "Şu anki dosyanın olduğu klasördeki data.json'ı bul" demek.
        base_path = Path(__file__).parent
        data_path = base_path / "data.json"

        try:
            with open(data_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
        except Exception as e:
            print(f"Uyari: data.json yuklenemedi. Hata: {e}")
            data = {}

        # (JSON'da yoksa içindeki yedeği kullan)
        self.TDP_MAP = data.get("TDP_MAP", {
            "i7-12": 125, "i5-11": 65, "Ryzen5": 65, "M1": 20, "M2": 22
        })
        
        self.CARBON_INTENSITY_MAP = data.get("CARBON_INTENSITY_MAP", {
            "TR": 475, "DE": 385, "FR": 55, "US": 367, "GB": 253, "DEFAULT": 475
        })

        # 3. Bölge Ayarları
        self.region_code = region_code.upper()
        self.region_factor = self.CARBON_INTENSITY_MAP.get(self.region_code, self.CARBON_INTENSITY_MAP.get("DEFAULT", 475))
        self.carbon_limit = carbon_limit

        # 4. Donanım Analizi (Çoklu Çekirdek ve CPU Modeli)
        self.total_cores = psutil.cpu_count(logical=True) or 1
        
        info = cpuinfo.get_cpu_info()
        cpu_brand = info.get('brand_raw', 'Unknown CPU')
        self.tdp = self.__getdynamic_tdp(cpu_brand)

        # 5. Log Dosyası Hazırlığı
        self.log_file = "ecotrace_log.csv"
        if not os.path.exists(self.log_file):
            with open(self.log_file, 'w', encoding='utf-8') as f:
                f.write("Function,Duration_Sec,Load_Factor,Carbon_g\n")

        # 6. Başlangıç Özeti (Ekrana havalı bir çıktı verelim)
        print(f"\n--- EcoTrace Baslatildi ---")
        print(f"Bolge: {self.region_code} ({self.region_factor} gCO2/kWh)")
        print(f"Cekirdek: {self.total_cores}")
        print(f"Islemci: {cpu_brand}")
        print(f"Tahmini TDP: {self.tdp}W")
        print(f"Veri Kaynagi: {'data.json' if data else 'Varsayilan (Fallback)'}")
        print(f"---------------------------\n")

    def __getdynamic_tdp(self, cpu_brand):
        # Artık global TDP_MAP yerine JSON'dan gelen self.TDP_MAP kullanılıyor
        for key, val in self.TDP_MAP.items():
            if key in cpu_brand:
                return val
        return 50 # Bulunamazsa yedek 50W

    def track(self, func):
        def wrapper(*args, **kwargs):
            process = psutil.Process(os.getpid())
            
            # Baslangic olcumleri
            start_cpu = process.cpu_times()
            start_time = time.perf_counter()

            # Gercek fonksiyonu calistir
            result = func(*args, **kwargs)

            # Bitis olcumleri
            end_time = time.perf_counter()
            end_cpu = process.cpu_times()

            # Hesaplamalar
            duration = end_time - start_time
            cpu_used_sec = (end_cpu.user - start_cpu.user) + (end_cpu.system - start_cpu.system)
            
            # Cekirdek bazli gercek islemci yuku
            total_capacity_sec = duration * self.total_cores
            load_factor = (cpu_used_sec / total_capacity_sec) if total_capacity_sec > 0 else 0
            
            # Enerji (Wh) ve Karbon (g)
            energy_wh = self.tdp * load_factor * (duration / 3600)
            carbon_gram = (energy_wh / 1000) * self.region_factor
            
            if self.carbon_limit and carbon_gram > self.carbon_limit:
                print("\033[91m" + "!!!" * 10)
                print(f"UYARI: KARBON LIMITI ASILDI! (Limit: {self.carbon_limit}g | Olculen: {carbon_gram:.6f}g)")
                print("!!!" * 10 + "\033[0m")

            # Sonuclari Bas
            print(f"\n--- [EcoTrace] '{func.__name__}' Sonuclari ---")
            print(f"Sure: {duration:.4f} sn | Yük: %{load_factor*100:.2f}")
            print(f"Karbon: {carbon_gram:.10f} g CO2")

            # CSV'ye Logla
            with open(self.log_file, 'a', encoding='utf-8') as f:
                f.write(f"{func.__name__},{duration:.6f},{load_factor:.4f},{carbon_gram:.10f}\n")

            return result
        return wrapper