"""
7945db Interpreter - database.7945d'yi Python'a çevirir
"""

import os
import re
import json
from pathlib import Path

class Interpreter7945:
    def __init__(self):
        self.generated_code = ""
    
    def compile_7945d_to_py(self):
        """database.7945d'yi okuyup database.py'ye çevirir"""
        try:
            # Dosya yolları
            base_dir = Path(__file__).parent.parent
            source_path = base_dir / "database.7945d"
            target_path = base_dir / "lib" / "database.py"
            
            if not source_path.exists():
                raise FileNotFoundError(f"database.7945d bulunamadı: {source_path}")
            
            print("🔧 database.7945d → database.py çevriliyor...")
            
            # .7945d'yi oku
            with open(source_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # Python kodunu oluştur
            py_code = self._convert_7945d_to_python(content)
            
            # database.py dosyasını oluştur
            with open(target_path, 'w', encoding='utf-8') as f:
                f.write(py_code)
            
            print("✅ database.py oluşturuldu!")
            return True
            
        except Exception as e:
            print(f"❌ Çeviri hatası: {e}")
            return False
    
    def _convert_7945d_to_python(self, content: str) -> str:
        """7945d kodunu Python'a çevir"""
        py_code = '''# -*- coding: utf-8 -*-
"""
7945db Database Modülü
Otomatik olarak database.7945d'den çevrildi
"""

import os
import json
import hashlib
from datetime import datetime
from typing import Dict, Any, Optional, Union, List
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes

class Database7945:
    def __init__(self):
        """7945db Database sınıfı"""
        self.tables: Dict[str, Dict] = {}
        self.functions: Dict[str, Any] = {}
        self.current_file: Optional[str] = None
        self.auto_save: bool = True
        
        # Ana şifreleme anahtarı
        self.master_key = self._generate_master_key()
        
        # Çekirdek fonksiyonları başlat
        self._init_core_functions()
    
    def _generate_master_key(self) -> bytes:
        """Ana şifreleme anahtarını oluştur"""
        import secrets
        return secrets.token_bytes(32)
    
    def file(self, file_path: str) -> 'Database7945':
        """Database dosyasını ayarlar"""
        if not file_path.endswith('.7945db'):
            raise ValueError("Geçersiz dosya uzantısı. .7945db dosyası gerekiyor.")
        
        self.current_file = file_path
        
        if os.path.exists(file_path):
            self._load_from_file(file_path)
        else:
            self._save_to_file()
        
        return self
    
    def add(self, **kwargs) -> 'Database7945':
        """Veri ekler"""
        if not self.current_file:
            raise ValueError("Önce database dosyası belirtin: db.file('./db.7945db')")
        
        data_type = kwargs.get('type')
        
        if data_type == 'table':
            self._add_table(kwargs.get('name'))
        elif data_type == 'variable':
            self._add_variable(
                kwargs.get('table'),
                kwargs.get('name'),
                kwargs.get('value'),
                kwargs.get('cstm_value', 'none')
            )
        else:
            raise ValueError(f"Bilinmeyen tip: {data_type}")
        
        if self.auto_save:
            self._save_to_file()
        
        return self
    
    def get(self, **kwargs) -> Any:
        """Veri okur"""
        table = kwargs.get('table')
        name = kwargs.get('name')
        
        if table in self.tables and name in self.tables[table].get('variables', {}):
            return self.tables[table]['variables'][name]['value']
        raise ValueError(f"Değişken bulunamadı: {table}.{name}")
    
    def set(self, table: str, name: str, value: Any) -> 'Database7945':
        """Değer günceller"""
        if table in self.tables and name in self.tables[table].get('variables', {}):
            self.tables[table]['variables'][name]['value'] = value
            self.tables[table]['variables'][name]['lastModified'] = datetime.now().isoformat()
            
            if self.auto_save:
                self._save_to_file()
            return self
        raise ValueError(f"Değişken bulunamadı: {table}.{name}")
    
    def show(self) -> 'Database7945':
        """Database'i gösterir"""
        print('\\n=== 7945 DATABASE ===')
        for table_name, table in self.tables.items():
            print(f'\\n{table_name}:')
            for var_name, variable in table.get('variables', {}).items():
                print(f'  {var_name}: {variable.get("value")}')
        print('\\n=====================\\n')
        return self
    
    def _add_table(self, name: str):
        """Tablo ekler"""
        if name not in self.tables:
            self.tables[name] = {
                'variables': {},
                'created': datetime.now().isoformat()
            }
    
    def _add_variable(self, table: str, name: str, value_type: str, custom_value: str = "none"):
        """Değişken ekler"""
        if table not in self.tables:
            self._add_table(table)
        
        value = custom_value if custom_value != "none" else (
            0 if value_type == 'num' else
            False if value_type == 'bool' else ""
        )
        
        self.tables[table]['variables'][name] = {
            'value': value,
            'type': value_type,
            'lastModified': datetime.now().isoformat()
        }
    
    def _save_to_file(self):
        """Database'i dosyaya kaydeder"""
        if not self.current_file:
            return
        
        data = {
            'tables': self.tables,
            'metadata': {
                'created': datetime.now().isoformat(),
                'version': '1.0.0'
            }
        }
        
        encrypted = self._encrypt_data(json.dumps(data))
        
        with open(self.current_file, 'wb') as f:
            f.write(encrypted)
    
    def _load_from_file(self, file_path: str):
        """Database'i dosyadan yükler"""
        try:
            with open(file_path, 'rb') as f:
                encrypted = f.read()
            
            decrypted = self._decrypt_data(encrypted)
            data = json.loads(decrypted)
            self.tables = data.get('tables', {})
        except Exception:
            self.tables = {}
    
    def _encrypt_data(self, data: str) -> bytes:
        """Veriyi şifreler"""
        # AES-256-CBC şifreleme
        key = hashlib.sha256(b'7945db-secret').digest()
        iv = get_random_bytes(16)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        
        padded_data = pad(data.encode('utf-8'), AES.block_size)
        encrypted = cipher.encrypt(padded_data)
        
        return iv + encrypted
    
    def _decrypt_data(self, encrypted: bytes) -> str:
        """Şifreli veriyi çözer"""
        try:
            key = hashlib.sha256(b'7945db-secret').digest()
            iv = encrypted[:16]
            ciphertext = encrypted[16:]
            
            cipher = AES.new(key, AES.MODE_CBC, iv)
            decrypted = unpad(cipher.decrypt(ciphertext), AES.block_size)
            
            return decrypted.decode('utf-8')
        except Exception:
            raise ValueError('Database dosyası okunamıyor')
    
    def _init_core_functions(self):
        """Çekirdek fonksiyonları başlatır"""
        # Temel fonksiyonlar
        self.functions['add.json.table'] = self._add_json_table
        self.functions['add.json.var'] = self._add_json_var
        self.functions['edit.var'] = self._edit_var
        self.functions['remove.var'] = self._remove_var
    
    def _add_json_table(self, table_name: str):
        """JSON tablosu ekler"""
        if table_name not in self.tables:
            self.tables[table_name] = {
                'variables': {},
                'created': datetime.now().isoformat(),
                'tableId': len(self.tables) + 1,
                'tableIndex': len(self.tables) + 1
            }
        return self.tables[table_name]
    
    def _add_json_var(self, table_name: str, var_name: str, var_value: Any):
        """JSON değişkeni ekler"""
        if table_name not in self.tables:
            self._add_json_table(table_name)
        
        self.tables[table_name]['variables'][var_name] = {
            'value': var_value,
            'lastModified': datetime.now().isoformat()
        }
    
    def _edit_var(self, table_name: str, var_name: str, new_value: Any):
        """Değişkeni düzenler"""
        if table_name in self.tables and var_name in self.tables[table_name].get('variables', {}):
            self.tables[table_name]['variables'][var_name]['value'] = new_value
            self.tables[table_name]['variables'][var_name]['lastModified'] = datetime.now().isoformat()
    
    def _remove_var(self, table_name: str, var_name: str):
        """Değişkeni siler"""
        if table_name in self.tables and var_name in self.tables[table_name].get('variables', {}):
            del self.tables[table_name]['variables'][var_name]
    
    # === DATABASE.7945d'DEN ÇEVRİLEN FONKSİYONLAR ===
'''
        
        # .7945d fonksiyonlarını Python'a çevir
        py_code += self._parse_7945d_functions(content)
        
        py_code += '''
if __name__ == "__main__":
    # Test
    db = Database7945()
    db.file("./test.7945db")
    print("✅ 7945db Python modülü hazır!")
'''
        
        return py_code
    
    def _parse_7945d_functions(self, content: str) -> str:
        """7945d fonksiyonlarını parse et ve Python'a çevir"""
        py_functions = ""
        lines = content.split('\\n')
        current_func = None
        
        for line in lines:
            trimmed = line.strip()
            
            # Yorum satırlarını atla
            if trimmed.startswith('/**') or trimmed.startswith('*/') or trimmed.startswith('//'):
                continue
            
            # db.import satırlarını atla
            if trimmed.startswith('db.import'):
                continue
            
            # func başlangıcı
            if trimmed.startswith('func.') and '=[' in trimmed:
                func_name = self._extract_function_name(trimmed)
                current_func = func_name
                py_functions += f'    # {func_name} fonksiyonu\\n'
                py_functions += f'    def {self._convert_func_name_to_py(func_name)}(self, args=None):\\n'
                py_functions += f'        """{func_name} fonksiyonu"""\\n'
                py_functions += f'        if args is None:\\n'
                py_functions += f'            args = {{}}\\n'
                py_functions += f'        print(f"🔧 {func_name} çalıştırılıyor:", args)\\n'
            
            # name.func bulma
            if current_func and 'name.func' in trimmed:
                actual_func_name = self._extract_func_name(trimmed)
                py_functions += self._generate_python_function_body(actual_func_name)
            
            # func sonu
            if trimmed == '];' and current_func:
                py_functions += '\\n'
                current_func = None
        
        return py_functions
    
    def _extract_function_name(self, line: str) -> str:
        """Fonksiyon adını çıkar"""
        match = re.search(r'func\\.([^.]+)', line)
        return match.group(1) if match else 'unknown'
    
    def _extract_func_name(self, line: str) -> str:
        """Gerçek fonksiyon adını çıkar"""
        match = re.search(r'name\\.func\\s*=\\s*"([^"]+)"', line)
        return match.group(1) if match else 'unknown'
    
    def _convert_func_name_to_py(self, func_name: str) -> str:
        """Fonksiyon adını Python formatına çevir"""
        # func.list.tables -> list_all_tables
        parts = func_name.split('.')
        return '_'.join(parts)
    
    def _generate_python_function_body(self, func_name: str) -> str:
        """Python fonksiyon gövdesi oluştur"""
        if func_name == 'list.all.tables':
            return '''        return list(self.tables.keys())\\n'''
        
        elif func_name == 'get.table.info':
            return '''        table = self.tables.get(args.get("tableName"))
        if not table:
            raise ValueError("Tablo bulunamadı")
        return {
            "variableCount": len(table.get("variables", {})),
            "created": table.get("created", "unknown")
        }\\n'''
        
        elif func_name == 'read.variable':
            return '''        return self.get(
            table=args.get("tableName"),
            name=args.get("varName")
        )\\n'''
        
        elif func_name == 'list.table.variables':
            return '''        table = self.tables.get(args.get("tableName"))
        if not table:
            raise ValueError("Tablo bulunamadı")
        return list(table.get("variables", {}).keys())\\n'''
        
        elif func_name == 'search.database':
            return '''        results = []
        for table_name, table in self.tables.items():
            for var_name, variable in table.get("variables", {}).items():
                value = str(variable.get("value", ""))
                if args.get("searchTerm", "") in value:
                    results.append({
                        "table": table_name,
                        "variable": var_name,
                        "value": value
                    })
        return results\\n'''
        
        elif func_name == 'database.statistics':
            return '''        total_vars = sum(
            len(table.get("variables", {}))
            for table in self.tables.values()
        )
        return {
            "tableCount": len(self.tables),
            "totalVariables": total_vars
        }\\n'''
        
        else:
            return f'''        return {{"executed": "{func_name}", "args": args}}\\n'''