"""Guide Registry - Tum sorun tipleri icin duzeltme rehberleri."""


class Guide:
    """Tek bir sorun tipi icin duzeltme rehberi."""
    def __init__(self, title, risk, what, why, steps, before, after, warning=None, tools=None):
        self.title = title
        self.risk = risk
        self.what = what
        self.why = why
        self.steps = steps
        self.before = before
        self.after = after
        self.warning = warning
        self.tools = tools or []

    def to_dict(self):
        return {
            "title": self.title, "risk": self.risk,
            "what": self.what, "why": self.why,
            "steps": self.steps,
            "before": self.before, "after": self.after,
            "warning": self.warning, "tools": self.tools,
        }


GUIDES = {
    "secrets": Guide("Kodda Sifre/Secret Temizligi", "Biri kodunuzu gorurse hesaplariniza erisir.", "Sifre veya gizli anahtar direkt kodun icinde yazili.", "Kod git'e push edildiginde herkes gorebilir. Bot'lar GitHub'i tarayip acik secret ariyor.", ["Proje kokunde .env dosyasi olusturun", "Gizli degerleri .env icine MY_SECRET=deger olarak yazin", ".gitignore'a .env ekleyin", "Kodda process.env.MY_SECRET ile okuyun", "Etkilenen API key'lerini yenileyin"], "const API_KEY = 'sk_live_abc123xyz';", "const API_KEY = process.env.STRIPE_API_KEY;", "Secret'i koddan kaldirmak yetmez! Git gecmisinde hala var. Key'i mutlaka rotate edin."),
    "api_keys": Guide("API Anahtari Gizleme", "API anahtarinizla baskasi islem yapar, faturasi size gelir.", "API anahtari kaynak kodda acikta.", "Acik key ile baskasi servis kullanirsa maliyet size yansir.", [".env dosyasina tasiyin", "process.env.API_KEY ile okuyin", ".env.example olusturun", "Mevcut anahtari iptal edip yenisini alin"], "headers: { 'x-api-key': 'abc123' }", "headers: { 'x-api-key': process.env.API_KEY }", "Eski key'i mutlaka iptal edin."),
    "sensitive_files": Guide(".env Dosyasini Git'ten Cikarma", ".env dosyaniz repo'da, tum sifreler acikta.", ".env veya credential dosyasi commit edilmis.", "Repo public ise herkes gorebilir.", ["git rm --cached .env", ".gitignore'a .env ekleyin", "Commit atin", "TUM sifreleri degistirin", ".env.example olusturun"], "# .env git'te\nDB_PASS=gizli123", "# .gitignore:\n.env", "Push ettiyseniz tum sifreleri MUTLAKA degistirin."),
    "https": Guide("HTTP yerine HTTPS", "Veri sifrelenmeden gider, okunabilir.", "Kodda http:// URL'ler var.", "Kafede WiFi'de kullanicinin verileri okunabilir.", ["http:// -> https:// degistirin", "SSL sertifikasi kontrol edin"], "fetch('http://api.example.com')", "fetch('https://api.example.com')"),
    "dangerous_functions": Guide("Tehlikeli Fonksiyon Temizligi", "Disaridan gelen kod calistirilabilir.", "Kod degerlendirme fonksiyonu kullaniliyor.", "Kullanici girdisi iceriyorsa code injection olur.", ["Veri parse icin JSON.parse() kullanin", "Girdiyi whitelist ile dogrulayin"], "const r = JSON.parse(input);", "const r = JSON.parse(input);"),
    "sql_injection": Guide("SQL Injection Korumasi", "Tum veriler okunabilir veya silinebilir.", "SQL string birlestirme ile olusturuluyor.", "' OR 1=1 -- ile tum veriler cekilir.", ["Parameterized query kullanin", "ORM kullanin"], "query(`SELECT * FROM users WHERE id=${id}`)", "query('SELECT * FROM users WHERE id=$1', [id])"),
    "command_injection": Guide("Komut Enjeksiyonu Korumasi", "Sunucuda istenen komut calistirilir.", "Shell komutu kullanici girdisiyle birlestiriliyor.", "Saldirgan ; rm -rf / ekleyebilir.", ["subprocess.run(shell=False) kullanin", "Argumanlari liste verin"], "subprocess.call(f'cmd {input}', shell=True)", "subprocess.run(['cmd', input])"),
    "path_traversal": Guide("Dosya Yolu Guvenlik Acigi", "Sunucu dosyalarina yetkisiz erisim.", "Dosya yolunda ../ kullanimi var.", "../../etc/passwd ile sistem dosyalarina erisilebilir.", ["../ temizleyin", "path.resolve() kullanin", "Base dizin kontrolu yapin"], "path.join(dir, req.params.name)", "const f = path.resolve(dir, name)\nif (!f.startsWith(dir)) throw Error()", "React Native'de require('../../assets/...') normal import'tur."),
    "cors_wildcard": Guide("CORS Yapilandirmasi", "Herhangi bir site API'nize istek atabilir.", "CORS'ta Allow-Origin: * kullanilmis.", "Kotu site kullanicinin oturumuyla erisir.", ["* yerine domain yazin", "Whitelist kullanin"], "'Access-Control-Allow-Origin': '*'", "'Access-Control-Allow-Origin': 'https://myapp.com'"),
    "cors_misconfiguration": Guide("CORS Yapilandirmasi", "Herhangi bir site API'nize istek atabilir.", "CORS'ta wildcard kullanilmis.", "Kotu site kullanicinin oturumunu kullanabilir.", ["Domain belirtin", "Whitelist kullanin"], "'Access-Control-Allow-Origin': '*'", "'Access-Control-Allow-Origin': 'https://myapp.com'"),
    "hardcoded_credentials": Guide("Hardcoded Credential", "Kodda yazili sifre ile hesaplara erisilebilir.", "Config'de sifre/token yazili.", "Kodunuzu goren herkes sisteminize erisir.", [".env'e tasiyin", "process.env ile okuyun", "Rotate edin"], "const secret = 'my-key';", "const secret = process.env.APP_SECRET;", "Git gecmisinde kalir, rotate edin."),
    "pii_exposure": Guide("Kisisel Veri Korumasi", "KVKK/GDPR cezasi.", "Email, telefon client-side'da acikta.", "Client kodu gorulebilir.", ["Sadece gerekli yerlerde gosterin", "Maskeleyin: k***@gmail.com"], "<Text>{user.email}</Text>", "<Text>{maskEmail(user.email)}</Text>"),
    "source_maps_prod": Guide("Source Map Kaldirma", "Kaynak kodunuz okunabilir.", "Production'da .map dosyalari var.", "Saldirgan kodunuzu okuyup zafiyet bulur.", ["Build'de source map kapatin", ".map dosyalarini silin"], "devtool: 'source-map'", "devtool: false"),
    "insecure_session_storage": Guide("Guvenli Veri Saklama", "AsyncStorage sifrelenmez, okunabilir.", "Token guvenli olmayan depolamada.", "Root'lu telefonda okunabilir.", ["SecureStore kullanin", "Web'de httpOnly cookie"], "AsyncStorage.setItem('token', t)", "SecureStore.setItemAsync('token', t)", None, ["expo-secure-store"]),
    "excessive_data_exposure": Guide("Gereksiz Veri Azaltma", "Yavaslik + gizli bilgi sizintisi.", "SELECT * ile her sey cekilyor.", "Gosterilmeyen alanlar da client'a gider.", ["Sadece gereken sutunlari secin", "Pagination ekleyin"], ".select('*')", ".select('id, name, avatar_url')"),
    "certificate_pinning": Guide("SSL Certificate Pinning", "WiFi'de trafik dinlenebilir.", "Certificate pinning yok.", "Sahte sertifika ile trafik okunur.", ["ssl-pinning kutuphane kurun", "Public key gomin"], "// Standart fetch", "import {fetch} from 'react-native-ssl-pinning'", "Sertifika yenilendiginde uygulama da guncelleyin.", ["react-native-ssl-pinning"]),
    "root_jailbreak_detection": Guide("Root/Jailbreak Tespiti", "Kirilmis telefonda uygulama manipule edilir.", "Root tespiti yok.", "Bellek okunabilir, API degistirilebilir.", ["jail-monkey kurun", "Baslarken kontrol yapin"], "// Kontrol yok", "if (JailMonkey.isJailBroken()) Alert.alert('Uyari')", None, ["jail-monkey"]),
    "deeplink_validation": Guide("Deep Link Dogrulama", "Kotu link yanlis yere yonlendirir.", "Deep link'ler dogrulanmiyor.", "Phishing sayfasina yonlendirme yapilabilir.", ["Whitelist ile kontrol edin"], "navigate(url)", "if (isAllowed(url)) navigate(url)"),
    "screenshot_protection": Guide("Ekran Goruntusu Korumasi", "Hassas bilgiler screenshot ile paylasilir.", "Hassas ekranlarda koruma yok.", "Kart bilgileri paylasılabilir.", ["prevent-screenshot kurun", "Hassas ekranlarda aktif edin"], "// Koruma yok", "addScreenshotListener(() => Alert.alert('Engellendi'))", None, ["react-native-prevent-screenshot"]),
    "gdpr_data_deletion": Guide("Hesap Silme (KVKK/GDPR)", "Yasal zorunluluk - App Store zorunlu kiliyor.", "Hesap silme mekanizmasi yok.", "KVKK md.7, Apple zorunlu tutar.", ["'Hesabimi Sil' butonu ekleyin", "Backend'de silme endpoint'i", "30 gun bekleme suresi"], "// Hesap silme yok", "<Button title='Hesabimi Sil' onPress={deleteAccount} />", "Apple 2022'den beri zorunlu tutar."),
    "insecure_random": Guide("Guvenli Rastgele Sayi", "Math.random() tahmin edilebilir.", "Guvenlik icin Math.random() kullaniliyor.", "Sonraki deger tahmin edilebilir.", ["crypto.getRandomValues() kullanin", "uuid kullanin"], "Math.random().toString(36)", "Crypto.getRandomBytes(32)", "Animasyon icin Math.random() sorun degildir."),
    "race_conditions": Guide("Race Condition Onleme", "Veri kaybi - islemler birbiri ustune yazar.", "Bakiye kilit olmadan degistiriliyor.", "Iki islem ayni anda okur, biri kaybolur.", ["Transaction kullanin", "FOR UPDATE ile kitleyin"], "bal = getBalance()\nsetBalance(bal - amount)", "supabase.rpc('deduct_balance', {uid, amount})"),
    "error_message_quality": Guide("Kullanici-Dostu Hata Mesajlari", "Teknik mesajlar kullaniciyi korkutur.", "Hata mesajlarinda teknik jargon.", "Kullanici ne yapacagini bilmek ister.", ["Anlasilir mesaj yazin", "Ne yapabilecegini soylayin"], "Alert.alert('Error', error.message)", "Alert.alert('Baglanti Hatasi', 'Internetinizi kontrol edin.')"),
    "missing_alt_text": Guide("Gorsel Erisilebilirligi", "Gorme engelliler resimleri anlayamaz.", "Image'larda accessibilityLabel yok.", "Ekran okuyucu 'resim' der, icerik anlasilmaz.", ["Image'a accessibilityLabel ekleyin", "Dekoratif gorsele accessible={false}"], "<Image source={logo} />", "<Image source={logo} accessibilityLabel='Logo' />"),
    "a11y_labels": Guide("Erisilebilirlik Etiketleri", "Ekran okuyucu kullananlar kullanamaz.", "Butonlarda accessibilityLabel yok.", "VoiceOver 'buton' der, ne butonu bilinmez.", ["accessibilityLabel ekleyin", "accessibilityRole belirtin"], "<TouchableOpacity><Icon /></TouchableOpacity>", "<TouchableOpacity accessibilityLabel='Kaydet'><Icon /></TouchableOpacity>"),
    "touch_target_size": Guide("Dokunma Alani Buyutme", "Kucuk butonlara basilamaz.", "Elementler 44px'den kucuk.", "Apple/Google min 44x44px oneriyor.", ["minHeight:44 verin", "hitSlop ekleyin"], "style={{width:24, height:24}}", "style={{width:44, height:44}}"),
    "ui_error_boundary": Guide("Error Boundary Ekleme", "Hata = beyaz ekran = kullanici kaybi.", "ErrorBoundary yok.", "Yakalanmayan hata uygulamayi cokertur.", ["ErrorBoundary olusturun", "App'in ustune sarin"], "return <Navigator />", "return <ErrorBoundary><Navigator /></ErrorBoundary>", None, ["react-error-boundary"]),
    "keyboard_handling": Guide("Klavye Form Uyumu", "Klavye formu kapatir, gorunmez.", "TextInput'larda KeyboardAvoidingView yok.", "Klavye ekranin yarisini kapatir.", ["KeyboardAvoidingView ile sarin"], "<View><TextInput /></View>", "<KeyboardAvoidingView><TextInput /></KeyboardAvoidingView>"),
    "term_consistency": Guide("Terim Tutarliligi", "Farkli terimler karistirir.", "Ayni kavram icin birden fazla terim.", "'Login' ve 'Sign in' farkli mi?", ["Terim sozlugu olusturun", "Tek terim kullanin"], "'Login' / 'Sign in'", "Her yerde: 'Giris Yap'"),
    "i18n_readiness": Guide("Cok Dil Destegi", "Cevirmek cok zor olur.", "UI string'leri kodda yazili.", "Tum string'leri bulup degistirmek gerekir.", ["i18n kutuphane kurun", "String'leri ceviri dosyasina tasiyin"], "<Text>Kaydet</Text>", "<Text>{t('save')}</Text>", None, ["i18next"]),
    "long_functions": Guide("Uzun Fonksiyon Bolme", "Okumak ve debug etmek zorlasir.", "50+ satirlik fonksiyonlar var.", "Cok fazla sorumluluk = karmasiklik.", ["Tek is yapan alt fonksiyonlara bolin"], "function handle() { // 80 satir }", "function handle() {\n  validate(); prepare(); submit();\n}"),
    "long_files": Guide("Buyuk Dosya Bolme", "Merge conflict ve hata riski.", "300+ satirlik dosyalar var.", "Code review zorlasir.", ["Component'leri ayrin", "Hook'lari ayrin", "Stilleri ayrin"], "// 500 satir tek dosya", "// component.tsx + useHook.ts + styles.ts"),
    "test_coverage": Guide("Test Yazma", "Degisiklik yapmak riskli.", "Test yok veya cok az.", "Her degisiklikte bir sey kirilabilir.", ["Jest kurun", "Kritik logic icin unit test yazin"], "// Test yok", "describe('fn', () => { it('works', () => expect(fn(1)).toBe(2)) })", None, ["jest"]),
    "readme_exists": Guide("README Ekleme", "Kimse projeyi anlamaz.", "README.md yok.", "README projenin karti vizitidir.", ["README.md olusturun", "Aciklama + kurulum + kullanim yazin"], "// README yok", "# MyApp\n\n## Kurulum\nnpm install"),
    "has_license": Guide("Lisans Ekleme", "Kullanim haklari belirsiz.", "LICENSE dosyasi yok.", "Lisans olmadan hak belirsiz.", ["Uygun lisans secin", "LICENSE dosyasi ekleyin"], "// Lisans yok", "MIT License\nCopyright (c) 2024"),
    "privacy_policy": Guide("Gizlilik Politikasi", "App Store red sebebi.", "Privacy policy referansi yok.", "Her uygulama icin zorunlu.", ["Privacy policy sayfasi olusturun", "Uygulamaya link ekleyin"], "// Yok", "<Text onPress={openPrivacy}>Gizlilik Politikasi</Text>"),
    "consent_management": Guide("Kullanici Izin Yonetimi", "KVKK/GDPR geregi zorunlu.", "Tracking var ama izin alinmiyor.", "Izinsiz veri toplama yasadisi.", ["Izin banner'i gosterin", "Secimi kaydedin", "Izinsiz tracking baslatmayin"], "Analytics.init()", "if (consent.ok) Analytics.init()"),
    "dark_mode_support": Guide("Dark Mode Destegi", "Kullanicilarin %80'i tercih ediyor.", "Dark mode destegi yok.", "Gece kullananlar goz yorgunlugu yasar.", ["useColorScheme() kullanin", "Light/dark tema tanimlayin"], "const bg = '#FFFFFF'", "const bg = scheme==='dark' ? '#0f172a' : '#fff'"),
    "hardcoded_colors": Guide("Tema Sistemi", "Renk degisikligi 100 yerde degisiklik demek.", "Renkler #hex olarak kodda.", "100 yerde ayni rengi degistirmek gerekir.", ["theme.ts olusturun", "Tema degiskenleri kullanin"], "backgroundColor: '#3B82F6'", "backgroundColor: colors.primary"),
    "loading_states": Guide("Yukleniyor Durumu", "Kullanici uygulamanin dongugunu dusunur.", "Async islemlerde loading yok.", "API 1-5 sn surebilir, geri bildirim sart.", ["isLoading state ekleyin", "ActivityIndicator gosterin"], "return <List data={data} />", "if (loading) return <Spinner />\nreturn <List data={data} />"),
    "empty_state": Guide("Bos Durum Ekrani", "Bos liste bozuk izlenim verir.", "Listede bos durum yok.", "Kullanici bozuk sandigi icin terk eder.", ["ListEmptyComponent ekleyin"], "<FlatList data={items} />", "<FlatList data={items} ListEmptyComponent={<Text>Henuz yok</Text>} />"),
    "privacy_manifest": Guide("Apple Privacy Manifest Eksik", "Mayis 2024'ten beri PrivacyInfo.xcprivacy olmadan RED alirsiniz.", "PrivacyInfo.xcprivacy dosyasi proje icinde bulunamadi.", "Apple tum uygulamalarin hangi API'leri neden kullandigini beyan etmesini zorunlu kiliyor.", ["Xcode'da File > New > File > App Privacy secin", "PrivacyInfo.xcprivacy dosyasi olusturulacak", "Kullandiginiz API kategorilerini ekleyin (UserDefaults, FileTimestamp vb.)", "Her API icin kullanim sebebi kodunu secin", "Dosyayi app target'a eklediginizden emin olun"], "// PrivacyInfo.xcprivacy yok", "// PrivacyInfo.xcprivacy olusturuldu\n// NSPrivacyAccessedAPITypes tanimlandi\n// NSPrivacyTracking: false", "React Native/Expo projelerinde expo-build-properties ile eklenebilir."),
    "purpose_strings": Guide("iOS Izin Aciklamasi Eksik", "Izin aciklamasi olmadan uygulama crash eder ve RED alir.", "Kamera, mikrofon, konum gibi API'ler icin Info.plist'te aciklama string'i eksik.", "iOS kullaniciya neden izin istediginizi gostermek zorunda. Aciklama yoksa uygulama crash eder.", ["Info.plist veya app.json'a eksik izin aciklamalarini ekleyin", "Aciklamalar kullaniciya anlamli olmali: 'Fotograf cekmek icin kamera erisimi gereklidir'", "Genel aciklamalar (Bu uygulama kameranizi kullanir) REDDEDILIR"], "// Info.plist'te NSCameraUsageDescription YOK", "// Info.plist:\n// NSCameraUsageDescription: Urun fotografi cekmek icin kamera erisimi gereklidir"),
    "sign_in_with_apple": Guide("Apple ile Giris Zorunlu", "Google/Facebook login varsa Apple Sign In yoksa RED alirsiniz.", "Ucuncu parti login (Google, Facebook) var ama Sign in with Apple yok.", "Apple guideline 4.8: 3rd party login sunuyorsaniz Apple Sign In da sunmaniz ZORUNLU.", ["expo-apple-authentication veya @invertase/react-native-apple-authentication kurun", "Login ekranina 'Apple ile Giris Yap' butonu ekleyin", "Apple Developer'da Sign In with Apple capability'yi aktif edin", "App ID'de Sign In with Apple'i etkinlestirin"], "// Sadece Google login var\n<GoogleSigninButton />", "// Google + Apple\n<GoogleSigninButton />\n<AppleAuthentication.AppleAuthenticationButton />", None, ["expo-apple-authentication"]),
    "account_deletion_apple": Guide("Hesap Silme Zorunlu (Apple)", "2022'den beri hesap silme ozelligi olmadan RED alirsiniz.", "Hesap olusturma var ama hesap silme mekanizmasi yok.", "Apple 2022'de hesap silme ozelligini tum uygulamalar icin ZORUNLU kildi. App Store red sebebi.", ["Ayarlar/Profil sayfasina 'Hesabimi Sil' butonu ekleyin", "Backend'de kullanici verilerini silen endpoint olusturun", "Kullaniciya silme oncesi onay dialog'u gosterin", "Apple 30 gun bekleme suresi oneriyor (geri alma icin)", "Silme sonrasi kullaniciyi cikis yapin"], "// Hesap silme yok", "// Settings ekraninda:\n<Button title='Hesabimi Sil' onPress={handleDeleteAccount} />\n\n// Backend:\nsupabase.auth.admin.deleteUser(userId)", "Apple App Store Connect'te de Privacy Practice'de 'Account Deletion' secenegini isaretleyin."),
    "att_compliance": Guide("App Tracking Transparency (ATT)", "IDFA kullaniminda ATT izni olmadan RED alirsiniz.", "IDFA veya tracking kullaniliyor ama ATTrackingManager ile izin istenmiyor.", "iOS 14.5'ten itibaren kullanici takibi icin acik izin almak ZORUNLU.", ["expo-tracking-transparency veya react-native-tracking-transparency kurun", "Uygulama baslarken ATTrackingManager.requestTrackingAuthorization() cagirin", "Info.plist'e NSUserTrackingUsageDescription ekleyin", "Kullanici reddederse IDFA'ya erismeyin"], "// IDFA kullaniliyor ama izin yok", "import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency'\nconst { status } = await requestTrackingPermissionsAsync()"),
    "external_payment": Guide("Dis Odeme Linki Yasagi", "Dijital icerik icin Apple IAP disinda odeme almak YASAKTIR.", "Uygulamada hem StoreKit hem dis odeme linki (Stripe, PayPal) tespit edildi.", "Apple dijital icerik/ozellik satisi icin sadece kendi IAP sistemini zorunlu kilar. Komisyon: %15-30.", ["Dijital icerik/ozellik satisi icin SADECE StoreKit/IAP kullanin", "Fiziksel urun satisi icin dis odeme kullanabilirsiniz", "Reader uygulamalar (Netflix, Spotify) istisnalar icin Apple'a basvurun"], "// Dijital icerik icin Stripe kullaniliyor\nStripe.redirectToCheckout()", "// Apple IAP kullanin\nconst result = await purchase(productId)", "ABD'de StoreKit External Purchase entitlement ile sinirli dis link verilebilir."),
    "iap_restore": Guide("Satin Alma Geri Yukleme", "Restore Purchases butonu olmadan RED alirsiniz.", "In-app purchase kullaniliyor ama geri yukleme mekanizmasi yok.", "Kullanici cihaz degistirdiginde veya uygulamayi silip yukleyince satin almalari geri yukleyebilmeli.", ["Ayarlar veya profil sayfasina 'Satin Almalari Geri Yukle' butonu ekleyin", "RevenueCat: Purchases.restorePurchases() cagirin", "StoreKit 2: AppStore.sync() cagirin", "Geri yukleme basarili/basarisiz bildirim gosterin"], "// Restore yok", "// Settings ekraninda:\n<Button title='Satin Almalari Geri Yukle' onPress={restorePurchases} />\n\nasync function restorePurchases() {\n  await Purchases.restorePurchases()\n}", None, ["react-native-purchases"]),
    "iap_verification": Guide("IAP Transaction Dogrulama", "Transaction dogrulamasi olmadan sahte satin alma yapilabilir.", "StoreKit kullaniliyor ama transaction dogrulama (.verified) bulunamadi.", "Dogrulanmamis transaction'lar sahte olabilir. Server-side dogrulama oneriliyor.", ["StoreKit 2'de .verified pattern kullanin", "Server-side receipt validation yapin", "RevenueCat kullaniyorsaniz otomatik dogrular"], "// Dogrulama yok\nlet transaction = result", "// Dogrulama var\nif case .verified(let transaction) = result {\n  // Guvenli\n}"),
    "recording_consent": Guide("Kayit Izni ve Gostergesi", "Kamera/mikrofon izinsiz kullanim RED sebebidir.", "Kayit API'si kullaniliyor ama izin isteme mekanizmasi bulunamadi.", "iOS kullanicinin kamera/mikrofon kullanimdan haberdar olmasini zorunlu kilar.", ["Kayit baslamadan once izin isteyin", "Kayit sirasinda gorsel gosterge (kirmizi nokta) gosterin", "Kullanici izin vermezse kaydi baslatmayin"], "// Izinsiz kayit\nAVCaptureSession.startRunning()", "// Izinli kayit\nconst { status } = await Camera.requestPermissionsAsync()\nif (status === 'granted') startRecording()"),
    "required_reason_api": Guide("Required Reason API Beyani", "API beyannamesi olmadan RED alirsiniz.", "UserDefaults, FileTimestamp gibi API'ler kullaniliyor ama PrivacyInfo.xcprivacy'de beyan edilmemis.", "Apple bazi API'lerin neden kullanildigini beyan etmenizi zorunlu kiliyor.", ["PrivacyInfo.xcprivacy dosyasini acin", "NSPrivacyAccessedAPITypes dizisine API kategorisini ekleyin", "Her API icin NSPrivacyAccessedAPITypeReasons ile sebep kodu girin", "UserDefaults icin CA92.1 (app functionality) kodu yaygindir"], "// Beyan yok, UserDefaults kullaniliyor", "// PrivacyInfo.xcprivacy:\n// NSPrivacyAccessedAPICategoryUserDefaults -> CA92.1"),
    "app_icon_sizes": Guide("App Icon Boyutlari", "Eksik ikon boyutlari submission'i engeller.", "App icon seti eksik veya yetersiz boyutta.", "App Store 1024x1024, iPhone @3x 180x180, @2x 120x120 gibi boyutlar ister.", ["Xcode'da Assets > AppIcon'a tum boyutlari ekleyin", "Expo'da app.json > icon alanini 1024x1024 PNG olarak ayarlayin", "makeappicon.com gibi araclarla tum boyutlari otomatik uretin"], "// Eksik ikon boyutlari", "// app.json:\n{ \"icon\": \"./assets/icon.png\" }  // 1024x1024 PNG"),
    "launch_screen": Guide("Launch Screen / Splash Screen", "Launch screen olmadan uygulama RED alir.", "LaunchScreen.storyboard veya splash screen yapilandirmasi bulunamadi.", "Apple her uygulamanin bir launch screen gostermesini zorunlu kilar.", ["Expo: app.json > splash yapilandirin", "Native: LaunchScreen.storyboard olusturun", "Splash screen'de statik gorsel kullanin (animasyon olmaz)"], "// Splash screen yok", "// app.json:\n{ \"splash\": { \"image\": \"./assets/splash.png\" } }"),
    "subscription_handling": Guide("Abonelik Durumu Yonetimi", "Abonelik durumu kontrol edilmezse kullanici ucretsiz erisim saglayabilir.", "Abonelik sistemi var ama durum kontrolu (aktif/suresi dolmus) bulunamadi.", "Abonelik durumu her uygulama acilisinda kontrol edilmeli.", ["Her acilista abonelik durumunu kontrol edin", "RevenueCat: Purchases.getCustomerInfo() kullanin", "Suresi dolan abonelik icin icerigi kisitlayin"], "// Durum kontrolu yok", "const info = await Purchases.getCustomerInfo()\nconst isActive = info.entitlements.active['pro']"),
    "app_thinning": Guide("Buyuk Asset Optimizasyonu", "200MB ustu uygulamalar WiFi'siz indirilemez - kullanici kaybi.", "5MB'dan buyuk asset dosyalari tespit edildi.", "Buyuk asset'ler uygulama boyutunu sisirır. Apple 200MB WiFi limiti koyar.", ["Gorselleri optimize edin (WebP, HEIC)", "Video'lari sikistirin veya streaming yapin", "On-Demand Resources (ODR) kullanin", "Gereksiz asset'leri kaldirin"], "// 15MB video bundle icinde", "// Video streaming ile:\nconst videoUrl = 'https://cdn.myapp.com/video.mp4'"),
    "app_completeness": Guide("Test/Placeholder Icerik Temizligi", "Apple test verisi, placeholder veya lorem ipsum iceren uygulamalari REDDEDER.", "Kodda test email, placeholder metin veya demo icerik kalmis.", "Apple Guideline 2.1: Uygulama tam ve calisan olmali. Test verileri RED sebebi.", ["Tum 'lorem ipsum', 'test@test.com' gibi yer tutucu metinleri gercek icerikle degistirin", "Debug URL'leri (localhost, staging) production URL ile degistirin", "console.log ifadelerini kaldirin veya loglama seviyesini ayarlayin"], "const email = 'test@test.com'", "const email = user.email"),
    "debug_urls": Guide("Production'da Debug URL", "localhost, staging veya ngrok URL'leri production'da calismiyor ve RED sebebi.", "Kodda debug/development URL'ler (localhost, 192.168.x, staging) kalmis.", "Production build'de bu URL'ler calismaz ve Apple reviewer test ederken hata alir.", ["Tum localhost/staging URL'leri environment variable ile degistirin", ".env dosyasinda production URL'leri tanimlayin", "Build sirasinda dogru env kullanildigina emin olun"], "fetch('http://localhost:3000/api')", "fetch(process.env.EXPO_PUBLIC_API_URL)"),
    "reason_code_validity": Guide("Required Reason API Kodu Gecersiz", "Gecersiz reason kodu ile submission REDDEDILIR.", "PrivacyInfo.xcprivacy icinde tanimsiz veya gecersiz reason kodu kullanilmis.", "Apple her API kategorisi icin sadece belirli reason kodlarini kabul eder.", ["Apple Developer dokumantasyonundan gecerli kodlari kontrol edin", "UserDefaults icin CA92.1 (app functionality) en yaygin koddur", "Her API icin dogrudan Apple listesinden secim yapin"], "NSPrivacyAccessedAPITypeReasons: ['XXXXX']", "NSPrivacyAccessedAPITypeReasons: ['CA92.1']"),
    "sdk_privacy_manifests": Guide("SDK Privacy Manifest Eksik", "SDK'nin privacy manifest'i yoksa Apple submission'i reddedebilir.", "Kullandiginiz ucuncu parti SDK'larin PrivacyInfo.xcprivacy dosyasi eksik.", "Mayis 2024'ten itibaren tum SDK'lar kendi privacy manifest'ini icermek zorunda.", ["SDK'yi son surume guncelleyin (yeni surumler manifest iceriyor)", "SDK maintainer'ina privacy manifest eklemesini talep edin", "Gerekirse kendiniz SDK icin manifest olusturun"], "// SDK v1.0 - manifest yok", "// SDK v2.0 - PrivacyInfo.xcprivacy dahil"),
    "ota_compliance": Guide("OTA Update Kurali (Guideline 3.3.2)", "OTA ile yeni ozellik gondermek YASAK - sadece bug fix gonderilebilir.", "expo-updates veya CodePush ile OTA guncelleme aktif.", "Apple Guideline 3.3.2: Kod yorumlama ile uygulama davranisini degistirmek yasak. Bug fix OTA kabul edilir.", ["OTA update'leri sadece bug fix icin kullanin", "Yeni ozellikler icin App Store submission yapin", "expo-updates config'de fallbackToCacheTimeout ayarlayin"], "// OTA ile yeni ekran ekleme (YASAK)", "// OTA ile sadece crash fix (GECERLI)"),
    "ats_override": Guide("App Transport Security Devre Disi", "NSAllowsArbitraryLoads tum HTTP trafigine izin verir - guvenlik acigi.", "Info.plist'te App Transport Security tamamen devre disi birakilmis.", "ATS kapatildiginda uygulama sifrelenmemis HTTP baglantilarini kabul eder. MITM saldirisina acik.", ["NSAllowsArbitraryLoads'i kaldirin veya false yapin", "Belirli domain'ler icin NSExceptionDomains kullanin", "Tum API'lerinizi HTTPS'e gecirin"], "NSAllowsArbitraryLoads: true", "NSAllowsArbitraryLoads: false\n// veya tamamen kaldirin"),
    "url_scheme_conflict": Guide("Apple Reserved URL Scheme Cakismasi", "Apple'in kendi URL scheme'lerini kullanmak RED sebebi.", "Uygulamanin URL scheme'i Apple'in reserved scheme'leriyle cakisiyor.", "maps://, tel://, mailto:// gibi scheme'ler Apple'a ait. Bunlari kullanmak yasak.", ["CFBundleURLSchemes'deki cakisan scheme'i degistirin", "Uygulamaniza ozel benzersiz bir scheme secin: betterplate://"], "CFBundleURLSchemes: ['maps']", "CFBundleURLSchemes: ['betterplate']"),
    "bundle_secrets": Guide("Bundle'da Gizli Anahtar", "EXPO_PUBLIC_ prefix'li secret'lar IPA'dan okunabilir.", "EXPO_PUBLIC_ ile baslayan hassas degiskenler (SECRET, KEY, TOKEN) tespit edildi.", "EXPO_PUBLIC_ prefix'li her degisken JS bundle'a gomulur. IPA extract edilince herkes okuyabilir.", ["Hassas degerleri EXPO_PUBLIC_ prefix'i OLMADAN tanimlayin", "Bu degerleri sadece server-side (Edge Function) tarafinda kullanin", "Client'ta sadece anon/public key'leri kullanin"], "EXPO_PUBLIC_SUPABASE_SECRET_KEY=xxx", "SUPABASE_SECRET_KEY=xxx  # Sadece server-side"),
    "uiwebview_deprecated": Guide("UIWebView Kullanimi (Deprecated)", "UIWebView 2020'den beri RED sebebi - WKWebView kullanin.", "Proje veya SDK'larda UIWebView kullanimi tespit edildi.", "Apple UIWebView'i 2020'de tamamen yasakladi. node_modules icindeki SDK'lar bile RED sebebi olabilir.", ["UIWebView kullanan SDK'yi guncelleyin", "Kendi kodunuzda WKWebView'a gecin", "SDK guncellenmiyorsa alternatif SDK bulun"], "UIWebView *webView = ...", "WKWebView *webView = ..."),
    # AST Analysis Guides
    "dangerous_calls": Guide("Tehlikeli Fonksiyon Cagirisi (AST)", "Disaridan gelen kod calistirilabilir.", "AST analizi ile GERCEK tehlikeli fonksiyon cagirisi tespit edildi.", "Bu regex degil, gercek AST node'u. Kesin sorun.", ["json.loads veya ast.literal_eval gibi guvenli alternatifler kullanin", "subprocess.run(shell=False) tercih edin"], "dangerous_func(user_input)", "json.loads(user_input)"),
    "mutable_defaults": Guide("Mutable Default Argument (AST)", "Fonksiyonlar arasi veri sizintisi.", "def f(x=[]) gibi mutable default argument tespit edildi.", "Python'da default degerler bir kez olusturulur.", ["Default olarak None kullanin", "Fonksiyon icinde yeni nesne olusturun"], "def f(items=[]):", "def f(items=None):\n    items = items or []"),
    "hardcoded_secrets": Guide("Hardcoded Secret (AST)", "AST ile dogrulandi - kesin.", "Degisken ismi secret/password VE deger string constant.", "AST regex'ten daha guvenilir.", ["Degeri .env'e tasiyin", "os.environ ile okuyun"], "password = 'gizli123'", "password = os.environ['DB_PASSWORD']"),
    # Taint Tracking Guides
    "sql_injection_taint": Guide("SQL Injection (Taint)", "Tum veritabani okunabilir.", "Kullanici girdisi SQL sorgusuna gidiyor.", "Taint tracking ile dogrulandi.", ["Parameterized query kullanin", "ORM kullanin"], "cursor.execute('...' + uid)", "cursor.execute('...%s', [uid])"),
    "xss_taint": Guide("XSS (Taint)", "Tarayicide kod calisir.", "Kullanici girdisi DOM hedefine gidiyor.", "Taint tracking ile dogrulandi.", ["DOMPurify ile sanitize edin", "textContent kullanin"], "elem.unsafeRender = input", "elem.textContent = input"),
    "command_injection_taint": Guide("Command Injection (Taint)", "Sunucuda komut calisir.", "Kullanici girdisi komut satirina gidiyor.", "Taint tracking ile dogrulandi.", ["subprocess.run(shell=False) kullanin", "Argumanlari liste verin"], "run_cmd(user_input)", "subprocess.run(['cmd', user_input])"),
    "path_traversal_taint": Guide("Path Traversal (Taint)", "Dosyalara yetkisiz erisim.", "Kullanici girdisi dosya yoluna gidiyor.", "Taint tracking ile dogrulandi.", ["realpath ile normalize edin", "Base dizin kontrolu yapin"], "open(user_path)", "safe = realpath(user_path)"),
    "general_taint": Guide("Genel Taint Akisi", "Girdi tehlikeli hedefe gidiyor.", "Source-sink eslesmesi tespit edildi.", "Sanitizasyon yok.", ["Girdiyi validate edin", "Guvenli alternatif kullanin"], "sink(user_input)", "sink(sanitize(user_input))"),
    # SCA Guides
    "npm_audit": Guide("npm Guvenlik Acigi", "Bilinen guvenlik acigi olan paketler projede.", "npm audit kritik veya yuksek seviye guvenlik acigi raporladi.", "Saldirgan bilinen aciklari otomatik tarayip istismar edebilir.", ["npm audit fix calistirin", "Breaking change varsa npm audit fix --force", "Manuel olarak paketi guncelleyin", "Alternatif paket arastirin"], "lodash: 4.17.15 (prototype pollution)", "lodash: 4.17.21 (guncellenmis)", None, ["npm-audit-resolver"]),
    "pip_audit": Guide("Python Dependency Acigi", "Python paketlerinde bilinen guvenlik acigi.", "pip-audit veya safety kritik seviye guvenlik acigi raporladi.", "Eski surumler bilinen zafiyetler icerir.", ["pip install --upgrade <paket>", "requirements.txt'i guncelleyin", "pip-audit --fix ile otomatik duzeltme", "Virtual environment'ta test edin"], "requests==2.25.0 (CVE-XXXX)", "requests==2.31.0 (guncellenmis)"),
    "go_vulncheck": Guide("Go Modul Acigi", "Go modullerinde bilinen guvenlik acigi.", "govulncheck bilinen guvenlik acigi raporladi.", "Go modulleri de guvenlik aciklari icerebilir.", ["go get -u <modul>", "go mod tidy", "govulncheck ./... ile detay gorun"], "golang.org/x/net v0.1.0", "golang.org/x/net v0.17.0"),
    "outdated_packages": Guide("Guncel Olmayan Paketler", "Major versiyon gerisinde paketler guvenlik riski.", "Paketler major versiyon gerisinde kalmis.", "Eski versiyonlar guvenlik yamalarini almaz.", ["npm outdated ile kontrol edin", "Major guncellemelerde CHANGELOG okuyun", "Test suite calistirin", "Asama asama guncelleyin"], "react: 16.14.0", "react: 18.2.0"),
    "license_compatibility": Guide("Lisans Uyumsuzlugu", "GPL paket MIT projede = lisans ihlali.", "GPL lisansli bir paket MIT/Apache lisansli projede kullaniliyor.", "GPL tum projenin GPL olmasi gerektirir (copyleft). Ihlal hukuki risk tasir.", ["GPL paketi kaldirin", "Alternatif MIT/Apache lisansli paket bulun", "Projeyi GPL'e cevirin", "Hukuk danismani ile gorusun"], "express-gpl-helper (GPL-3.0)", "express-mit-helper (MIT)"),
    "deprecated_packages": Guide("Deprecated Paket", "Kullanim disi paket guvenlik yamasi almaz.", "Projede deprecated (kullanim disi birakilmis) paket kullaniliyor.", "Deprecated paketler artik guvenlik yamasi almaz, yeni hatalar duzeltilmez.", ["Paketin onerilen alternatifine gecin", "Migration guide'i takip edin", "Testleri gecis sonrasi calistirin"], "request (deprecated)", "axios veya node-fetch"),
    "typosquatting": Guide("Typosquatting Paketi - TEHLIKE", "Zararli paket projede! Hemen kaldirin.", "Bilinen bir typosquatting paketi projede tespit edildi.", "Typosquatting: Populer paket ismine benzer isimli zararli paket. Veri calabilir, backdoor acabilir.", ["HEMEN paketi kaldirin: npm uninstall <paket>", "node_modules silerek yeniden kurun", "Sistem/credentials kontrolu yapin", "Dogru isimli paketi kurun"], "crossenv (ZARARLI)", "cross-env (GERCEK)", "Bu ciddi bir guvenlik olayidir. Tum credential'lari rotate edin."),
    # Play Store Guides
    "target_sdk": Guide("Target SDK Guncelleme", "Google Play uygulamayi reddeder.", "targetSdkVersion guncel degil (34 altinda).", "Google Play Agustos 2024'ten itibaren targetSdk 34+ zorunlu kiliyor.", ["build.gradle'da targetSdkVersion 34 yapin", "Android 14 API degisikliklerini kontrol edin", "Ozellikle izin degisikliklerine dikkat edin"], "targetSdkVersion 31", "targetSdkVersion 34"),
    "exported_components": Guide("Exported Component Beyani", "Android 12+ icin zorunlu, yoksa crash eder.", "Activity/Service/Receiver'da android:exported belirtilmemis.", "Android 12 (API 31) ile tum intent-filter'li component'lerde exported zorunlu.", ["AndroidManifest.xml'de her component'e android:exported ekleyin", "Intent-filter varsa exported=true", "Sadece dahili kullanim varsa exported=false"], "<activity android:name='.Main'>", "<activity android:name='.Main' android:exported='true'>"),
    "network_security": Guide("Android Ag Guvenligi", "HTTP trafik okunabilir, MITM saldirisina acik.", "cleartext traffic acik veya network security config eksik.", "Sifrelenmemis HTTP trafik kafedeki WiFi'de okunabilir.", ["usesCleartextTraffic=false yapin", "network_security_config.xml olusturun", "Certificate pinning ekleyin"], "usesCleartextTraffic='true'", "usesCleartextTraffic='false'"),
    "debuggable": Guide("Release Debug Modu", "Play Store RED - uygulama tersine muhendislige acik.", "Release build'de debuggable=true.", "Debug modunda uygulama bellegi okunabilir, kod adim adim izlenebilir.", ["build.gradle > release > debuggable false", "AndroidManifest.xml'den debuggable kaldirin"], "debuggable true // release", "debuggable false // release"),
    "proguard": Guide("Kod Obfuscation (R8/ProGuard)", "Kodunuz okunabilir, API key'ler, logic gorunur.", "Release build'de minifyEnabled=false.", "APK decompile edilince tum Java/Kotlin kodunuz okunur.", ["build.gradle > release > minifyEnabled true", "proguard-rules.pro dosyasini yapilandirin", "Obfuscation sonrasi test calistirin"], "minifyEnabled false", "minifyEnabled true"),
    "permissions": Guide("Android Izin Gozden Gecirme", "Gereksiz izin = kullanici guvensizligi + Play Store inceleme.", "Riskli veya gereksiz olabilecek izinler tespit edildi.", "Google Play hassas izinleri (SMS, arama, konum) ozel incelemeye aliyor.", ["Her iznin gercekten gerekli olup olmadigini degerlendirin", "ACCESS_FINE yerine COARSE_LOCATION yeterli olabilir", "Runtime permission kullanin", "Izin aciklamasi ekleyin"], "ACCESS_FINE_LOCATION + CAMERA + READ_SMS", "ACCESS_COARSE_LOCATION + CAMERA (gerektigi kadar)"),
    "data_safety": Guide("Play Store Data Safety Beyani", "Data Safety formu doldurmak zorunlu.", "Veri toplama yapiliyor ama Data Safety beyani yok.", "Google Play tum uygulamalarin veri toplama pratikerini beyan etmesini zorunlu kilar.", ["Play Console'da Data Safety formunu doldurun", "Analytics, konum, reklam verisi toplamayi beyan edin", "Ucuncu parti SDK'larin topladigi verileri dahil edin"], "// Beyan yok", "// Play Console > Data Safety formu dolduruldu"),
    "backup_rules": Guide("Android Yedekleme Kurallari", "Hassas veri (token, sifre) yedege dahil olabilir.", "allowBackup=true ama backup rules tanimlanmamis.", "Kullanici yedegi sifreler, token'lar ve hassas verileri icerebilir.", ["fullBackupRules ile hassas dosyalari haric tutin", "Token ve credential dosyalarini exclude edin", "Android 12+ icin dataExtractionRules kullanin"], "allowBackup='true'", "allowBackup='true'\nfullBackupRules='@xml/backup_rules'"),
}


class GuideRegistry:
    @staticmethod
    def get(subtype):
        g = GUIDES.get(subtype)
        return g.to_dict() if g else None

    @staticmethod
    def get_all():
        return {k: v.to_dict() for k, v in GUIDES.items()}

    @staticmethod
    def has(subtype):
        return subtype in GUIDES
