import os
import json
import time
import psutil
import cpuinfo
import csv
from datetime import datetime
from fpdf import FPDF

class EcoTrace:
    def __init__(self, region_code="TR", carbon_limit=None):
        self.region_code = region_code
        self.carbon_limit = carbon_limit
        self.total_carbon = 0.0
        
        self.base_dir = os.path.dirname(os.path.abspath(__file__))
        self.json_path = os.path.join(self.base_dir, "constants.json")
        self.csv_path = os.path.join(self.base_dir, "cpu_data.csv") 

        self.tdp_db = self._load_tdp_database() 
        self.carbon_intensity = self._get_carbon_intensity()
        self.cpu_info = self._get_cpu_info()

        print("\n--- EcoTrace Baslatildi ---")
        print(f"Bolge: {self.region_code} ({self.carbon_intensity} gCO2/kWh)")
        print(f"Islemci: {self.cpu_info['brand']}")
        print(f"Cekirdek: {self.cpu_info['cores']}")
        print(f"Bulunan TDP: {self.cpu_info['tdp']}W")
        print("---------------------------\n")

    def generate_pdf_report(self, filename="ecotrace_full_report.pdf"):
        """Cihaz bilgilerini ve tum olcum gecmisini detayli raporlar."""
        try:
            def fix_tr(text):
                tr_map = str.maketrans("çğıöşüÇĞİÖŞÜ", "cgiosuCGIOSU")
                return str(text).translate(tr_map)

            history = []
            log_file = "ecotrace_log.csv"
            if os.path.exists(log_file):
                with open(log_file, mode='r', encoding='utf-8') as f:
                    reader = csv.reader(f)
                    next(reader) 
                    for row in reader:
                        if len(row) >= 5: # Tarih, Fonk, Sure, Karbon, Bolge
                            history.append([fix_tr(item) for item in row])
            
            pdf = FPDF()
            pdf.add_page()
            
            # --- 1. BOLUM: BASLIK ---
            pdf.set_font("helvetica", 'B', 20)
            pdf.set_text_color(46, 139, 87)
            pdf.cell(200, 15, txt="EcoTrace Analiz Raporu", ln=True, align='C')
            pdf.ln(5)

            # --- 2. BOLUM: CIHAZ VE SISTEM BILGILERI ---
            pdf.set_fill_color(245, 245, 245)
            pdf.set_font("helvetica", 'B', 12)
            pdf.set_text_color(0, 0, 0)
            pdf.cell(0, 10, txt=fix_tr(" Sistem Ozellikleri"), ln=True, fill=True)
            
            pdf.set_font("helvetica", size=10)
            pdf.cell(100, 8, txt=fix_tr(f"Islemci: {self.cpu_info['brand']}"), ln=False)
            pdf.cell(100, 8, txt=fix_tr(f"Cekirdek Sayisi: {self.cpu_info['cores']}"), ln=True)
            pdf.cell(100, 8, txt=fix_tr(f"Tespit Edilen TDP: {self.cpu_info['tdp']}W"), ln=False)
            pdf.cell(100, 8, txt=fix_tr(f"Aktif Bolge: {self.region_code}"), ln=True)
            pdf.ln(10)

            # --- 3. BOLUM: DETAYLI TABLO ---
            pdf.set_font("helvetica", 'B', 12)
            pdf.cell(0, 10, txt=fix_tr(" Islem Gecmisi"), ln=True, fill=True)
            pdf.ln(2)

            # Tablo Basliklari (Genislikler ayarlandi)
            pdf.set_font("helvetica", 'B', 9)
            pdf.set_fill_color(200, 220, 200)
            pdf.cell(40, 10, "Tarih", border=1, fill=True)
            pdf.cell(50, 10, "Fonksiyon", border=1, fill=True)
            pdf.cell(25, 10, "Sure(sn)", border=1, fill=True)
            pdf.cell(45, 10, "Karbon(gCO2)", border=1, fill=True)
            pdf.cell(30, 10, "Bolge", border=1, fill=True, ln=True)

            # Veriler
            pdf.set_font("helvetica", size=8)
            total_sum = 0.0
            for row in history:
                pdf.cell(40, 8, row[0], border=1)
                pdf.cell(50, 8, row[1], border=1)
                pdf.cell(25, 8, row[2], border=1)
                pdf.cell(45, 8, row[3], border=1)
                pdf.cell(30, 8, row[4], border=1, ln=True)
                try: total_sum += float(row[3])
                except: pass

            # --- 4. BOLUM: OZET ---
            pdf.ln(10)
            pdf.set_font("helvetica", 'B', 14)
            pdf.set_fill_color(46, 139, 87)
            pdf.set_text_color(255, 255, 255)
            pdf.cell(0, 15, txt=fix_tr(f"TOPLAM KUMULATIF SALINIM: {total_sum:.8f} gCO2"), border=1, fill=True, align='C', ln=True)

            pdf.output(filename)
            print(f"\n[EcoTrace] Detayli rapor olusturuldu: {filename}")

        except Exception as e:
            print(f"\n[EcoTrace] PDF Olusturma Hatasi: {e}")

    # --- DIGER METODLAR (AYNEN KORUNDU) ---
    def _load_tdp_database(self):
        tdp_dict = {}
        if not os.path.exists(self.csv_path): return tdp_dict
        try:
            with open(self.csv_path, mode='r', encoding='utf-8') as f:
                reader = csv.DictReader(f)
                for row in reader:
                    m_name = row.get('name', '').lower().strip()
                    tdp_val = row.get('tdp')
                    if m_name and tdp_val:
                        try: tdp_dict[m_name] = float(tdp_val)
                        except: continue
        except Exception: pass
        return tdp_dict

    def _get_carbon_intensity(self):
        try:
            if os.path.exists(self.json_path):
                with open(self.json_path, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    return data.get("CARBON_INTENSITY_MAP", {}).get(self.region_code, 475)
            return 475 
        except Exception: return 475

    def _get_cpu_info(self):
        info = cpuinfo.get_cpu_info()
        brand = info.get("brand_raw","Bilinmeyen Islemci")
        clean_brand = brand.lower().replace("(r)", "").replace("(tm)", "").replace("13th gen", "").strip()
        found_tdp = 65.0 
        for model_name, tdp in self.tdp_db.items():
            if model_name in clean_brand or clean_brand in model_name:
                found_tdp = tdp
                break
        return {"brand": brand, "cores": psutil.cpu_count(logical=False), "tdp": found_tdp}

    def track(self, func):
        def wrapper(*args, **kwargs):
            start_time = time.perf_counter()
            cpu_before = psutil.cpu_percent(interval=None)
            result = func(*args, **kwargs)
            cpu_after = psutil.cpu_percent(interval=None)
            end_time = time.perf_counter()
            duration = end_time - start_time
            avg_cpu_usage = (cpu_before + cpu_after) / 2
            power_usage = (self.cpu_info['tdp'] * (avg_cpu_usage / 100) * duration) / 3600
            carbon_emitted = (power_usage / 1000) * self.carbon_intensity
            self.total_carbon += carbon_emitted
            self._log_to_csv(func.__name__, duration, carbon_emitted)
            print(f"\n[EcoTrace] Fonksiyon: {func.__name__}\n[EcoTrace] Sure: {duration:.4f} sn\n[EcoTrace] Salinan Karbon: {carbon_emitted:.8f} gCO2")
            return result
        return wrapper

    def _log_to_csv(self, func_name, duration, carbon):
        file_exists = os.path.isfile("ecotrace_log.csv")
        with open("ecotrace_log.csv", "a", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            if not file_exists:
                writer.writerow(["Tarih", "Fonksiyon", "Sure(sn)", "Karbon(gCO2)", "Bolge"])
            writer.writerow([datetime.now().strftime("%Y-%m-%d %H:%M:%S"), func_name, f"{duration:.4f}", f"{carbon:.8f}", self.region_code])