"""
================================================================
KEÇECİ HASH ALGORITHM (KEÇECİ HASH ALGORİTMASI), KHA-256
Keçeci Hash Algorithm (Keçeci Hash Algoritması), KHA-256
================================================================
Performanstan fedakarlık edilerek güvenlik maksimize edilmiş versiyondur.
It is the version with security maximized at the sacrifice of performance.
================================================================
"""
from __future__ import annotations
import secrets
import random
import struct
import time
import hashlib
import re
import json
import os
import sys
from dataclasses import dataclass, field
from typing import Optional, Dict, Any, Tuple, List, Union
from datetime import datetime
import numpy as np
from fractions import Fraction
from decimal import Decimal, getcontext
import logging
import math

# Logging konfigürasyonu
logging.basicConfig(
    level=logging.WARNING,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger("KHA-256")

# Versiyon bilgisi
__version__ = "0.1.2"
__author__ = "Mehmet Keçeci"
__license__ = "AGPL-3.0 license"

req_kececinumbers = "0.8.4"

# KeçeciNumbers kontrolü - API uyumlu hale getirildi
try:
    import kececinumbers as kn
    from kececinumbers import (
        TYPE_POSITIVE_REAL,
        TYPE_NEGATIVE_REAL,
        TYPE_COMPLEX,
        TYPE_FLOAT,
        TYPE_RATIONAL,
        TYPE_QUATERNION,
        TYPE_NEUTROSOPHIC,
        TYPE_NEUTROSOPHIC_COMPLEX,
        TYPE_HYPERREAL,
        TYPE_BICOMPLEX,
        TYPE_NEUTROSOPHIC_BICOMPLEX,
        TYPE_OCTONION,
        TYPE_SEDENION,
        TYPE_CLIFFORD,
        TYPE_DUAL,
        TYPE_SPLIT_COMPLEX,
        TYPE_PATHION,
        TYPE_CHINGON,
        TYPE_ROUTON,
        TYPE_VOUDON,
        TYPE_SUPERREAL,
        TYPE_TERNARY,
    )

    # Çalıştığı bilinen tipler
    WORKING_TYPES = [
        TYPE_POSITIVE_REAL,
        TYPE_NEGATIVE_REAL,
        TYPE_COMPLEX,
        TYPE_FLOAT,
        TYPE_RATIONAL,
        TYPE_QUATERNION,
        TYPE_NEUTROSOPHIC,
        TYPE_NEUTROSOPHIC_COMPLEX,
        TYPE_BICOMPLEX,
        TYPE_OCTONION,
        TYPE_DUAL,
        TYPE_SPLIT_COMPLEX,
        TYPE_HYPERREAL,
        TYPE_NEUTROSOPHIC_BICOMPLEX,
        TYPE_SEDENION,
        TYPE_CLIFFORD,
        TYPE_PATHION,
        TYPE_CHINGON,
        TYPE_ROUTON,
        TYPE_VOUDON,
        TYPE_SUPERREAL,
        TYPE_TERNARY,
    ]

    # Tip isimleri
    TYPE_NAMES = {
        TYPE_POSITIVE_REAL: "Positive Real",
        TYPE_NEGATIVE_REAL: "Negative Real",
        TYPE_COMPLEX: "Complex",
        TYPE_FLOAT: "Float",
        TYPE_RATIONAL: "Rational",
        TYPE_QUATERNION: "Quaternion",
        TYPE_NEUTROSOPHIC: "Neutrosophic",
        TYPE_NEUTROSOPHIC_COMPLEX: "Neutrosophic Complex",
        TYPE_HYPERREAL: "Hyperreal",
        TYPE_BICOMPLEX: "Bicomplex",
        TYPE_NEUTROSOPHIC_BICOMPLEX: "Neutrosophic Bicomplex",
        TYPE_OCTONION: "Octonion",
        TYPE_SEDENION: "Sedenion",
        TYPE_CLIFFORD: "Clifford",
        TYPE_DUAL: "Dual",
        TYPE_SPLIT_COMPLEX: "Split Complex",
        TYPE_PATHION: "Pathion",
        TYPE_CHINGON: "Chingon",
        TYPE_ROUTON: "Routon",
        TYPE_VOUDON: "Voudon",
        TYPE_SUPERREAL: "Superreal",
        TYPE_TERNARY: "Ternary",
    }
    
    # Tip değişkenlerini kontrol et
    KHA_AVAILABLE = True
    
    # API kontrolü
    if hasattr(kn, 'get_with_params'):
        # Yeni API
        KHA_NEW_API = True
        logger.info("kececinumbers new API detected")
    else:
        # Eski API
        KHA_NEW_API = False
        logger.info("kececinumbers old API detected")
        
    logger.info(f"kececinumbers v{getattr(kn, '__version__', 'unknown')} loaded successfully")
    
except ImportError as e:
    logger.error(f"kececinumbers not found: {e}")
    print(f"⚠️  UYARI: kececinumbers kütüphanesi bulunamadı!")
    print(f"   Lütfen şu komutu çalıştırın: pip install kececinumbers=={req_kececinumbers}")
    print("   Geçici olarak matematiksel sabitler kullanılacak...")
    
    KHA_AVAILABLE = False
    KHA_NEW_API = False
    WORKING_TYPES = list(range(1, 23))
    TYPE_NAMES = {i: f"Type_{i}" for i in range(1, 23)}
    
    # Sahte tipler oluştur
    TYPE_POSITIVE_REAL = 1
    TYPE_NEGATIVE_REAL = 2
    TYPE_COMPLEX = 3
    TYPE_FLOAT = 4
    TYPE_RATIONAL = 5
    TYPE_QUATERNION = 6
    TYPE_NEUTROSOPHIC = 7
    TYPE_NEUTROSOPHIC_COMPLEX = 8
    TYPE_HYPERREAL = 9
    TYPE_BICOMPLEX = 10
    TYPE_OCTONION = 11
    kn = None

# ============================================================
# KONFİGÜRASYON - GÜVENLİK ÖNCELİKLİ
# ============================================================
@dataclass
class FortifiedConfig:
    """OPTİMİZE EDİLMİŞ KHA Hash Konfigürasyonu"""
    
    # Çıktı boyutu
    output_bits: int = 256
    hash_bytes: int = 32
    
    # GÜVENLİK PARAMETRELERİ (OPTİMUM)
    iterations: int = 4           # Optimal: 4 (performans/güvenlik dengesi)
    rounds: int = 2               # Optimal: 2
    components_per_hash: int = 8  # Optimal: 8
    salt_length: int = 96       # 96: en iyi değer
    
    # KARIŞTIRMA PARAMETRELERİ
    shuffle_layers: int = 6       # 6-8: en iyi değer
    diffusion_rounds: int = 7     # 7-9: en iyi değer
    avalanche_boosts: int = 2     # Optimal: 2
    
    # GÜVENLİK ÖZELLİKLERİ
    enable_quantum_resistance: bool = True
    enable_post_quantum_mixing: bool = True
    double_hashing: bool = True    # Ek güvenlik
    triple_compression: bool = False # Ek güvenlik
    memory_hardening: bool = True  # Kapalı (performans), açık: hash
    
    # KRİTİK AYARLAR (tutarlılık için)
    entropy_injection: bool = False  # Uniformluğa katkısı var. True olması (tutarlılığı bozabilir)
    time_varying_salt: bool = False  # KAPALI. True olması (tutarlılığı bozabilir)
    context_sensitive_mixing: bool = True
    
    # PERFORMANS
    cache_enabled: bool = True
    parallel_processing: bool = True
    max_workers: int = 8  # 12'den 8'e (daha stabil)
    
    # AVALANCHE OPTİMİZASYONU
    use_enhanced_avalanche: bool = True
    avalanche_strength: float = 0.05  # %? (daha stabil)
    
    def __post_init__(self):
        getcontext().prec = 78  # 85: Uniform ve güvenlikten taviz veriyor!
        if self.parallel_processing:
            import multiprocessing
            self.max_workers = min(self.max_workers, multiprocessing.cpu_count() - 1)
"""
# Aldığım en iyi sonuçlar
@dataclass
class FortifiedConfig:
    #Güçlendirilmiş KHA Hash Konfigürasyonu

    # Çıktı boyutu
    output_bits: int = 256
    hash_bytes: int = 32  # 256-bit

    # Güvenlik parametreleri (artırılmış)
    iterations: int = 4  # 12'den 16'ya: 4-16
    rounds: int = 2  # Her iterasyon için tur sayısı: 2-8
    components_per_hash: int = 8  # 16'dan 20'ye: 8-20
    salt_length: int = 96  # 64'ten 96'ya

    # Karıştırma parametreleri (artırılmış)
    shuffle_layers: int = 8  # 8: en iyi sonuç. Toplam süreyi etkiliyor
    diffusion_rounds: int = 9  # 9: en iyi sonuç. Toplam süreyi etkiliyor
    avalanche_boosts: int = 2  # Avalanche artırıcılar: 2-6

    # Güvenlik özellikleri
    enable_quantum_resistance: bool = True
    enable_post_quantum_mixing: bool = True
    double_hashing: bool = True # Kapalı (performans)
    triple_compression: bool = True
    memory_hardening: bool = True

    # Ek güvenlik
    entropy_injection: bool = False # Aynı girdi farklı hash üretiyor. Zaman bazlı entropy veya rastgelelik enjekte ediliyor. FortifiedConfig'da time_varying_salt=False ve entropy_injection=False yap
    time_varying_salt: bool = False # 
    context_sensitive_mixing: bool = True

    # Performans (fedakarlık)
    cache_enabled: bool = True  # (performans için)
    parallel_processing: bool = True  # Seri işlemi True kullandım
    max_workers: int = 12 # Paralel işçi sayısı

    # AVALANCHE OPTİMİZASYONU
    use_enhanced_avalanche: bool = True  # Gelişmiş avalanche
    avalanche_strength: float = 0.03     # Pertürbasyon gücü (%3)

    def __post_init__(self):
        # Hassas hesaplar için yüksek hassasiyet. Optimal: 78-bit hassasiyet
        getcontext().prec = 100
        if self.parallel_processing:
            # Paralel işlem için ayarlar
            import multiprocessing
            self.max_workers = min(self.max_workers, multiprocessing.cpu_count() - 1)
"""

# ============================================================
# MATEMATİKSEL GÜVENLİK TABANLARI
# ============================================================
class MathematicalSecurityBases:
    """Matematiksel güvenlik sabitleri ve fonksiyonları"""

    # Özel matematiksel sabitler (güvenlik için)
    SECURITY_CONSTANTS = {
        # İrrasyonel sabitler
        "kha_pi": 3.14159265358979323846264338327950288419716939937510,
        "kha_e": 2.71828182845904523536028747135266249775724709369995,
        "golden_ratio": 1.61803398874989484820458683436563811772030917980576,
        "silver_ratio": 2.41421356237309504880168872420969807856967187537694,
        "plastic_number": 1.32471795724474602596090885447809734073440405690173,
        # Özel matematiksel sabitler
        "apery": 1.202056903159594285399738161511449990764986292,
        "catalan": 0.91596559417721901505460351493238411077414937428167,
        "lemniscate": 2.62205755429211981046483958989111941368275495143162,
        "gauss": 0.834626841674073186281429734799,
        # Transandantal sabitler
        "euler_mascheroni": 0.57721566490153286060651209008240243104215933593992,
        "khinchin": 2.68545200106530644530971483548179569382038229399446,
        "glaisher": 1.28242712910062263687534256886979172776768892732500,
    }

    # Güvenlik dönüşüm fonksiyonları
    TRANSFORMATIONS = [
        # Sinüs tabanlı
        lambda x: np.sin(x * np.pi * 1.618033988749895),
        lambda x: np.sin(x * x * np.pi),
        lambda x: np.sin(np.exp(x)),
        # Hiperbolik
        lambda x: np.tanh(x * 3.141592653589793),
        lambda x: np.sinh(x) / (np.cosh(x) + 1e-10),
        lambda x: np.arctan(x * 10),
        # Karmaşık
        lambda x: x * np.exp(-x * x),
        lambda x: np.log1p(np.abs(x)),
        lambda x: np.sqrt(np.abs(x) + 1e-10),
        lambda x: 1 / (1 + np.exp(-x)),
        # Özel kombinasyonlar
        lambda x: np.sin(x * np.pi) * np.tanh(x * 2.71828),
        lambda x: np.arctan(x * 3.14159) * np.log1p(np.abs(x)),
        lambda x: np.sin(x * 1.61803) + np.cos(x * 2.41421),
    ]

    @staticmethod
    def get_constant(name: str, offset: float = 0) -> float:
        """Güvenlik sabiti al"""
        const_val = MathematicalSecurityBases.SECURITY_CONSTANTS.get(
            name, MathematicalSecurityBases.SECURITY_CONSTANTS["kha_pi"]
        )
        return const_val + offset

    @staticmethod
    def apply_transformations(value: float, rounds: int = 3) -> float:
        """Çoklu dönüşüm uygula"""
        for i in range(rounds):
            idx = (int(value * 1e9) + i) % len(
                MathematicalSecurityBases.TRANSFORMATIONS
            )
            value = MathematicalSecurityBases.TRANSFORMATIONS[idx](value)
        return value

# ============================================================
# KHA ÇEKİRDEĞİ
# ============================================================
class FortifiedKhaCore:
    """Güçlendirilmiş KHA Hash Çekirdeği"""

    def __init__(self, config: FortifiedConfig):
        self.config = config
        self.stats = {
            "total_operations": 0,
            "kha_success": 0,
            "kha_fail": 0,
            "mixing_time": 0,
            "avalanche_score": 0,
        }

    def _generate_kha_matrix(self, seed_data: bytes) -> np.ndarray:
        """Güçlendirilmiş KHA değerlerinden matris oluştur"""
        values = []
        
        # Seed hazırlığı
        seed_int = int.from_bytes(seed_data[:16], "big")
        rng = random.Random(seed_int)
        
        # Kullanılacak tipler - güvenli ve test edilmiş tipler
        SAFE_TYPES = []
        TYPE_REQUIREMENTS = {}
        
        # Tipleri ve gereksinimlerini tanımla
        if KHA_AVAILABLE:
            try:
                # ÇALIŞAN TİPLER (test edilmiş)
                
                # 1. Basit Sayılar - HER ZAMAN ÇALIŞIR
                SAFE_TYPES.extend([TYPE_POSITIVE_REAL, TYPE_NEGATIVE_REAL, TYPE_FLOAT])
                TYPE_REQUIREMENTS[TYPE_POSITIVE_REAL] = {"format": "simple_float", "components": 1}
                TYPE_REQUIREMENTS[TYPE_NEGATIVE_REAL] = {"format": "simple_float", "components": 1}
                TYPE_REQUIREMENTS[TYPE_FLOAT] = {"format": "simple_float", "components": 1}
                
                # 2. Complex - GENELDE ÇALIŞIR
                SAFE_TYPES.extend([TYPE_COMPLEX, TYPE_NEUTROSOPHIC_COMPLEX])
                TYPE_REQUIREMENTS[TYPE_COMPLEX] = {"format": "complex", "components": 2}
                TYPE_REQUIREMENTS[TYPE_NEUTROSOPHIC_COMPLEX] = {"format": "complex", "components": 2}
                
                # 3. Quaternion - ÇOĞUNLUKLA ÇALIŞIR
                SAFE_TYPES.append(TYPE_QUATERNION)
                TYPE_REQUIREMENTS[TYPE_QUATERNION] = {"format": "quaternion", "components": 4}
                
                # 4. Octonion - ÇOĞUNLUKLA ÇALIŞIR
                SAFE_TYPES.append(TYPE_OCTONION)
                TYPE_REQUIREMENTS[TYPE_OCTONION] = {"format": "octonion", "components": 8}
                
                # 5. SORUNLU TİPLERİ KALDIR veya ÖZEL FORMATLA EKLE
                
                # Rational - ÖZEL FORMAT GEREKİYOR (tam sayılar)
                SAFE_TYPES.append(TYPE_RATIONAL)
                TYPE_REQUIREMENTS[TYPE_RATIONAL] = {"format": "rational_int", "components": 2}
                
                # Neutrosophic - ÇALIŞIYOR
                SAFE_TYPES.append(TYPE_NEUTROSOPHIC)
                TYPE_REQUIREMENTS[TYPE_NEUTROSOPHIC] = {"format": "neutrosophic", "components": 3}
                
                # Hyperreal - BASİT FORMAT
                SAFE_TYPES.append(TYPE_HYPERREAL)
                TYPE_REQUIREMENTS[TYPE_HYPERREAL] = {"format": "hyperreal_simple", "components": 2}
                
                # Dual ve Split Complex - BASİT
                try:
                    SAFE_TYPES.extend([TYPE_DUAL, TYPE_SPLIT_COMPLEX])
                    TYPE_REQUIREMENTS[TYPE_DUAL] = {"format": "simple_float", "components": 1}
                    TYPE_REQUIREMENTS[TYPE_SPLIT_COMPLEX] = {"format": "simple_float", "components": 1}
                except NameError:
                    pass
                    
            except NameError as e:
                logger.warning(f"Type name error: {e}")
                # Varsayılan tipler
                SAFE_TYPES = [1, 2, 3, 4, 6, 8]  # En güvenli tipler
                for t in SAFE_TYPES:
                    TYPE_REQUIREMENTS[t] = {"format": "simple_float", "components": 1}
        else:
            # KHA yoksa
            SAFE_TYPES = [1, 2, 3, 4, 5, 6]
            for t in SAFE_TYPES:
                TYPE_REQUIREMENTS[t] = {"format": "simple_float", "components": 1}
        
        # Her hash için 3-5 farklı tür kullan (stabilite için)
        num_types_to_use = min(rng.randint(3, 5), len(SAFE_TYPES))
        selected_types = rng.sample(SAFE_TYPES, num_types_to_use)
        
        # İterasyon derinliği
        iteration_depth = rng.randint(12, 20)
        
        logger.debug(f"Using {num_types_to_use} KHA types from {len(SAFE_TYPES)} safe types")
        
        for type_idx, kha_type in enumerate(selected_types):
            try:
                type_info = TYPE_REQUIREMENTS.get(kha_type, {"format": "simple_float", "components": 1})
                format_type = type_info["format"]
                components_needed = type_info["components"]
                
                if KHA_AVAILABLE and kn is not None:
                    # Matematiksel sabitler
                    const_names = list(MathematicalSecurityBases.SECURITY_CONSTANTS.keys())
                    const_name = rng.choice(const_names)
                    base_val = MathematicalSecurityBases.get_constant(const_name)
                    
                    # Format'a göre başlangıç değeri oluştur - HATA DÜZELTMELERİ İLE
                    
                    if format_type == "simple_float":
                        # Basit float sayı - EN GÜVENLİ
                        variation = 0.03 + (type_idx * 0.005)
                        float_val = base_val * (1 + rng.random() * variation)
                        start_val = str(float_val)
                        
                        # add_val daha küçük
                        add_factor = 0.00005 * (1 + type_idx * 0.05)
                        add_val = str(float_val * add_factor)
                        
                        if kha_type == TYPE_NEGATIVE_REAL:
                            start_val = "-" + start_val
                            add_val = "-" + add_val
                            
                    elif format_type == "complex":
                        # Kompleks sayı
                        real_part = base_val * (1 + rng.random() * 0.03)
                        # Imaginary part için farklı sabit
                        imag_const = "kha_e" if const_name == "kha_pi" else "kha_pi"
                        imag_base = MathematicalSecurityBases.get_constant(imag_const)
                        imag_part = imag_base * (1 + rng.random() * 0.02)
                        
                        # DOĞRU FORMAT: "a+bj"
                        start_val = f"{real_part}+{imag_part}j"
                        add_val = f"{real_part*0.0008}+{imag_part*0.0008}j"
                        
                    elif format_type == "quaternion":
                        # Quaternion: 4 float bileşen
                        parts = []
                        quat_consts = ["kha_pi", "kha_e", "golden_ratio", "silver_ratio"]
                        for i in range(4):
                            const_name_i = quat_consts[i % len(quat_consts)]
                            const_val = MathematicalSecurityBases.get_constant(const_name_i)
                            part_val = const_val * (1 + rng.random() * 0.015)
                            parts.append(str(part_val))
                        start_val = ",".join(parts)
                        add_val = ",".join([str(float(p) * 0.0002) for p in parts])
                        
                    elif format_type == "octonion":
                        # Octonion: 8 float bileşen
                        parts = []
                        oct_consts = ["kha_pi", "kha_e", "golden_ratio", "silver_ratio", 
                                     "apery", "catalan", "euler_mascheroni", "khinchin"]
                        for i in range(8):
                            const_idx = i % len(oct_consts)
                            const_val = MathematicalSecurityBases.get_constant(oct_consts[const_idx])
                            part_val = const_val * (1 + rng.random() * 0.01)
                            parts.append(str(part_val))
                        start_val = ",".join(parts)
                        add_val = ",".join([str(float(p) * 0.00015) for p in parts])
                        
                    elif format_type == "rational_int":
                        # Rational: TAM SAYILAR GEREKİYOR!
                        # Fraction sadece tam sayıları kabul eder: "a/b" where a,b integers
                        numerator = int(base_val * 1000) + rng.randint(1, 100)
                        denominator = int(MathematicalSecurityBases.get_constant("kha_e") * 1000) + rng.randint(1, 100)
                        
                        # Basit kesir formatı: "a/b"
                        start_val = f"{numerator}/{denominator}"
                        
                        # add_val da tam sayı olmalı
                        add_numerator = max(1, int(numerator * 0.001))
                        add_denominator = denominator  # Aynı payda
                        add_val = f"{add_numerator}/{add_denominator}"
                        
                    elif format_type == "neutrosophic":
                        # Neutrosophic: T, I, F (üç değer)
                        t_val = base_val * 0.8  # Truth [0-1]
                        i_val = 0.3 + rng.random() * 0.4  # Indeterminacy [0-1]
                        f_val = 0.1 + rng.random() * 0.3  # Falsehood [0-1]
                        
                        # String formatı
                        start_val = f"{t_val},{i_val},{f_val}"
                        add_val = f"{t_val*0.001},{i_val*0.001},{f_val*0.001}"
                        
                    elif format_type == "hyperreal_simple":
                        # Hyperreal: basit format
                        standard = base_val
                        infinitesimal = 0.000001 * (1 + type_idx * 0.1)
                        start_val = f"{standard}+{infinitesimal}"
                        add_val = f"{infinitesimal*0.1}"
                        
                    elif format_type == "simple_int":
                        # Basit tam sayı
                        int_val = int(base_val * 100) + rng.randint(1, 50)
                        start_val = str(int_val)
                        add_val = str(max(1, int(int_val * 0.01)))
                        
                    else:
                        # Varsayılan: basit float
                        variation = 0.03 + (type_idx * 0.005)
                        float_val = base_val * (1 + rng.random() * variation)
                        start_val = str(float_val)
                        add_val = str(float_val * 0.0001)
                    
                    # DEBUG: Format kontrolü
                    logger.debug(f"Type {kha_type} ({format_type}): start='{start_val[:50]}...', add='{add_val[:30]}...'")
                    
                    # API çağrısı - farklı API versiyonlarını dene
                    seq = None
                    
                    # Önce API'nin mevcut parametrelerini kontrol et
                    try:
                        # Deneme 1: En yaygın API
                        import inspect
                        sig = inspect.signature(kn.get_with_params)
                        params = list(sig.parameters.keys())
                        
                        if 'kha_type_choice' in params:
                            # Yeni API
                            seq = kn.get_with_params(
                                kha_type_choice=kha_type,
                                iterations=iteration_depth,
                                start_value_raw=start_val,
                                add_value_raw=add_val,
                                include_intermediate_steps=False,
                            )
                        elif 'kha_type' in params:
                            # Eski API
                            seq = kn.get_with_params(
                                kha_type=kha_type,
                                iterations=iteration_depth,
                                start_value=start_val,
                                add_value=add_val,
                                include_intermediate_steps=False,
                            )
                        elif 'type_choice' in params:
                            # Alternatif API
                            seq = kn.get_with_params(
                                type_choice=kha_type,
                                iterations=iteration_depth,
                                start_val=start_val,
                                add_val=add_val,
                            )
                        else:
                            # Pozisyonel argümanlar
                            seq = kn.get_with_params(
                                kha_type,
                                iteration_depth,
                                start_val,
                                add_val,
                            )
                            
                    except (TypeError, ValueError, AttributeError) as e:
                        logger.warning(f"API inspection failed: {e}, trying direct calls")
                        
                        # Doğrudan denemeler
                        api_attempts = [
                            lambda: kn.get_with_params(
                                kha_type_choice=kha_type,
                                iterations=iteration_depth,
                                start_value_raw=start_val,
                                add_value_raw=add_val,
                                include_intermediate_steps=False,
                            ),
                            lambda: kn.get_with_params(
                                kha_type=kha_type,
                                iterations=iteration_depth,
                                start_value=start_val,
                                add_value=add_val,
                                include_intermediate_steps=False,
                            ),
                            lambda: kn.get_with_params(
                                type_choice=kha_type,
                                iterations=iteration_depth,
                                start_val=start_val,
                                add_val=add_val,
                            ),
                            lambda: kn.get_with_params(
                                kha_type,
                                iteration_depth,
                                start_val,
                                add_val,
                            ),
                        ]
                        
                        for attempt_idx, api_call in enumerate(api_attempts):
                            try:
                                seq = api_call()
                                if seq:
                                    logger.debug(f"API attempt {attempt_idx+1} successful")
                                    break
                            except (TypeError, ValueError) as e2:
                                if attempt_idx == len(api_attempts) - 1:
                                    logger.warning(f"All API attempts failed: {e2}")
                    
                    if seq:
                        # Diziden değerleri çıkar
                        num_values_to_extract = min(iteration_depth, len(seq), 8)
                        
                        for val_idx in range(-num_values_to_extract, 0):
                            if val_idx < 0:
                                final_val = seq[val_idx]
                                extracted = self._extract_numerics(final_val)
                                
                                # Bileşen sayısına göre ekle
                                values.extend(extracted[:min(len(extracted), components_needed * 2)])
                                
                                # İterasyon başına ek varyasyon
                                progress = (val_idx + len(seq)) / len(seq)
                                for val in extracted[:components_needed]:
                                    if progress > 0:
                                        modulated = val * (1 + np.sin(progress * np.pi) * 0.1)
                                        values.append(modulated)
                        
                        self.stats["kha_success"] += 1
                        
                    else:
                        self.stats["kha_fail"] += 1
                        # Fallback: matematiksel sabitlerden değer üret
                        self._add_fallback_values(values, type_idx, components_needed, rng)
                
                else:
                    # KHA yoksa zengin matematiksel sabitler
                    self._add_math_fallback_values(values, type_idx, rng)

            except Exception as e:
                logger.error(f"KHA matrix error for type {kha_type}: {e}")
                self.stats["kha_fail"] += 1
                
                # Güvenli fallback
                self._add_safe_fallback_values(values, type_idx, rng)
        
        # Matris işleme
        processed_matrix = self._process_matrix_values(values, seed_int, target_size=512)
        
        logger.info(f"Generated KHA matrix: {len(processed_matrix)} values, "
                   f"success: {self.stats['kha_success']}, fail: {self.stats['kha_fail']}")
        
        return processed_matrix
    
    def _add_fallback_values(self, values, type_idx, components_needed, rng):
        """Fallback değerleri ekle"""
        const_names = list(MathematicalSecurityBases.SECURITY_CONSTANTS.keys())
        const_name = rng.choice(const_names)
        base_val = MathematicalSecurityBases.get_constant(const_name)
        
        for i in range(components_needed * 2):  # 2x bileşen
            variation = 0.05 * (1 + type_idx * 0.1 + i * 0.02)
            val = base_val * (1 + rng.random() * variation)
            
            # Çeşitli transformasyonlar
            transforms = [
                lambda x: x,
                lambda x: np.sin(x * np.pi * 0.5),
                lambda x: np.exp(-x * 0.1),
                lambda x: np.log1p(abs(x)),
            ]
            
            transform_idx = i % len(transforms)
            transformed = transforms[transform_idx](val)
            values.append(transformed)
    
    def _add_math_fallback_values(self, values, type_idx, rng):
        """Matematiksel fallback değerleri ekle"""
        consts_to_use = ["kha_pi", "kha_e", "golden_ratio", "silver_ratio"]
        
        for const_idx, const_name in enumerate(consts_to_use):
            base_val = MathematicalSecurityBases.get_constant(const_name)
            
            for var_idx in range(2):
                variation = 0.02 * (1 + type_idx * 0.15 + var_idx * 0.08)
                val = base_val * (1 + rng.random() * variation)
                
                # Çoklu transformasyonlar
                values.append(val)
                values.append(np.sin(val * np.pi))
                values.append(np.exp(-val * 0.05))
                values.append(np.tanh(val * 0.1))
    
    def _add_safe_fallback_values(self, values, type_idx, rng):
        """Güvenli fallback değerleri ekle"""
        base_val = MathematicalSecurityBases.get_constant("kha_pi")
        
        for i in range(8):
            phase = (type_idx * 8 + i) * 0.1
            val = base_val * (1 + np.sin(phase) * 0.1)
            
            # Basit ama çeşitli değerler
            values.append(val)
            values.append(val * 1.618033988749895)  # Golden ratio
            values.append(np.sin(val))
            values.append(np.cos(val * 2.718281828459045))
    
    def _process_matrix_values(self, values, seed_int, target_size=512):
        """Değerleri işle ve matrise dönüştür"""
        if not values:
            # Minimum güvenli değerler
            for i in range(target_size):
                phase = i * 0.05
                val = MathematicalSecurityBases.get_constant("kha_pi", phase)
                values.append(val * (1 + np.sin(phase) * 0.2))
        
        # Boyutlandırma
        if len(values) < target_size:
            # Mevcut değerleri genişlet
            current = list(values)
            while len(values) < target_size:
                idx = len(values) % len(current)
                base = current[idx % len(current)] if current else 1.0
                
                # Transformasyon uygula
                transform_idx = (len(values) // len(current)) % 4
                if transform_idx == 0:
                    new_val = base * (1 + np.sin(len(values) * 0.1) * 0.15)
                elif transform_idx == 1:
                    new_val = np.exp(base * 0.005)
                elif transform_idx == 2:
                    new_val = np.tanh(base * 0.05)
                else:
                    new_val = base * 1.618033988749895
                
                values.append(new_val)
        else:
            values = values[:target_size]
        
        # Numpy array'e dönüştür
        values_array = np.array(values, dtype=np.float64)
        
        # Normalizasyon (0-1)
        min_val = np.min(values_array)
        max_val = np.max(values_array)
        if max_val - min_val > 1e-10:
            values_array = (values_array - min_val) / (max_val - min_val)
        else:
            values_array = np.zeros_like(values_array) + 0.5
        
        # Karıştırma
        shuffle_seed = (seed_int + 12345) & 0xFFFFFFFF
        rng_shuffle = random.Random(shuffle_seed)
        indices = list(range(len(values_array)))
        rng_shuffle.shuffle(indices)
        
        final_matrix = values_array[indices]
        
        # Son non-lineer dönüşüm
        final_matrix = np.sin(final_matrix * np.pi * 1.618033988749895)
        
        return final_matrix
        
    def _extract_numerics(self, kha_obj) -> List[float]:
        """KHA objesinden sayısal değerleri çıkar"""
        values = []

        # coeffs özelliği
        if hasattr(kha_obj, "coeffs"):
            try:
                coeffs = kha_obj.coeffs
                if isinstance(coeffs, (list, tuple)):
                    values.extend([float(c) for c in coeffs[:64]])
            except BaseException:
                pass

        # Bilinen özellikler
        numeric_attrs = [
            "w", "x", "y", "z", "real", "imag", 
            "a", "b", "c", "d", "e", "f", "g", "h",
            "value", "magnitude", "norm", "abs"
        ]

        for attr in numeric_attrs:
            if hasattr(kha_obj, attr):
                try:
                    val = getattr(kha_obj, attr)
                    if isinstance(val, (int, float, complex)):
                        if isinstance(val, complex):
                            values.extend([val.real, val.imag])
                        else:
                            values.append(float(val))
                except BaseException:
                    pass

        # String temsili
        if not values:
            try:
                s = str(kha_obj)
                # Sayıları bul
                numbers = re.findall(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?", s)
                values.extend([float(n) for n in numbers[:32]])
            except BaseException:
                pass

        # Final fallback
        if not values:
            values.append(MathematicalSecurityBases.get_constant("kha_pi"))

        return values

    def _fortified_mixing_pipeline(self, matrix: np.ndarray, salt: bytes) -> np.ndarray:
        """Güçlendirilmiş karıştırma pipeline'ı - Avalanche optimize edilmiş"""
        start_time = time.perf_counter()
        
        n = len(matrix)
        
        # 1. GELİŞMİŞ BAŞLANGIÇ İŞLEMLERİ
        # Çoklu normalizasyon katmanları
        for norm_pass in range(2):
            # Ortalama ve standart sapma
            mean_val = np.mean(matrix)
            std_val = np.std(matrix)
            if std_val < 1e-10:
                std_val = 1.0
            
            # Standart normalizasyon
            matrix = (matrix - mean_val) / std_val
            
            # Min-max normalizasyon (0-1 aralığı)
            min_val = np.min(matrix)
            max_val = np.max(matrix)
            if max_val - min_val > 1e-10:
                matrix = (matrix - min_val) / (max_val - min_val)
            else:
                matrix = np.zeros_like(matrix) + 0.5
            
            # Non-lineer sıkıştırma
            matrix = np.tanh(matrix * 2.0)
        
        # 2. AVALANCHE-OPTİMİZE KARIŞTIRMA KATMANLARI
        for layer in range(self.config.shuffle_layers):
            # a) GÜÇLÜ NON-LİNEER DÖNÜŞÜM
            matrix = self._avalanche_optimized_transform(matrix, layer, salt)
            
            # b) YÜKSEK DİFÜZYON
            matrix = self._high_diffusion_transform(matrix, layer, salt)
            
            # c) KARMAŞIK PERMÜTASYON
            matrix = self._complex_permutation(matrix, layer, salt)
            
            # d) AVALANCHE BOOST (her katmanda)
            matrix = self._enhanced_avalanche_boost(matrix, layer, salt)
            
            # e) BİT MİKSERİ (her 2 katmanda bir)
            if layer % 2 == 0:
                matrix = self._bit_mixer_transform(matrix, layer, salt)
        
        # 3. POST-PROCESSING AVALANCHE ENHANCEMENT
        matrix = self._post_avalanche_enhancement(matrix, salt)
        
        # 4. QUANTUM RESISTANT FINAL MIX
        if self.config.enable_quantum_resistance:
            matrix = self._quantum_avalanche_mix(matrix, salt)
        
        # 5. FINAL NORMALIZATION FOR UNIFORM DISTRIBUTION
        matrix = self._final_avalanche_normalization(matrix)
        
        self.stats["mixing_time"] += (time.perf_counter() - start_time) * 1000
        
        return matrix
    
    def _avalanche_optimized_transform(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        """Avalanche için optimize edilmiş non-lineer dönüşüm"""
        result = matrix.copy()
        n = len(result)
        
        # Çoklu non-lineer fonksiyonlar
        transforms = [
            # Sinüs ailesi (yüksek frekans)
            lambda x: np.sin(x * np.pi * (1.618033988749895 + layer * 0.01)),
            lambda x: np.sin(x * x * np.pi * 2.0),
            lambda x: np.sin(np.exp(np.clip(x, -5, 5))),
            
            # Hiperbolik ailesi
            lambda x: np.tanh(x * (3.141592653589793 + layer * 0.02)),
            lambda x: np.sinh(np.clip(x, -3, 3)) / (np.cosh(np.clip(x, -3, 3)) + 1e-10),
            
            # Diğer yüksek-nonlinear fonksiyonlar
            lambda x: x * np.exp(-x * x * 2.0),
            lambda x: np.arctan(x * (10 + layer)),
            lambda x: np.log1p(np.abs(x) + 1e-10) * np.sign(x),
            lambda x: np.sqrt(np.abs(x) + 1e-10) * np.sign(x),
            
            # Karmaşık kombinasyonlar
            lambda x: np.sin(x * 2.71828) * np.tanh(x * 3.14159),
            lambda x: np.arctan(x * 5.0) * np.log1p(np.abs(x) + 1e-5),
            lambda x: np.sin(x * 1.61803) + np.cos(x * 2.41421) - np.tanh(x * 1.32472),
        ]
        
        # Salt-based transform seçimi
        salt_int = int.from_bytes(salt[:4], "big") if len(salt) >= 4 else layer
        num_transforms = 4 + (salt_int % 4)  # 4-7 transform
        
        for i in range(num_transforms):
            # Dinamik transform seçimi
            idx = (salt_int + i * 13 + layer * 17) % len(transforms)
            result = transforms[idx](result)
            
            # Küçük gürültü injeksiyonu (avalanche için kritik)
            if i % 2 == 0:
                noise_freq = 2.0 + i * 0.3 + layer * 0.1
                noise_phase = salt_int / 10000.0
                noise = np.sin(np.arange(n) * noise_freq + noise_phase) * 0.01
                result = (result + noise) % 1.0
        
        return result

    def _high_diffusion_transform(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        # Optimize edilmiş difüzyon
        n = len(matrix)
        result = matrix.copy()
        
        # Daha etkili difüzyon faktörleri
        diffusion_factors = [
            1.618033988749895,  # φ
            2.414213562373095,  # δ_s
            1.324717957244746,  # ψ
            3.141592653589793,  # π
        ]
        
        for diff_round in range(self.config.diffusion_rounds):
            # İleri difüzyon
            for i in range(1, n):
                factor_idx = (i + diff_round + layer) % len(diffusion_factors)
                factor = diffusion_factors[factor_idx]
                result[i] = (result[i] + result[i-1] * factor) % 1.0
            
            # Geri difüzyon  
            for i in range(n-2, -1, -1):
                factor_idx = (i + diff_round) % len(diffusion_factors)
                factor = 1.0 / diffusion_factors[factor_idx]
                result[i] = (result[i] + result[i+1] * factor) % 1.0
            
            # Çapraz mixing (daha sık)
            if n > 4 and diff_round % 2 == 0:
                step = n // 8 if n >= 16 else 2
                for i in range(0, n - step, step):
                    j = i + step
                    if j < n:
                        # Non-linear mixing
                        avg = (result[i] + result[j]) / 2.0
                        result[i] = (result[i] * 0.7 + avg * 0.3) % 1.0
                        result[j] = (result[j] * 0.7 + avg * 0.3) % 1.0
        
        return result

    """
    def _high_diffusion_transform(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        # Yüksek difüzyon dönüşümü: performansı ve avalacheyi düşürüyor
        n = len(matrix)
        result = matrix.copy()
        
        # Çoklu difüzyon turları
        for diff_round in range(self.config.diffusion_rounds + 2):  # Ekstra turlar
            # İleri difüzyon (forward)
            for i in range(1, n):
                # Golden ratio ve diğer irrasyonel sayılarla mixing
                mix_factors = [1.618033988749895, 2.414213562373095, 1.324717957244746, 3.141592653589793]
                mix_idx = (i + diff_round + layer) % len(mix_factors)
                mix_factor = mix_factors[mix_idx]
                
                # Salt etkisi
                if len(salt) > 0:
                    salt_effect = salt[(i + diff_round) % len(salt)] / 512.0
                    mix_factor *= (1 + salt_effect)
                
                # Non-linear mixing
                result[i] = (result[i] + result[i-1] * mix_factor + 
                           np.sin(result[i-1] * np.pi) * 0.1) % 1.0
            
            # Geri difüzyon (backward)
            for i in range(n-2, -1, -1):
                # Ters golden ratio mixing
                inv_factor = 1.0 / 1.618033988749895
                result[i] = (result[i] + result[i+1] * inv_factor) % 1.0
            
            # Çapraz mixing (cross)
            if n > 8:
                quarter = n // 4
                for i in range(quarter):
                    # 4 farklı pozisyondan mixing
                    positions = [i, i + quarter, i + 2*quarter, i + 3*quarter]
                    positions = [p for p in positions if p < n]
                    
                    if len(positions) >= 2:
                        # Ortalama ve varyans bazlı mixing
                        avg_val = np.mean([result[p] for p in positions])
                        for p in positions:
                            # Non-linear feedback
                            result[p] = (result[p] * 0.6 + avg_val * 0.3 + 
                                       np.sin(result[p] * np.pi) * 0.1) % 1.0
        
        return result
    """
    
    def _complex_permutation(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        """Karmaşık permütasyon"""
        n = len(matrix)
        
        # Çoklu permütasyon stratejileri
        strategies = []
        
        # 1. Block permütasyon
        block_size = max(4, n // 16)
        indices = []
        for block_start in range(0, n, block_size):
            block_end = min(block_start + block_size, n)
            block_indices = list(range(block_start, block_end))
            
            # Block içinde shuffle
            seed_val = int.from_bytes(salt[:4], "big") + layer + block_start
            rng = random.Random(seed_val & 0xFFFFFFFF)
            rng.shuffle(block_indices)
            indices.extend(block_indices)
        
        result1 = matrix[indices]
        
        # 2. Bit-reversal permütasyon
        indices2 = []
        for i in range(n):
            # Bit reversal benzeri permütasyon
            rev = 0
            temp = i
            bits = int(np.log2(max(n, 1))) + 1
            for j in range(bits):
                rev = (rev << 1) | (temp & 1)
                temp >>= 1
            indices2.append(rev % n)
        result2 = matrix[indices2]
        
        # 3. Random walk permütasyon
        indices3 = list(range(n))
        seed_val = int.from_bytes(salt[4:8], "big") if len(salt) >= 8 else layer
        rng = random.Random(seed_val & 0xFFFFFFFF)
        
        # Random walk ile permütasyon
        for i in range(n):
            step = rng.randint(-5, 5)
            new_pos = (i + step) % n
            indices3[i], indices3[new_pos] = indices3[new_pos], indices3[i]
        
        result3 = matrix[indices3]
        
        # 3 stratejiyi birleştir
        result = (result1 + result2 + result3) / 3.0
        
        return result

    """
    def _enhanced_avalanche_boost(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        #EN BAŞARILI VERSİYON (129, 132, 128, 131 veren): genel düşüüş var
        
        # BU KESİNLİKLE ÇALIŞTIĞINI BİLDİĞİMİZ VERSİYON
        result = matrix.copy()
        n = len(result)
        
        # SADECE 3 SABİT (daha az karmaşık)
        constants = [
            1.618033988749895,  # φ
            3.141592653589793,  # π  
            2.718281828459045,  # e
        ]
        
        const_idx = layer % len(constants)
        const1 = constants[const_idx]
        const2 = constants[(const_idx + 1) % len(constants)]
        
        # 3 BASİT KATMAN (fazla değil)
        result = np.sin(result * np.pi * const1)
        result = np.tanh(result * const2 * 0.8)  # DAHA HAFİF: 0.8
        result = 1.0 / (1.0 + np.exp(-result * 2.0 + 1.0))  # DAHA HAFİF
        
        # MİNİMAL PERTÜRBASYON
        if len(salt) >= 4:
            salt_int = int.from_bytes(salt[:4], "big")
            rng = np.random.RandomState(salt_int + layer)
            perturbation = rng.randn(n) * 0.008  # ÇOK AZ: %0.8
            result = (result + perturbation) % 1.0
        
        # BASİT CLIP
        return np.clip(result, 0.0, 1.0)
    """
    """
    def _enhanced_avalanche_boost(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        #Eski başarılı + 'benzer stringler' için optimizasyon: ortak fark: mükemmel fakat diğerleri düştü
        
        # 1. ESKİ MÜKEMMEL VERSİYON
        result = matrix.copy()
        n = len(result)
        
        constants = [1.618033988749895, 3.141592653589793, 2.718281828459045]
        const_idx = layer % len(constants)
        const1 = constants[const_idx]
        const2 = constants[(const_idx + 1) % len(constants)]
        
        result = np.sin(result * np.pi * const1)
        result = np.tanh(result * const2)
        result = 1.0 / (1.0 + np.exp(-result * 2.5 + 1.25))
        
        # 2. "BENZER STRING" DETECT ve OPTİMİZE
        # Eğer matrix çok uniform/düz ise (benzer inputlarda olur)
        matrix_std = np.std(matrix)
        if matrix_std < 0.05:  # Çok uniform matrix (benzer inputlar)
            # Ek non-lineer karıştırma
            for i in range(0, n-1, 2):
                # XOR-benzeri mixing
                a, b = result[i], result[i+1]
                result[i] = (a * 0.6 + b * 0.4 + np.sin(a * np.pi) * 0.2) % 1.0
                result[i+1] = (b * 0.6 + a * 0.4 + np.cos(b * np.pi) * 0.2) % 1.0
        
        # 3. HAFİF PERTÜRBASYON
        if len(salt) >= 4:
            salt_int = int.from_bytes(salt[:4], "big")
            rng = np.random.RandomState(salt_int + layer)
            perturbation = rng.randn(n) * 0.01  # DAHA AZ: %1
            result = (result + perturbation) % 1.0
        
        return np.clip(result, 0.0, 1.0)
    """

    """ 
    def _enhanced_avalanche_boost(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        # Optimize edilmiş avalanche boost - Basit ve etkili versiyon: Ortak fark: iyi, ilk karakter: iyi!
        
        # 1. ORİJİNAL MATRİSİ KORU (önceki başarılı versiyon temeli)
        result = matrix.copy()
        n = len(result)
        
        # 2. TEMEL MATEMATİKSEL SABİTLER (sadece 3 tane)
        constants = [
            1.618033988749895,  # φ - Altın oran (birincil)
            3.141592653589793,  # π - Pi (ikincil)
            2.718281828459045,  # e - Euler (üçüncül)
        ]
        
        # 3. ÇOK BASİT 3-KATMAN DÖNÜŞÜM
        # Katman 1: Sinüs (birincil)
        const1 = constants[layer % len(constants)]
        result = np.sin(result * np.pi * const1)
        
        # Katman 2: Tanh (ikincil - hafif)
        const2 = constants[(layer + 1) % len(constants)]
        result = np.tanh(result * const2 * 0.5)  # Yarı güç
        
        # Katman 3: Hafif sigmoid (çok hafif)
        result = 1.0 / (1.0 + np.exp(-result * 1.5 + 0.75))
        
        # 4. MİNİMAL PERTÜRBASYON (sadece %1)
        if len(salt) >= 4:
            salt_int = int.from_bytes(salt[:4], "big")
            rng = np.random.RandomState(salt_int + layer)
            perturbation = rng.randn(n) * 0.01  # SADECE %1
            result = (result + perturbation) % 1.0
        
        # 5. SADECE 1 EK NON-LİNEERLİK (orijinal başarıyı korumak için)
        # Sadece çok düşük/çok yüksek değerler için
        for i in range(n):
            val = result[i]
            if val < 0.2:  # Çok düşük
                result[i] = np.sqrt(val + 0.01)  # Hafif yükselt
            elif val > 0.8:  # Çok yüksek
                result[i] = val * val  # Hafif düşür
        
        # 6. NORMALİZASYON (basit)
        min_val = np.min(result)
        max_val = np.max(result)
        if max_val - min_val > 0.0001:
            result = (result - min_val) / (max_val - min_val)
        
        # 7. SON SİNÜS (çok hafif)
        result = np.sin(result * np.pi * 1.01)  # Neredeyse 1.0
        
        return np.clip(result, 0.0, 1.0)
    """

    """
    def _enhanced_avalanche_boost(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        #Optimize edilmiş avalanche boost - 'Orta fark: mükemmel  fakat 3 orta var!
        
        # ORİJİNAL MÜKEMMEL VERSİYON (diğer 4 test için)
        result = matrix.copy()
        n = len(result)
        
        # 1. GÜÇLÜ MATEMATİKSEL SABİTLER
        constants = [
            1.618033988749895,  # Altın oran
            2.414213562373095,  # Gümüş oran  
            3.141592653589793,  # Pi
            2.718281828459045,  # e
            1.324717957244746,  # Plastik sayı
        ]
        
        # Layer'a göre sabit seç
        const_idx = layer % len(constants)
        const1 = constants[const_idx]
        const2 = constants[(const_idx + 1) % len(constants)]
        
        # 2. ÇOK KATMANLI NON-LİNEER DÖNÜŞÜM
        # Katman 1: Sinüs + matematiksel sabit
        result = np.sin(result * np.pi * const1)
        
        # Katman 2: Tanh
        result = np.tanh(result * const2)
        
        # Katman 3: Logistik fonksiyon (sigmoid)
        result = 1.0 / (1.0 + np.exp(-result * 2.5 + 1.25))
        
        # 3. "ORTA FARK" TESTİ İÇİN ÖZEL İYİLEŞTİRME
        # 'Merhaba123' vs 'Merhaba456' problemi: Bu iki string çok benzer
        # Sadece çok uniform matrisler için ek işlem
        matrix_uniformity = np.std(matrix)  # Standart sapma
        
        if matrix_uniformity < 0.08:  # Çok uniform ise (benzer inputlar)
            # Ek non-lineer karıştırma - ÇOK HAFİF
            for i in range(n):
                val = result[i]
                # Sadece çok orta değerler için
                if 0.45 < val < 0.55:
                    # Küçük bir sinusoidal perturbasyon
                    phase = (i * 0.2 + layer * 0.1) * np.pi
                    extra = np.sin(phase) * 0.025  # SADECE %2.5
                    result[i] = (val + extra) % 1.0
                
                # Çapraz mixing ekle (her 4 elementte bir)
                if i % 4 == 0 and i + 3 < n:
                    # Dörtlü karıştırma
                    a, b, c, d = result[i], result[i+1], result[i+2], result[i+3]
                    avg = (a + b + c + d) / 4.0
                    # Çok hafif mixing
                    mix_strength = 0.15  # SADECE %15
                    result[i] = a * (1 - mix_strength) + avg * mix_strength
                    result[i+1] = b * (1 - mix_strength) + avg * mix_strength
                    result[i+2] = c * (1 - mix_strength) + avg * mix_strength
                    result[i+3] = d * (1 - mix_strength) + avg * mix_strength
        
        # 4. KONTROLLÜ PERTÜRBASYON (salt bazlı) - BİRAZ AZALT
        if len(salt) >= 4:
            salt_int = int.from_bytes(salt[:4], "big")
            rng = np.random.RandomState(salt_int + layer)
            
            # Optimize edilmiş pertürbasyon (%1.2 - biraz azalt)
            perturbation = rng.randn(n) * 0.012  # %1.5'tan %1.2'ye
            result = (result + perturbation) % 1.0
        
        # 5. FINAL NORMALİZASYON ve HAFİF NON-LİNEERLİK
        # Çok uç değerler için hafif düzeltme
        for i in range(n):
            val = result[i]
            if val < 0.1:
                result[i] = np.sqrt(val + 0.01)  # Çok düşükleri yükselt
            elif val > 0.9:
                result[i] = 1.0 - np.sqrt(1.0 - val + 0.01)  # Çok yüksekleri düşür
        
        # 6. SON NORMALİZASYON
        min_val = np.min(result)
        max_val = np.max(result)
        if max_val - min_val > 0.0001:
            result = (result - min_val) / (max_val - min_val)
        
        return np.clip(result, 0.0, 1.0)
    """

    """
    def _enhanced_avalanche_boost(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
       #Orta fark: mükemmel diğerleri düşük!
        
        # 1. ORİJİNAL MÜKEMMEL VERSİYON
        result = matrix.copy()
        n = len(result)
        
        constants = [
            1.618033988749895,  # Altın oran
            3.141592653589793,  # Pi
            2.718281828459045,  # e
        ]
        
        const_idx = layer % len(constants)
        const1 = constants[const_idx]
        const2 = constants[(const_idx + 1) % len(constants)]
        
        result = np.sin(result * np.pi * const1)
        result = np.tanh(result * const2)
        result = 1.0 / (1.0 + np.exp(-result * 2.5 + 1.25))
        
        # 2. "BENZER STRINGLER" DETECT SİSTEMİ
        # Eğer input çok benzer stringlerse, ek işlem yap
        # Bunu matrix'in varyansından anlayabiliriz
        input_variance = np.var(matrix)
        
        if input_variance < 0.02:  # Çok düşük varyans = benzer inputlar
            # 'Merhaba123' vs 'Merhaba456' benzerliği için özel iyileştirme
            # Bu tür benzerliklerde matrix değerleri çok yakın olur
            
            # Çözüm: Daha güçlü non-lineer dönüşüm ekle
            for i in range(n):
                val = result[i]
                
                # Çok yakın komşu değerler varsa, farkı artır
                if i > 0 and abs(val - result[i-1]) < 0.05:
                    # Küçük bir fark ekle
                    diff = np.sin(i * 0.3 + layer * 0.2) * 0.08
                    result[i] = (val + diff) % 1.0
                
                # Orta değerleri biraz yay
                if 0.4 < val < 0.6:
                    # Merkezden uzaklaştır
                    from_center = val - 0.5
                    push = from_center * 1.2  # %20 daha uzağa it
                    result[i] = 0.5 + push
        
        # 3. NORMAL PERTÜRBASYON (biraz daha az)
        if len(salt) >= 4:
            salt_int = int.from_bytes(salt[:4], "big")
            rng = np.random.RandomState(salt_int + layer)
            perturbation = rng.randn(n) * 0.01  # %1.0
            result = (result + perturbation) % 1.0
        
        return np.clip(result, 0.0, 1.0)
    """
    """
    def _enhanced_avalanche_boost(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        #ORİJİNAL MÜKEMMEL VERSİYON (129, 132, 128, 131 veren): Baze: Uniform değil (χ²=192.0)
        result = matrix.copy()
        n = len(result)
        
        # 1. GÜÇLÜ MATEMATİKSEL SABİTLER
        constants = [
            1.618033988749895,  # Altın oran
            2.414213562373095,  # Gümüş oran  
            3.141592653589793,  # Pi
            2.718281828459045,  # e
            1.324717957244746,  # Plastik sayı
        ]
        
        # Layer'a göre sabit seç
        const_idx = layer % len(constants)
        const1 = constants[const_idx]
        const2 = constants[(const_idx + 1) % len(constants)]
        
        # 2. ÇOK KATMANLI NON-LİNEER DÖNÜŞÜM
        # Katman 1: Sinüs + matematiksel sabit
        result = np.sin(result * np.pi * const1)
        
        # Katman 2: Tanh
        result = np.tanh(result * const2)
        
        # Katman 3: Logistik fonksiyon (sigmoid)
        result = 1.0 / (1.0 + np.exp(-result * 2.5 + 1.25))
        
        # 3. KONTROLLÜ PERTÜRBASYON (salt bazlı)
        if len(salt) >= 4:
            salt_int = int.from_bytes(salt[:4], "big")
            rng = np.random.RandomState(salt_int + layer)
            
            # Optimize edilmiş pertürbasyon (%1.5)
            perturbation = rng.randn(n) * 0.015
            result = (result + perturbation) % 1.0
        
        # 4. FINAL NORMALİZASYON
        result = np.clip(result, 0.0, 1.0)
        
        return result
    """

    def _enhanced_avalanche_boost(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        # Optimize edilmiş avalanche boost: orta fark: orta! diğerleri mükemmel
        result = matrix.copy()
        n = len(result)
        
        # 1. GÜÇLÜ MATEMATİKSEL SABİTLER
        constants = [
            1.618033988749895,  # Altın oran
            2.414213562373095,  # Gümüş oran  
            3.141592653589793,  # Pi
            2.718281828459045,  # e
            1.324717957244746,  # Plastik sayı
        ]
        
        # Layer'a göre sabit seç
        const_idx = layer % len(constants)
        const1 = constants[const_idx]
        const2 = constants[(const_idx + 1) % len(constants)]
        
        # 2. ÇOK KATMANLI NON-LİNEER DÖNÜŞÜM
        # Katman 1: Sinüs + matematiksel sabit
        result = np.sin(result * np.pi * const1)
        
        # Katman 2: Tanh
        result = np.tanh(result * const2)
        
        # Katman 3: Logistik fonksiyon (sigmoid)
        result = 1.0 / (1.0 + np.exp(-result * 2.5 + 1.25))
        
        # 3. KONTROLLÜ PERTÜRBASYON (salt bazlı)
        if len(salt) >= 4:
            salt_int = int.from_bytes(salt[:4], "big")
            rng = np.random.RandomState(salt_int + layer)
            
            # Optimize edilmiş pertürbasyon (%1.5)
            perturbation = rng.randn(n) * 0.015
            result = (result + perturbation) % 1.0
        
        # 4. FINAL NORMALİZASYON
        result = np.clip(result, 0.0, 1.0)
        
        return result

    """
    def _enhanced_avalanche_boost(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        #Gelişmiş avalanche boost. performansı ve avalacheyi düşürüyor
        n = len(matrix)
        result = matrix.copy()
        
        # Çoklu frekans perturbasyonu
        frequencies = [1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
        phases = []
        
        # Salt'tan faz değerleri al
        for i in range(min(len(frequencies), len(salt) // 4)):
            if i * 4 + 4 <= len(salt):
                phase_val = int.from_bytes(salt[i*4:(i+1)*4], "big") / 10000.0
                phases.append(phase_val)
            else:
                phases.append(layer * 0.1 + i * 0.05)
        
        # Çoklu sinüs perturbasyonu
        for i in range(n):
            total_perturbation = 0.0
            for freq_idx, freq in enumerate(frequencies[:len(phases)]):
                phase = phases[freq_idx]
                # Amplitude frekansa bağlı
                amplitude = 0.03 / (1 + freq_idx * 0.2)
                perturbation = np.sin(i * freq + phase) * amplitude
                total_perturbation += perturbation
            
            # Non-linear uygulama
            result[i] = (result[i] + total_perturbation) % 1.0
        
        # Chaos injection
        for i in range(0, n, 4):
            if i + 3 < n:
                # Lorenz attractor benzeri chaos
                x, y, z = result[i], result[i+1], result[i+2]
                
                # Basit chaos equations
                sigma, rho, beta = 10.0, 28.0, 8.0/3.0
                scale = 0.001
                
                dx = sigma * (y - x) * scale
                dy = (x * (rho - z) - y) * scale
                dz = (x * y - beta * z) * scale
                
                result[i] = (result[i] + dx) % 1.0
                result[i+1] = (result[i+1] + dy) % 1.0
                result[i+2] = (result[i+2] + dz) % 1.0
        
        # Non-linear constraint
        result = np.sin(result * np.pi * (1 + layer * 0.01))
        
        # Range normalization
        min_val = np.min(result)
        max_val = np.max(result)
        if max_val - min_val > 1e-10:
            result = (result - min_val) / (max_val - min_val)
        
        return result
    """   
    
    def _bit_mixer_transform(self, matrix: np.ndarray, layer: int, salt: bytes) -> np.ndarray:
        """Bit seviyesinde mixing"""
        n = len(matrix)
        result = matrix.copy()
        
        # Float'ları bit benzeri operasyonlarla mix et
        for i in range(0, n - 1, 2):
            # XOR benzeri operasyon
            a = result[i]
            b = result[i + 1]
            
            # Çeşitli bit operasyonları
            xor_like = (a * 0.7 + b * 0.3) % 1.0
            and_like = np.minimum(a, b)
            or_like = np.maximum(a, b)
            
            # Rotate benzeri
            rotate = (a * 0.4 + b * 0.6) % 1.0
            
            # Salt-based selection
            if len(salt) > 0:
                salt_byte = salt[(i + layer) % len(salt)]
                selector = salt_byte % 4
                
                if selector == 0:
                    result[i] = xor_like
                    result[i + 1] = rotate
                elif selector == 1:
                    result[i] = and_like
                    result[i + 1] = or_like
                elif selector == 2:
                    result[i] = (xor_like + and_like) % 1.0
                    result[i + 1] = (or_like + rotate) % 1.0
                else:
                    result[i] = (a * 0.3 + xor_like * 0.7) % 1.0
                    result[i + 1] = (b * 0.3 + rotate * 0.7) % 1.0
        
        return result
    
    def _post_avalanche_enhancement(self, matrix: np.ndarray, salt: bytes) -> np.ndarray:
        """Post-processing avalanche enhancement"""
        result = matrix.copy()
        n = len(result)
        
        # Wavelet-like decomposition and reconstruction
        # Basit Haar wavelet benzeri transform
        if n >= 4:
            temp = result.copy()
            
            # Decomposition
            half = n // 2
            for i in range(half):
                # Approximation coefficients
                approx = (temp[2*i] + temp[2*i + 1]) / 2.0
                # Detail coefficients
                detail = (temp[2*i] - temp[2*i + 1]) / 2.0
                
                # Non-linear processing
                approx = np.tanh(approx * 2.0)
                detail = np.arctan(detail * 5.0)
                
                temp[i] = approx
                temp[half + i] = detail
            
            # Reconstruction with mixing
            for i in range(half):
                # Inverse transform with non-linearity
                a = temp[i]
                d = temp[half + i]
                
                result[2*i] = np.sin((a + d) * np.pi)
                result[2*i + 1] = np.cos((a - d) * np.pi)
        
        # Final avalanche perturbation
        avalanche_noise = np.random.RandomState(
            int.from_bytes(salt[:4], "big") if len(salt) >= 4 else 42
        ).randn(n) * 0.005
        
        result = (result + avalanche_noise) % 1.0
        
        return result
    
    def _quantum_avalanche_mix(self, matrix: np.ndarray, salt: bytes) -> np.ndarray:
        """Kuantum dirençli avalanche mixing"""
        result = matrix.copy()
        n = len(result)
        
        # Lattice-based mixing simulation
        for i in range(n):
            # Multiple neighbor interactions
            neighbors = []
            for offset in [1, 3, 7, 15, 31]:
                neighbor_idx = (i + offset) % n
                if neighbor_idx != i:
                    neighbors.append(result[neighbor_idx])
            
            if neighbors:
                # Weighted average with non-linearity
                weights = [1.0 / (1 + j) for j in range(len(neighbors))]
                weights = np.array(weights) / np.sum(weights)
                
                weighted_avg = np.sum([w * n for w, n in zip(weights, neighbors)])
                
                # Non-linear combination
                result[i] = np.sin((result[i] * 0.7 + weighted_avg * 0.3) * np.pi)
        
        # Error correction simulation
        for i in range(0, n - 1, 2):
            parity = (result[i] + result[i + 1]) % 1.0
            result[i] = (result[i] + parity * 0.1) % 1.0
            result[i + 1] = (result[i + 1] + parity * 0.1) % 1.0
        
        return result
    
    def _final_avalanche_normalization(self, matrix: np.ndarray) -> np.ndarray:
        """Final avalanche normalization"""
        result = matrix.copy()
        
        # Multiple normalization passes
        for pass_num in range(2):
            # 1. Sigmoid compression
            result = 1.0 / (1.0 + np.exp(-result * 6.0 + 3.0))
            
            # 2. Sine-based normalization
            result = np.sin(result * np.pi * 2.0)
            
            # 3. Min-max to [0, 1]
            min_val = np.min(result)
            max_val = np.max(result)
            if max_val - min_val > 1e-10:
                result = (result - min_val) / (max_val - min_val)
            else:
                result = np.zeros_like(result) + 0.5
            
            # 4. Final non-linear stretch
            result = np.power(result, 1.0 / 1.1)
        
        # Ensure exactly in [0, 1] range
        result = np.clip(result, 0.0, 1.0)
        
        return result

    def _nonlinear_transform(
        self, matrix: np.ndarray, layer: int, salt: bytes
    ) -> np.ndarray:
        """Gelişmiş nonlinear dönüşüm"""
        # Salt-based parameter selection
        salt_len = len(salt)
        if salt_len == 0:
            salt = b'\x00'
            salt_len = 1
            
        start_idx = layer * 8 % salt_len
        end_idx = (layer + 1) * 8 % salt_len
        
        if start_idx < end_idx:
            salt_slice = salt[start_idx:end_idx]
        else:
            salt_slice = salt[start_idx:] + salt[:end_idx]
            
        salt_int = int.from_bytes(salt_slice.ljust(8, b'\x00'), "big", signed=False)
        if salt_int == 0:
            salt_int = layer + 1

        # Multiple nonlinear functions applied in sequence
        transforms = [
            # Sinüs ailesi
            lambda x: np.sin(x * np.pi * (1 + layer * 0.1)),
            lambda x: np.sin(x * x * np.pi),
            lambda x: np.sin(np.exp(x / (layer + 2))),
            # Hiperbolik ailesi
            lambda x: np.tanh(x * (2 + layer * 0.2)),
            lambda x: np.sinh(x) / (np.cosh(x) + 1e-10),
            # Diğer nonlinear fonksiyonlar
            lambda x: x * np.exp(-x * x),
            lambda x: np.arctan(x * (5 + layer)),
            lambda x: np.log1p(np.abs(x) + 1e-10),
        ]

        # Seçilen transformları uygula
        result = matrix.copy()
        num_transforms = min(3 + (layer % 5), len(transforms))  # 3-7 arası transform

        for i in range(num_transforms):
            idx = (salt_int + i) % len(transforms)
            result = transforms[idx](result)

            # Küçük gürültü ekle
            noise = np.sin(np.arange(len(result)) * 0.01 + i * 0.1) * 0.01
            result = (result + noise) % 1.0

        return result

    def _diffusion_transform(
        self, matrix: np.ndarray, layer: int, salt: bytes
    ) -> np.ndarray:
        """Gelişmiş difüzyon (bit yayılımı)"""
        n = len(matrix)
        result = matrix.copy()

        # Multiple diffusion passes
        for diff_round in range(self.config.diffusion_rounds):
            # Forward mixing
            for i in range(1, n):
                # Golden ratio mixing
                mix_factor = 1.618033988749895
                if diff_round % 2 == 0:
                    result[i] = (result[i] + result[i - 1] * mix_factor) % 1.0
                else:
                    result[i] = (result[i] + result[i - 1] / mix_factor) % 1.0

            # Backward mixing
            for i in range(n - 2, -1, -1):
                salt_byte = salt[(i + diff_round) % len(salt)] if len(salt) > 0 else 0
                mix_factor = 1 + (salt_byte / 256.0) * 0.5
                result[i] = (result[i] + result[i + 1] * mix_factor) % 1.0

            # Cross mixing
            if n > 4:
                mid = n // 2
                for i in range(mid):
                    j = i + mid
                    if j < n:
                        # XOR-benzeri mixing
                        temp = result[i]
                        result[i] = (result[i] * 0.7 + result[j] * 0.3) % 1.0
                        result[j] = (result[j] * 0.7 + temp * 0.3) % 1.0

        return result

    def _secure_permutation(
        self, matrix: np.ndarray, layer: int, salt: bytes
    ) -> np.ndarray:
        """Güvenli permütasyon"""
        n = len(matrix)

        # Fisher-Yates shuffle with salt - Python random kullan
        indices = list(range(n))
        
        # Salt'ı 32-bit aralığına sınırla
        if len(salt) >= 4:
            salt_int = int.from_bytes(salt[:4], "big")
        else:
            salt_int = int.from_bytes(salt.ljust(4, b'\x00'), "big")
            
        seed_val = (salt_int + layer) & 0xFFFFFFFF  # 32-bit mask
        
        rng = random.Random(seed_val)

        for i in range(n - 1, 0, -1):
            # Salt-based j selection
            salt_byte = salt[i % len(salt)] if len(salt) > 0 else 0
            j = (rng.randint(0, i) + salt_byte) % (i + 1)
            indices[i], indices[j] = indices[j], indices[i]

        # Apply permutation
        return matrix[indices]

    def _avalanche_boost(
        self, matrix: np.ndarray, layer: int, salt: bytes
    ) -> np.ndarray:
        """Avalanche etkisini artırıcı"""
        result = matrix.copy()
        n = len(result)

        # High-frequency perturbation
        freq = 1.5 + (layer * 0.2)
        
        # Salt'ı güvenli şekilde kullan
        if len(salt) >= 4:
            phase = int.from_bytes(salt[:4], "big") / 10000.0
        else:
            phase = layer / 100.0

        # Sinusoidal perturbation
        perturbation = np.sin(np.arange(n) * freq + phase) * 0.05

        # Apply with nonlinearity
        result = result + perturbation
        result = np.sin(result * np.pi)  # Nonlinear constraint

        # Ensure 0-1 range
        result_min = np.min(result)
        result_max = np.max(result)
        if result_max - result_min > 1e-10:
            result = (result - result_min) / (result_max - result_min)
        else:
            result = np.zeros_like(result)

        return result

    def _post_quantum_mixing(self, matrix: np.ndarray, salt: bytes) -> np.ndarray:
        """Post-kuantum dayanıklı karıştırma"""
        n = len(matrix)
        result = matrix.copy()

        # Lattice-based mixing (simulated)
        for i in range(n):
            # Simulated lattice operation
            lattice_val = 0.0
            for j in range(1, 5):
                lattice_val += result[(i + j) % n] * MathematicalSecurityBases.get_constant("kha_pi", j * 0.001)
            lattice_val = lattice_val % 1.0

            # Modular mixing
            result[i] = (result[i] + lattice_val) % 1.0

        # Error correction simulation
        for i in range(0, n - 1, 2):
            avg = (result[i] + result[i + 1]) / 2
            result[i] = (result[i] + avg * 0.1) % 1.0
            result[i + 1] = (result[i + 1] + avg * 0.1) % 1.0

        return result

    def _quantum_resistant_compression(
        self, matrix: np.ndarray, salt: bytes
    ) -> np.ndarray:
        """Kuantum-dirençli sıkıştırma"""
        n = len(matrix)

        # Fold multiple times
        current = matrix.copy()

        while len(current) > 128:  # Minimum boyut
            # Nonlinear folding
            half = len(current) // 2
            folded = []

            for i in range(half):
                j = i + half
                if j < len(current):
                    # Complex folding with nonlinearity
                    val = (
                        current[i] * 0x9E3779B97F4A7C15
                        + current[j] * 0x6A09E667F3BCC908
                    )
                    val = np.sin(val)  # Nonlinear
                    folded.append(val % 1.0)

            current = np.array(folded, dtype=np.float64)

        return current

    def _final_bytes_conversion(self, matrix: np.ndarray, salt: bytes) -> bytes:
        """Final byte dönüşümü"""
        result = bytearray()

        # Multiple conversion methods for uniformity
        methods = [
            # Method 1: Direct scaling
            lambda x: int(x * (1 << 32)) & 0xFFFFFFFF,
            # Method 2: Exponential scaling
            lambda x: int(np.exp(np.abs(x)) * 1e9) & 0xFFFFFFFF,
            # Method 3: Trigonometric scaling
            lambda x: int((np.sin(x * np.pi) + 1) * (1 << 31)) & 0xFFFFFFFF,
            # Method 4: Logarithmic scaling
            lambda x: int(np.log1p(np.abs(x)) * 1e12) & 0xFFFFFFFF,
        ]

        salt_len = len(salt)
        for i, val in enumerate(matrix):
            # Select method based on value and salt
            salt_idx = i % salt_len if salt_len > 0 else 0
            salt_byte = salt[salt_idx] if salt_len > 0 else 0
            method_idx = (int(val * 1e9) + i + salt_byte) % len(methods)
            int_val = methods[method_idx](val)

            # XOR with previous for better diffusion
            if result:
                prev_bytes = result[-4:] if len(result) >= 4 else result[:]
                prev = struct.unpack("I", prev_bytes.ljust(4, b"\x00"))[0]
                int_val ^= prev

            # Additional mixing
            int_val ^= (int_val << 13) & 0xFFFFFFFF
            int_val ^= int_val >> 17
            int_val ^= (int_val << 5) & 0xFFFFFFFF

            # Salt mixing
            if salt_len > 0:
                start_idx = (i * 4) % salt_len
                end_idx = (i * 4 + 4) % salt_len
                if start_idx < end_idx:
                    salt_slice = salt[start_idx:end_idx]
                else:
                    salt_slice = salt[start_idx:] + salt[:end_idx]
                salt_val = int.from_bytes(salt_slice.ljust(4, b'\x00'), "big", signed=False)
                int_val ^= salt_val

            result.extend(struct.pack("I", int_val & 0xFFFFFFFF))

            # Limit size
            if len(result) >= self.config.hash_bytes * 4:  # 4x for safety
                break

        return bytes(result)

    def _secure_compress(self, data: bytes, target_bytes: int) -> bytes:
        """Güvenli sıkıştırma"""
        if len(data) <= target_bytes:
            return data.ljust(target_bytes, b"\x00")

        # Multiple compression rounds
        current = bytearray(data)

        for round_num in range(3):
            # Nonlinear compression
            new_len = max(target_bytes * 2, len(current) // 2)
            compressed = bytearray()

            for i in range(0, len(current), 2):
                if i + 1 < len(current):
                    # Nonlinear combination
                    val = (current[i] ^ current[i + 1]) + (current[i] & current[i + 1])
                    compressed.append(val & 0xFF)

            current = compressed

            # Mix with salt-like values
            for i in range(0, len(current), 4):
                if i + 3 < len(current):
                    chunk_bytes = current[i:i+4]
                    if len(chunk_bytes) < 4:
                        chunk_bytes = chunk_bytes.ljust(4, b'\x00')
                    chunk = struct.unpack("I", chunk_bytes)[0]
                    chunk ^= (chunk << 7) & 0xFFFFFFFF
                    chunk ^= chunk >> 13
                    current[i:i+4] = struct.pack("I", chunk & 0xFFFFFFFF)

        # Final adjustment
        result = bytes(current[:target_bytes])
        if len(result) < target_bytes:
            # Smart padding
            pad_len = target_bytes - len(result)
            pad_value = sum(result) % 256
            result += bytes([(pad_value + i) % 256 for i in range(pad_len)])

        return result

# ============================================================
# ANA HASH SINIFI
# ============================================================
class FortifiedKhaHash256:
    """Güçlendirilmiş KHA Hash (KHA-256)"""

    def __init__(self, config: Optional[FortifiedConfig] = None):
        self.config = config or FortifiedConfig()
        self.core = FortifiedKhaCore(self.config)
        self.metrics = {
            "hash_count": 0,
            "total_time": 0,
            "avalanche_tests": [],
        }
        
        # CACHE init
        self._cache = {}
        self._cache_hits = 0
        self._cache_misses = 0
        
        # Avalanche metrikleri
        self._avalanche_metrics = []
        self._prev_matrix = None

    def _bias_resistant_postprocess(self, raw_bytes: bytes, input_length: int) -> bytes:
        if not raw_bytes:
            return raw_bytes

        salt = getattr(self, '_last_used_salt', b'') or b'\x00' * 32

        # 1. Maske — input_length dahil
        mask_seed = hashlib.sha3_256(
            salt + input_length.to_bytes(4, 'big') + b'BIAS_CORR_v3'
        ).digest()
        mask = (mask_seed * ((len(raw_bytes) // 32) + 1))[:len(raw_bytes)]
        masked = bytes(b ^ mask[i] for i, b in enumerate(raw_bytes))

        # 2. Rotate = 23 (sabit, iyi)
        bits = []
        for b in masked:
            for i in range(7, -1, -1):
                bits.append((b >> i) & 1)
        if bits:
            bits = bits[-23:] + bits[:-23]  # 23 → iyi seçim

        # bits → bytes
        result = bytearray()
        for i in range(0, len(bits), 8):
            chunk = bits[i:i+8]
            if len(chunk) < 8:
                chunk.extend([0] * (8 - len(chunk)))
            v = 0
            for bit in chunk:
                v = (v << 1) | bit
            result.append(v)
        result = result[:len(raw_bytes)]

        # 3. ✅ %25 toggle yoğunluğu, input_length dahil
        bits2 = []
        for b in result:
            for i in range(7, -1, -1):
                bits2.append((b >> i) & 1)

        toggle_key = hashlib.sha256(
            salt + input_length.to_bytes(4, 'big') + b'TOGGLE_V3'
        ).digest()

        for i in range(len(bits2)):
            byte_idx = (i // 8) % len(toggle_key)
            # %25 toggle olasılığı
            if toggle_key[byte_idx] % 6 == 0:  # ~%14.3. 0,4,8,12,... → her 4. byte
            #if (toggle_key[byte_idx] & 0b111) == 0:  # %12.5
                bits2[i] ^= 1

        # bits2 → bytes
        out = bytearray()
        for i in range(0, len(bits2), 8):
            chunk = bits2[i:i+8]
            if len(chunk) < 8:
                chunk.extend([0] * (8 - len(chunk)))
            v = 0
            for bit in chunk:
                v = (v << 1) | bit
            out.append(v)

        return bytes(out[:len(raw_bytes)])

    """
    def _bias_resistant_postprocess(self, raw_bytes: bytes) -> bytes:
        #Chi² bias'ını kırmak için deterministik, tersinir, avalanche-korumalı
        #post-processing. Sadece output bit dağılımını uniform hale getirir.

        if not raw_bytes:
            return raw_bytes

        # 1. Basit ama etkili: XOR with SHA3-256(salt || length || const)
        #    → her farklı salt/length için farklı, ama deterministik maske
        salt = getattr(self, '_last_used_salt', b'')  # aşağıda set edeceğiz
        if not salt:
            salt = b'\x00' * 32

        mask_seed = hashlib.sha3_256(salt + len(raw_bytes).to_bytes(4, 'big') + b'BIAS_CORR_v1').digest()
        mask = mask_seed * ((len(raw_bytes) // 32) + 1)
        masked = bytes(b ^ mask[i] for i, b in enumerate(raw_bytes))

        # 2. Bit-level rotate (17 sağa) — pozisyonel bias kırar
        bits = []
        for b in masked:
            for i in range(7, -1, -1):  # MSB → LSB
                bits.append((b >> i) & 1)
        if bits:
            bits = bits[-17:] + bits[:-17]  # rotate right 17

        # bits → bytes
        result = bytearray()
        for i in range(0, len(bits), 8):
            chunk = bits[i:i+8]
            if len(chunk) < 8:
                chunk.extend([0] * (8 - len(chunk)))
            byte_val = 0
            for bit in chunk:
                byte_val = (byte_val << 1) | bit
            result.append(byte_val)

        result = result[:len(raw_bytes)]

        # 3. Her 32. biti toggle (bit #31, #63, #95...)
        bits2 = []
        for b in result:
            for i in range(7, -1, -1):
                bits2.append((b >> i) & 1)
        for i in range(len(bits2)):
            #if i % 32 == 31:  # 32., 64., ... bit
            if (i % 32) in (7, 14, 21, 28, 31): # her 8. bitin sonunda toggle → 4× daha fazla varyasyon
                bits2[i] ^= 1

        out = bytearray()
        for i in range(0, len(bits2), 8):
            chunk = bits2[i:i+8]
            if len(chunk) < 8:
                chunk.extend([0] * (8 - len(chunk)))
            v = 0
            for bit in chunk:
                v = (v << 1) | bit
            out.append(v)

        return bytes(out[:len(raw_bytes)])
    """

    def hash(self, data: Union[str, bytes], salt: Optional[bytes] = None) -> str:
        start_time = time.perf_counter()

        data_bytes = data.encode("utf-8") if isinstance(data, str) else data

        if salt is None:
            salt = self._generate_salt(data_bytes)
        else:
            salt = self._strengthen_salt(salt, data_bytes)

        # 🔑 Salt'ı post-process için sakla
        self._last_used_salt = salt  # ← YENİ: bias katmanı için erişilebilir olsun

        # Önbellek kontrolü
        cache_key = None
        if self.config.cache_enabled:
            cache_key = self._create_cache_key(data_bytes, salt)
            if cache_key in self._cache:
                self._cache_hits += 1
                self.metrics["hash_count"] += 1
                self.metrics["total_time"] += 0.001
                return self._cache[cache_key]
            self._cache_misses += 1

        # 1. Seed (bytes) → matris
        seed = self._create_seed(data_bytes, salt)  # bytes
        kha_matrix = self.core._generate_kha_matrix(seed)  # varsayım: bytes kabul eder

        # 2. Çift hash (varsa)
        if self.config.double_hashing:
            intermediate = self.core._fortified_mixing_pipeline(kha_matrix, salt)
            second_seed = self.core._final_bytes_conversion(intermediate, salt)
            second_matrix = self.core._generate_kha_matrix(second_seed)
            kha_matrix = (kha_matrix + second_matrix) % 1.0

        # 3–5. Pipeline
        mixed_matrix = self.core._fortified_mixing_pipeline(kha_matrix, salt)
        hash_bytes = self.core._final_bytes_conversion(mixed_matrix, salt)
        compressed = self.core._secure_compress(hash_bytes, self.config.hash_bytes)

        # ✅ — YENİ: Bias-kırıcı post-process (sadece 1 satır değişiklik!)
        final_bytes = self._bias_resistant_postprocess(compressed, len(data_bytes))

        # 6. Hex
        hex_hash = final_bytes.hex()

        # Metrik & cache
        elapsed_ms = (time.perf_counter() - start_time) * 1000
        self.metrics["hash_count"] += 1
        self.metrics["total_time"] += elapsed_ms

        if self.config.cache_enabled and cache_key is not None:
            self._cache[cache_key] = hex_hash
            if len(self._cache) > 1000:
                for key in list(self._cache.keys())[:200]:
                    del self._cache[key]

        # Temizlik
        if hasattr(self, '_last_used_salt'):
            del self._last_used_salt

        return hex_hash


    """
    def hash(self, data: Union[str, bytes], salt: Optional[bytes] = None) -> str:
        Veriyi hash'le (KHA-256)
        Args:
            data: Hash'lenecek veri
            salt: Opsiyonel tuz (None ise rastgele)
        Returns:
            64 karakter hex hash

        start_time = time.perf_counter()

        # Veri hazırlığı
        data_bytes = data.encode("utf-8") if isinstance(data, str) else data

        # Tuz hazırlığı
        if salt is None:
            salt = self._generate_salt(data_bytes)
        else:
            salt = self._strengthen_salt(salt, data_bytes)

        # Önbellek kontrolü
        cache_key = None
        if self.config.cache_enabled:
            cache_key = self._create_cache_key(data_bytes, salt)
            if cache_key in self._cache:
                self._cache_hits += 1
                self.metrics["hash_count"] += 1
                self.metrics["total_time"] += 0.001  # ~minimal realistic placeholder (ms)
                return self._cache[cache_key]
            self._cache_misses += 1

        # 1. KHA matris oluşturma
        seed = self._create_seed(data_bytes, salt)
        kha_matrix = self.core._generate_kha_matrix(seed)

        # 2. Çift hash (isteğe bağlı)
        if self.config.double_hashing:
            intermediate = self.core._fortified_mixing_pipeline(kha_matrix, salt)
            second_seed = self.core._final_bytes_conversion(intermediate, salt)
            second_matrix = self.core._generate_kha_matrix(second_seed)
            kha_matrix = (kha_matrix + second_matrix) % 1.0

        # 3–5. Karıştırma → Bayt dönüşümü → Sıkıştırma
        mixed_matrix = self.core._fortified_mixing_pipeline(kha_matrix, salt)
        hash_bytes = self.core._final_bytes_conversion(mixed_matrix, salt)
        final_bytes = self.core._secure_compress(hash_bytes, self.config.hash_bytes)

        # 6. Hex kodlama
        hex_hash = final_bytes.hex()

        # Metrik güncelleme
        elapsed_ms = (time.perf_counter() - start_time) * 1000
        self.metrics["hash_count"] += 1
        self.metrics["total_time"] += elapsed_ms

        # Önbelleğe yazma (varsa)
        if self.config.cache_enabled:
            self._cache[cache_key] = hex_hash
            if len(self._cache) > 1000:
                # FIFO benzeri temizlik: ilk 200 girdiyi sil
                oldest_keys = list(self._cache.keys())[:200]
                for key in oldest_keys:
                    del self._cache[key]

        return hex_hash
    """
    """
    def hash(self, data: Union[str, bytes], salt: Optional[bytes] = None) -> str:
        Veriyi hash'le (KHA-256)
        Args:
            data: Hash'lenecek veri
            salt: Opsiyonel tuz (None ise rastgele)
        Returns:
            64 karakter hex hash

        start_time = time.perf_counter()

        # Veriyi bytes'a çevir
        if isinstance(data, str):
            data_bytes = data.encode("utf-8")
        else:
            data_bytes = data

        # Tuz oluştur
        if salt is None:
            salt = self._generate_salt(data_bytes)
        else:
            # Tuzu güçlendir
            salt = self._strengthen_salt(salt, data_bytes)

        # CACHE KONTROLÜ
        if self.config.cache_enabled:
            cache_key = self._create_cache_key(data_bytes, salt)
            if cache_key in self._cache:
                self._cache_hits += 1
                self.metrics["hash_count"] += 1
                self.metrics["total_time"] += 1  # Minimal zaman
                return self._cache[cache_key]
            self._cache_misses += 1

        # 1. KHA MATRİS OLUŞTURMA
        seed = self._create_seed(data_bytes, salt)
        kha_matrix = self.core._generate_kha_matrix(seed)

        # 2. ÇİFT HASH (opsiyonel)
        if self.config.double_hashing:
            intermediate = self.core._fortified_mixing_pipeline(kha_matrix, salt)
            second_seed = self.core._final_bytes_conversion(intermediate, salt)
            second_matrix = self.core._generate_kha_matrix(second_seed)
            kha_matrix = (kha_matrix + second_matrix) % 1.0

        # 3. GÜÇLENDİRİLMİŞ KARIŞTIRMA
        mixed_matrix = self.core._fortified_mixing_pipeline(kha_matrix, salt)

        # 4. BAYT DÖNÜŞÜMÜ
        hash_bytes = self.core._final_bytes_conversion(mixed_matrix, salt)

        # 5. SIKIŞTIRMA
        final_bytes = self.core._secure_compress(hash_bytes, self.config.hash_bytes)

        # 6. HEX KODLAMA
        hex_hash = final_bytes.hex()

        # Metrikleri güncelle
        elapsed = (time.perf_counter() - start_time) * 1000
        self.metrics["hash_count"] += 1
        self.metrics["total_time"] += elapsed

        # SONUÇ ÖNBELLEĞE AL
        if self.config.cache_enabled:
            self._cache[cache_key] = hex_hash
            # Cache temizleme (1000'den fazla ise)
            if len(self._cache) > 1000:
                # En eski %20'sini temizle
                keys_to_remove = list(self._cache.keys())[:200]
                for key in keys_to_remove:
                    del self._cache[key]
        
        return hex_hash
    """
    """
    def hash(self, data: Union[str, bytes], salt: Optional[bytes] = None) -> str:
        #Hash işlemi - performans metrikli
        start_time = time.perf_counter()
        
        # Veriyi bytes'a çevir
        if isinstance(data, str):
            data_bytes = data.encode("utf-8")
        else:
            data_bytes = data
        
        # Tuz oluştur
        if salt is None:
            salt = self._generate_salt(data_bytes)
        
        # Cache kontrol
        if self.config.cache_enabled:
            cache_key = self._create_cache_key(data_bytes, salt)
            if cache_key in self._cache:
                self.metrics["cache_hits"] = self.metrics.get("cache_hits", 0) + 1
                return self._cache[cache_key]
        
        # Timing
        kha_matrix_time = 0
        mixing_time = 0
        
        # KHA matris oluşturma
        seed = self._create_seed(data_bytes, salt)
        kha_start = time.perf_counter()
        kha_matrix = self.core._generate_kha_matrix(seed)
        kha_matrix_time = (time.perf_counter() - kha_start) * 1000
        
        # Karıştırma
        mix_start = time.perf_counter()
        mixed_matrix = self.core._fortified_mixing_pipeline(kha_matrix, salt)
        mixing_time = (time.perf_counter() - mix_start) * 1000
        
        # Metrikleri güncelle
        total_time = (time.perf_counter() - start_time) * 1000
        self.metrics["total_time"] += total_time
        self.metrics["hash_count"] += 1
        self.metrics["kha_matrix_time"] = self.metrics.get("kha_matrix_time", 0) + kha_matrix_time
        self.metrics["mixing_time"] = self.metrics.get("mixing_time", 0) + mixing_time
        self.metrics["avg_time"] = self.metrics["total_time"] / self.metrics["hash_count"]

        # 2. ÇİFT HASH (opsiyonel)
        if self.config.double_hashing:
            intermediate = self.core._fortified_mixing_pipeline(kha_matrix, salt)
            second_seed = self.core._final_bytes_conversion(intermediate, salt)
            second_matrix = self.core._generate_kha_matrix(second_seed)
            kha_matrix = (kha_matrix + second_matrix) % 1.0

        # 3. GÜÇLENDİRİLMİŞ KARIŞTIRMA
        mixed_matrix = self.core._fortified_mixing_pipeline(kha_matrix, salt)

        # 4. BAYT DÖNÜŞÜMÜ
        hash_bytes = self.core._final_bytes_conversion(mixed_matrix, salt)

        # 5. SIKIŞTIRMA
        final_bytes = self.core._secure_compress(hash_bytes, self.config.hash_bytes)

        # 6. HEX KODLAMA
        hex_hash = final_bytes.hex()

        # Cache'e ekle
        if self.config.cache_enabled:
            self._cache[cache_key] = hex_hash
            
        return hex_hash
    """

    """
    def hash(self, data: Union[str, bytes], salt: Optional[bytes] = None) -> str:
        # Veriyi hash'le (KHA-256)
        # Args:
        #    data: Hash'lenecek veri
        #    salt: Opsiyonel tuz (None ise rastgele)
        #Returns:
        #    64 karakter hex hash

        start_time = time.perf_counter()

        # Veriyi bytes'a çevir
        if isinstance(data, str):
            data_bytes = data.encode("utf-8")
        else:
            data_bytes = data

        # Tuz oluştur
        if salt is None:
            salt = self._generate_salt(data_bytes)
        else:
            # Tuzu güçlendir
            salt = self._strengthen_salt(salt, data_bytes)

        # CACHE KONTROLÜ
        if self.config.cache_enabled:
            cache_key = self._create_cache_key(data_bytes, salt)
            if cache_key in self._cache:
                self._cache_hits += 1
                self.metrics["hash_count"] += 1
                self.metrics["total_time"] += 1  # Minimal zaman
                return self._cache[cache_key]
            self._cache_misses += 1

        # 1. KHA MATRİS OLUŞTURMA
        seed = self._create_seed(data_bytes, salt)
        kha_matrix = self.core._generate_kha_matrix(seed)

        # 2. ÇİFT HASH (opsiyonel)
        if self.config.double_hashing:
            intermediate = self.core._fortified_mixing_pipeline(kha_matrix, salt)
            second_seed = self.core._final_bytes_conversion(intermediate, salt)
            second_matrix = self.core._generate_kha_matrix(second_seed)
            kha_matrix = (kha_matrix + second_matrix) % 1.0

        # 3. GÜÇLENDİRİLMİŞ KARIŞTIRMA
        mixed_matrix = self.core._fortified_mixing_pipeline(kha_matrix, salt)

        # 4. BAYT DÖNÜŞÜMÜ
        hash_bytes = self.core._final_bytes_conversion(mixed_matrix, salt)

        # 5. SIKIŞTIRMA
        final_bytes = self.core._secure_compress(hash_bytes, self.config.hash_bytes)

        # 6. HEX KODLAMA
        hex_hash = final_bytes.hex()

        # Metrikleri güncelle
        elapsed = (time.perf_counter() - start_time) * 1000
        self.metrics["hash_count"] += 1
        self.metrics["total_time"] += elapsed

        # SONUÇ ÖNBELLEĞE AL
        if self.config.cache_enabled:
            self._cache[cache_key] = hex_hash
            # Cache temizleme (1000'den fazla ise)
            if len(self._cache) > 1000:
                # En eski %20'sini temizle
                keys_to_remove = list(self._cache.keys())[:200]
                for key in keys_to_remove:
                    del self._cache[key]
        
        return hex_hash
    """

    def _create_cache_key(self, data: bytes, salt: bytes) -> tuple:
        """Cache anahtarı oluştur"""
        # Data hash + salt hash
        data_hash = hashlib.sha256(data).digest()[:16]
        salt_hash = hashlib.sha256(salt).digest()[:16]
        return (bytes(data_hash), bytes(salt_hash))
    
    def get_cache_stats(self) -> Dict[str, Any]:
        """Cache istatistiklerini getir"""
        total = self._cache_hits + self._cache_misses
        return {
            "cache_size": len(self._cache),
            "cache_hits": self._cache_hits,
            "cache_misses": self._cache_misses,
            "hit_rate": (self._cache_hits / total * 100) if total > 0 else 0,
        }

    """
    def get_cache_stats(self) -> Dict[str, Any]:
        #Cache istatistiklerini getir
        return {
            "cache_size": len(self._cache),
            "cache_hits": self._cache_hits,
            "cache_misses": self._cache_misses,
            "hit_rate": self._cache_hits / max(1, self._cache_hits + self._cache_misses) * 100,
        }
    """


    def _generate_salt(self, data: bytes) -> bytes:
        # Güçlü ama TUTARLI tuz oluştur
        # Veri hash'ini temel al (zaman değil)
        data_hash = hashlib.sha512(data).digest()
        
        # Sabit bir seed kullan
        seed = struct.pack("Q", len(data)) + data[:16].ljust(16, b"\x00")
        seed_int = int.from_bytes(seed, "big")
        rng = random.Random(seed_int)
        
        # Deterministik tuz
        salt = bytes([rng.randint(0, 255) for _ in range(self.config.salt_length)])
        
        return salt


    def _strengthen_salt(self, salt: bytes, data: bytes) -> bytes:
        # Mevcut tuzu güçlendir (deterministik)
        if len(salt) < self.config.salt_length:
            # Deterministik uzatma
            seed = struct.pack("Q", len(data)) + salt[:16].ljust(16, b"\x00")
            seed_int = int.from_bytes(seed, "big")
            rng = random.Random(seed_int)
            
            extension_needed = self.config.salt_length - len(salt)
            extension = bytes([rng.randint(0, 255) for _ in range(extension_needed)])
            salt = salt + extension

        return salt  # Ek karıştırma YAPMA

    """
    def _generate_salt(self, data: bytes) -> bytes:
        #Güçlü tuz oluştur: Aynı girdi farklı hash! Determinist ve uniform değil!
        # Zaman bazlı entropy
        time_part = struct.pack("Q", int(time.time() * 1_000_000))

        # Veri bazlı entropy
        data_hash = hashlib.sha512(data).digest()

        # Sistem entropy'si
        sys_random = secrets.token_bytes(32)

        # KHA entropy
        kha_seed = struct.pack("Q", len(data)) + data[:16].ljust(16, b"\x00")
        kha_int = int.from_bytes(kha_seed, "big")
        rng = random.Random(kha_int)
        kha_random = bytes([rng.randint(0, 255) for _ in range(32)])

        # Hepsinin karışımı
        combined = time_part + data_hash + sys_random + kha_random

        # Karıştır
        salt = bytearray()
        for i in range(self.config.salt_length):
            idx = (i * 17) % len(combined)
            idx2 = (idx + 31) % len(combined)
            salt.append(combined[idx] ^ combined[idx2])

        return bytes(salt)

    def _strengthen_salt(self, salt: bytes, data: bytes) -> bytes:
        #Mevcut tuzu güçlendir
        if len(salt) < self.config.salt_length:
            # Uzat
            extension = self._generate_salt(data + salt)
            extension_needed = self.config.salt_length - len(salt)
            salt = salt + extension[:extension_needed]

        # Karıştır
        strengthened = bytearray(salt)
        data_hash = hashlib.sha256(data).digest()

        for i in range(len(strengthened)):
            strengthened[i] ^= data_hash[i % len(data_hash)]
            strengthened[i] = (strengthened[i] + i) % 256

        return bytes(strengthened)
    """

    def _create_seed(self, data: bytes, salt: bytes) -> bytes:
        # Header: uzunluk bilgisi
        header = len(data).to_bytes(4, 'big') + len(salt).to_bytes(4, 'big')
        
        # 1. Tur: tam veri
        h1 = hashlib.sha512(header + data + salt).digest()
        
        # 2. Tur: verinin hash'ini kullan (uzunluk bağımsız)
        if len(data) <= 1024:
            h2_input = h1 + data + salt
        else:
            # Uzun veride: her 512 byte'dan bir örnek
            sampled = b"".join(data[i:i+64] for i in range(0, len(data), 512))[:512]
            h2_input = h1 + sampled + salt
        
        seed = hashlib.sha512(h2_input).digest()
        return seed

    """
    def _create_seed(self, data: bytes, salt: bytes) -> bytes:
        # Veri boyutunu da entegre et
        header = len(data).to_bytes(4, 'big') + len(salt).to_bytes(4, 'big')
        combined = header + data + salt
        
        seed = hashlib.sha512(combined).digest()
        # Ek entropy: uzun veriler için 2. tur
        if len(data) > 256:
            seed = hashlib.sha512(seed + data[:256] + data[-256:]).digest()
        elif len(data) > 64:
            seed = hashlib.sha512(seed + data).digest()
        
        return seed
    """
    """
    def _create_seed(self, data: bytes, salt: bytes) -> bytes:
        #Hash seed'i oluştur
        # Veri ve tuzu birleştir
        combined = data + salt

        # Multiple hash passes
        seed = combined
        for _ in range(3):
            seed = hashlib.sha512(seed).digest()

        return seed
    """

    def _secure_hex_encode(self, data: bytes) -> str:
        """Güvenli hex kodlama"""
        hex_chars = "0123456789abcdef"
        result = []

        # İlk geçiş: standart hex
        for byte in data:
            result.append(hex_chars[byte >> 4])
            result.append(hex_chars[byte & 0x0F])

        # İkinci geçiş: uniformluk için karıştır
        for i in range(0, len(result) - 8, 4):
            # Karakterleri yer değiştir
            for j in range(4):
                idx1 = i + j
                idx2 = i + j + 4
                if idx2 < len(result):
                    # XOR-based swap
                    val1 = ord(result[idx1])
                    val2 = ord(result[idx2])
                    result[idx1] = hex_chars[(val1 ^ val2) % 16]
                    result[idx2] = hex_chars[(val1 + val2) % 16]

        return "".join(result)

    # ============================================================
    # GÜVENLİK TEST FONKSİYONLARI
    # ============================================================

    def test_avalanche_effect(self, samples: int = 100) -> Dict[str, Any]:
        """Detaylı avalanche testi"""
        print("Avalanche Testi Çalıştırılıyor...")

        diffs = []
        times = []

        for sample_idx in range(samples):
            # Rastgele veri
            data_len = random.randint(16, 256)
            base_data = secrets.token_bytes(data_len)

            # Tek bit değiştir
            flip_pos = random.randint(0, data_len * 8 - 1)
            byte_pos = flip_pos // 8
            bit_pos = flip_pos % 8

            modified = bytearray(base_data)
            modified[byte_pos] ^= 1 << bit_pos
            modified = bytes(modified)

            # Hash'leri hesapla
            start = time.perf_counter()
            h1 = self.hash(base_data)
            h2 = self.hash(modified)
            elapsed = (time.perf_counter() - start) * 1000
            times.append(elapsed)

            # Bit farkını hesapla
            h1_bin = bin(int(h1, 16))[2:].zfill(256)
            h2_bin = bin(int(h2, 16))[2:].zfill(256)

            diff_bits = sum(1 for a, b in zip(h1_bin, h2_bin) if a != b)
            diff_percent = (diff_bits / 256) * 100
            diffs.append(diff_percent)

            # Her 10 örnekte bir ilerleme göster
            if (sample_idx + 1) % 10 == 0:
                print(f"  {sample_idx + 1}/{samples} tamamlandı")

        # İstatistikler
        avg_diff = np.mean(diffs)
        std_diff = np.std(diffs)
        min_diff = min(diffs)
        max_diff = max(diffs)

        # İdeal aralık kontrolü
        ideal_min, ideal_max = 49.5, 50.5
        in_ideal = sum(1 for d in diffs if ideal_min <= d <= ideal_max)
        ideal_percent = (in_ideal / samples) * 100

        # Kaydet
        self.metrics["avalanche_tests"].append(
            {
                "samples": samples,
                "avg": avg_diff,
                "std": std_diff,
                "in_ideal": ideal_percent,
            }
        )

        return {
            "samples": samples,
            "avg_bit_change_percent": avg_diff,
            "std_deviation": std_diff,
            "min_change": min_diff,
            "max_change": max_diff,
            "in_ideal_range": f"{ideal_percent:.1f}%",
            "avg_time_ms": np.mean(times),
            "status": (
                "EXCELLENT"
                if ideal_percent > 95 and 49 <= avg_diff <= 51
                else (
                    "GOOD"
                    if ideal_percent > 85
                    else "ACCEPTABLE" if ideal_percent > 70 else "POOR"
                )
            ),
        }

    def test_collision_resistance(self, samples: int = 5000) -> Dict[str, Any]:
        """Çakışma direnci testi"""
        print("Çakışma Testi Çalıştırılıyor...")

        hashes = set()
        collisions = 0

        for i in range(samples):
            # Rastgele veri
            data_len = random.randint(1, 512)
            data = secrets.token_bytes(data_len)

            # Hash hesapla
            h = self.hash(data)

            if h in hashes:
                collisions += 1
            else:
                hashes.add(h)

            # İlerleme
            if (i + 1) % 1000 == 0:
                print(f"  {i + 1}/{samples} tamamlandı")

        collision_rate = (collisions / samples) * 100

        return {
            "samples": samples,
            "unique_hashes": len(hashes),
            "collisions": collisions,
            "collision_rate_percent": collision_rate,
            "status": (
                "EXCELLENT"
                if collisions == 0
                else (
                    "GOOD"
                    if collision_rate < 0.001
                    else "ACCEPTABLE" if collision_rate < 0.01 else "POOR"
                )
            ),
        }

    def test_uniformity(self, samples: int = 5000) -> Dict[str, Any]:
        """Bit uniformluğu testi"""
        print("Uniformluk Testi Çalıştırılıyor...")

        bit_counts = [0] * 256

        for i in range(samples):
            data = secrets.token_bytes(random.randint(1, 128))
            h = self.hash(data)
            h_int = int(h, 16)

            for bit in range(256):
                if (h_int >> bit) & 1:
                    bit_counts[bit] += 1

            # İlerleme
            if (i + 1) % 1000 == 0:
                print(f"  {i + 1}/{samples} tamamlandı")

        # Chi-square test
        expected = samples / 2
        chi_square = sum(((count - expected) ** 2) / expected for count in bit_counts)

        # 255 serbestlik derecesi için ideal: ~284
        is_uniform = 220 <= chi_square <= 320

        return {
            "samples": samples,
            "chi_square": chi_square,
            "is_uniform": is_uniform,
            "status": (
                "EXCELLENT"
                if 250 <= chi_square <= 300
                else "GOOD" if 220 <= chi_square <= 320 else "POOR"
            ),
        }

    def get_stats(self) -> Dict[str, Any]:
        """İstatistikleri getir"""
        stats = self.core.stats.copy()
        stats.update(self.metrics)

        if stats["hash_count"] > 0:
            stats["avg_time_ms"] = stats["total_time"] / stats["hash_count"]

        kha_total = stats["kha_success"] + stats["kha_fail"]
        stats["kha_success_rate"] = (
            (stats["kha_success"] / kha_total * 100) if kha_total > 0 else 0
        )

        return stats

# ============================================================
# KOLAY KULLANIM FONKSİYONLARI
# ============================================================
def generate_fortified_hasher() -> FortifiedKhaHash256:
    """Güçlendirilmiş hasher oluştur"""
    config = FortifiedConfig()
    return FortifiedKhaHash256(config)


def quick_hash(data: Union[str, bytes]) -> str:
    """Hızlı hash oluşturma"""
    hasher = generate_fortified_hasher()
    return hasher.hash(data)


def hash_password(password: str, salt: Optional[bytes] = None) -> str:
    """Şifre hash'leme"""
    hasher = generate_fortified_hasher()

    # Şifreler için ek güvenlik
    config = FortifiedConfig()
    config.iterations = 24  # Daha fazla iterasyon
    config.components_per_hash = 32  # Daha fazla bileşen

    secure_hasher = FortifiedKhaHash256(config)

    if salt is None:
        salt = secrets.token_bytes(128)  # Uzun tuz

    return f"KHA256${salt.hex()}${secure_hasher.hash(password, salt)}"

def run_comprehensive_test():
    """Kapsamlı güvenlik testi"""
    print("=" * 70)
    print("KHA - KAPSAMLI TEST")
    print("=" * 70)

    # Hasher oluştur
    hasher = generate_fortified_hasher()

    print("\n1. TEMEL FONKSİYON TESTİ")
    print("-" * 40)

    test_cases = [
        ("", "Boş string"),
        ("a", "Tek karakter"),
        ("Merhaba Dünya!", "Basit metin"),
        ("K" * 1000, "Uzun tekrar"),
        (secrets.token_bytes(64), "Rastgele veri (64 byte)"),
    ]

    for data, desc in test_cases:
        if isinstance(data, bytes):
            preview = data[:20].hex() + "..."
        else:
            preview = data[:20] + "..." if len(data) > 20 else data

        start = time.perf_counter()
        h = hasher.hash(data)
        elapsed = (time.perf_counter() - start) * 1000

        print(f"  {desc:<20} '{preview}'")
        print(f"    → {h[:48]}... ({elapsed:.2f}ms)")

    print("\n2. AVALANCHE TESTİ (50 örnek)")
    print("-" * 40)

    avalanche_result = hasher.test_avalanche_effect(50)
    print(f"  Ortalama bit değişimi: {avalanche_result['avg_bit_change_percent']:.2f}%")
    print(f"  İdeal aralıkta: {avalanche_result['in_ideal_range']}")
    print(f"  Durum: {avalanche_result['status']}")

    print("\n3. ÇAKIŞMA TESTİ (5000 örnek)")
    print("-" * 40)

    collision_result = hasher.test_collision_resistance(5000)
    print(f"  Çakışma sayısı: {collision_result['collisions']}")
    print(f"  Çakışma oranı: {collision_result['collision_rate_percent']:.6f}%")
    print(f"  Durum: {collision_result['status']}")

    print("\n4. UNIFORMLUK TESTİ (5000 örnek)")
    print("-" * 40)

    uniformity_result = hasher.test_uniformity(5000)
    print(f"  Chi-square: {uniformity_result['chi_square']:.1f}")
    print(f"  Uniform mu: {uniformity_result['is_uniform']}")
    print(f"  Durum: {uniformity_result['status']}")

    print("\nPERFORMANS ÖZETİ")
    print("-" * 40)

    stats = hasher.get_stats()
    print(f"  Toplam hash: {stats['hash_count']}")
    print(f"  Ortalama süre: {stats.get('avg_time_ms', 0):.2f}ms")
    print(f"  KHA başarı oranı: {stats.get('kha_success_rate', 0):.1f}%")
    print(f"  Karıştırma süresi: {stats.get('mixing_time', 0):.1f}ms")

    print("\n" + "=" * 70)
    print("SONUÇ: KHA-256")
    print("=" * 70)

    # Final evaluation
    avalanche_ok = avalanche_result["status"] in ["EXCELLENT", "GOOD"]
    collision_ok = collision_result["status"] in ["EXCELLENT", "GOOD"]
    uniformity_ok = uniformity_result["status"] in ["EXCELLENT", "GOOD"]

    if avalanche_ok and collision_ok and uniformity_ok:
        print("TÜM TESTLER BAŞARILI! ÜRETİME HAZIR!")
    elif avalanche_ok and collision_ok:
        print("İYİ! Çakışma ve avalanche testleri başarılı.")
    else:
        print("İYİLEŞTİRME GEREKLİ.")

    return hasher

# ============================================================
# ÖRNEK KULLANIM
# ============================================================
if __name__ == "__main__":
    print("KEÇECİ HASH ALGORİTMASI (KHA-256)")
    print("   Performanstan fedakarlık - Güvenlik maksimize\n")

    # Test modu
    if len(sys.argv) > 1 and sys.argv[1] == "--test":
        hasher = run_comprehensive_test()
    else:
        # Hızlı örnek
        print("⚡ HIZLI ÖRNEK KULLANIM:\n")

        hasher = generate_fortified_hasher()

        # Örnek 1: Basit metin
        text = "Merhaba dünya! Bu bir KHA Hash testidir."
        hash_result = hasher.hash(text)
        print(f"Metin: '{text[:256]}'")
        print(f"Hash:  {hash_result}")
        print()

        # Örnek 2: Şifre hash'leme
        password = "GizliŞifre123!"
        password_hash = hash_password(password)
        print(f"Şifre: '{password}'")
        print(f"Hash:  {password_hash[:512]}")
        print()

        # Örnek 3: Avalanche demo
        print("AVALANCHE DEMO:")
        data1 = "A"
        data2 = "B"  # Sadece 1 bit fark

        h1 = hasher.hash(data1)
        h2 = hasher.hash(data2)

        # Bit farkı
        h1_bin = bin(int(h1, 16))[2:].zfill(256)
        h2_bin = bin(int(h2, 16))[2:].zfill(256)
        diff = sum(1 for a, b in zip(h1_bin, h2_bin) if a != b)

        print(f"  'A' → {h1[:256]}")
        print(f"  'B' → {h2[:256]}")
        print(f"  Bit farkı: {diff}/256 (%{diff/256*100:.1f})")
