import time
import json
import pickle
import os
import platform
import subprocess
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.edge.options import Options as EdgeOptions
from selenium.webdriver.edge.service import Service as EdgeService
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.microsoft import EdgeChromiumDriverManager
import logging

# Logging ayarları
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class G2GAutomation:
    def __init__(self):
        self.driver = None
        self.wait = None
        self.session_file = "g2g_session.pkl"
        self.cookies_file = "g2g_cookies.json"
        self.base_url = "https://www.g2g.com"
        self.profile_name = None
        self.profile_dir = None
    
    def get_chrome_version(self):
        """Chrome tarayıcısının versiyonunu al"""
        try:
            if platform.system() == "Windows":
                # Windows için Chrome versiyonunu al
                result = subprocess.run([
                    'reg', 'query', 
                    'HKEY_CURRENT_USER\\Software\\Google\\Chrome\\BLBeacon', 
                    '/v', 'version'
                ], capture_output=True, text=True, shell=True)
                
                if result.returncode == 0:
                    version_line = result.stdout.strip().split('\n')[-1]
                    version = version_line.split()[-1]
                    return version.split('.')[0]  # Major version
            else:
                # Linux/Mac için
                result = subprocess.run(['google-chrome', '--version'], 
                                      capture_output=True, text=True)
                if result.returncode == 0:
                    version = result.stdout.strip().split()[-1]
                    return version.split('.')[0]
        except Exception as e:
            logger.warning(f"Chrome versiyonu tespit edilemedi: {e}")
        
        return None
        
    def setup_driver(self):
        """Chrome WebDriver'ı ayarla ve başlat"""
        try:
            chrome_options = Options()
            # Kalıcı profil dizini oluştur
            import uuid
            import os
            
            # Kalıcı profil dizini
            self.profile_name = "g2g_permanent_profile"
            self.profile_dir = os.path.abspath(f"./{self.profile_name}")
            
            # Profil dizini yoksa oluştur
            if not os.path.exists(self.profile_dir):
                os.makedirs(self.profile_dir)
                logger.info(f"Yeni profil dizini oluşturuldu: {self.profile_dir}")
            else:
                logger.info(f"Mevcut profil dizini kullanılıyor: {self.profile_dir}")
            
            chrome_options.add_argument(f"--user-data-dir={self.profile_dir}")
            
            # Chrome ayarları
            chrome_options.add_argument("--no-sandbox")
            chrome_options.add_argument("--disable-dev-shm-usage")
            chrome_options.add_argument("--disable-blink-features=AutomationControlled")
            chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
            chrome_options.add_experimental_option('useAutomationExtension', False)
            # Yeni profil için ek ayarlar
            chrome_options.add_argument("--disable-extensions")
            chrome_options.add_argument("--disable-plugins")
            chrome_options.add_argument("--disable-images")  # Hızlı yükleme için
            # Güvenlik ve izin ayarları
            chrome_options.add_argument("--disable-web-security")
            chrome_options.add_argument("--allow-running-insecure-content")
            chrome_options.add_argument("--disable-features=VizDisplayCompositor")
            # Performance log'ları için
            chrome_options.add_argument("--enable-logging")
            chrome_options.add_argument("--log-level=0")
            
            # Headless modunu kapat (giriş yapabilmek için)
            # chrome_options.add_argument("--headless")
            
            # Chrome versiyonunu al
            chrome_version = self.get_chrome_version()
            logger.info(f"Chrome versiyonu: {chrome_version}")
            
            # Driver kurulum stratejileri
            driver_strategies = [
                # Strateji 1: Chrome WebDriver Manager ile otomatik
                lambda: self._try_webdriver_manager(chrome_version),
                # Strateji 2: Edge WebDriver Manager ile otomatik
                lambda: self._try_edge_webdriver_manager(),
                # Strateji 3: Chrome sistem PATH'inden
                lambda: self._try_system_path(chrome_options),
                # Strateji 4: Manuel Chrome driver yolu
                lambda: self._try_manual_driver(chrome_options)
            ]
            
            for i, strategy in enumerate(driver_strategies, 1):
                try:
                    logger.info(f"Driver kurulum stratejisi {i} deneniyor...")
                    self.driver = strategy()
                    if self.driver:
                        break
                except Exception as e:
                    logger.warning(f"Strateji {i} başarısız: {e}")
                    continue
            
            if not self.driver:
                raise Exception("Tüm driver kurulum stratejileri başarısız")
            
            self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
            self.wait = WebDriverWait(self.driver, 20)
            
            logger.info("Chrome WebDriver başarıyla başlatıldı")
            return True
            
        except Exception as e:
            logger.error(f"WebDriver başlatılamadı: {e}")
            logger.info("Manuel Chrome driver kurulumu gerekebilir")
            logger.info("Chrome driver'ı https://chromedriver.chromium.org/ adresinden indirip PATH'e ekleyin")
            return False
    
    def _try_webdriver_manager(self, chrome_version):
        """Chrome WebDriver Manager ile driver kurulumu"""
        try:
            if chrome_version:
                service = Service(ChromeDriverManager(driver_version=chrome_version).install())
            else:
                service = Service(ChromeDriverManager().install())
            return webdriver.Chrome(service=service)
        except Exception as e:
            logger.warning(f"Chrome WebDriver Manager başarısız: {e}")
            return None
    
    def _try_edge_webdriver_manager(self):
        """Edge WebDriver Manager ile driver kurulumu"""
        try:
            edge_options = EdgeOptions()
            edge_options.add_argument("--no-sandbox")
            edge_options.add_argument("--disable-dev-shm-usage")
            edge_options.add_argument("--disable-blink-features=AutomationControlled")
            edge_options.add_experimental_option("excludeSwitches", ["enable-automation"])
            edge_options.add_experimental_option('useAutomationExtension', False)
            
            service = EdgeService(EdgeChromiumDriverManager().install())
            return webdriver.Edge(service=service, options=edge_options)
        except Exception as e:
            logger.warning(f"Edge WebDriver Manager başarısız: {e}")
            return None
    
    def _try_system_path(self, chrome_options):
        """Sistem PATH'inden driver kullanma"""
        try:
            return webdriver.Chrome(options=chrome_options)
        except Exception as e:
            logger.warning(f"Sistem PATH driver başarısız: {e}")
            return None
    
    def _try_manual_driver(self, chrome_options):
        """Manuel driver yolu deneme"""
        try:
            # Yaygın driver yolları
            driver_paths = [
                "./chromedriver.exe",
                "./chromedriver",
                "chromedriver.exe",
                "chromedriver"
            ]
            
            for path in driver_paths:
                if os.path.exists(path):
                    service = Service(path)
                    return webdriver.Chrome(service=service, options=chrome_options)
            
            return None
        except Exception as e:
            logger.warning(f"Manuel driver başarısız: {e}")
            return None
    
    def save_session(self):
        """Oturum bilgilerini ve cookie'leri kaydet"""
        try:
            # Cookie'leri kaydet
            cookies = self.driver.get_cookies()
            with open(self.cookies_file, 'w') as f:
                json.dump(cookies, f)
            
            # Oturum bilgilerini kaydet
            session_data = {
                'current_url': self.driver.current_url,
                'window_handles': self.driver.window_handles,
                'timestamp': time.time()
            }
            
            with open(self.session_file, 'wb') as f:
                pickle.dump(session_data, f)
            
            logger.info("Oturum bilgileri başarıyla kaydedildi")
            return True
            
        except Exception as e:
            logger.error(f"Oturum kaydedilemedi: {e}")
            return False
    
    def load_session(self):
        """Kaydedilmiş oturum bilgilerini yükle"""
        try:
            # Profil dizini varsa oturum bilgileri mevcut
            if os.path.exists(self.profile_dir):
                logger.info("Kalıcı profil dizini bulundu, oturum bilgileri mevcut")
                # G2G.com'a git - profil otomatik yüklenecek
                self.driver.get(self.base_url)
                time.sleep(5)  # Sayfanın tam yüklenmesini bekle
                return True
            else:
                logger.info("Profil dizini bulunamadı, yeni oturum gerekli")
                return False
            
        except Exception as e:
            logger.error(f"Oturum yüklenemedi: {e}")
            return False
    
    def check_login_status(self):
        """Giriş yapılıp yapılmadığını kontrol et"""
        try:
            # G2G.com için özel giriş göstergeleri
            login_indicators = [
                # G2G.com'un gerçek giriş göstergeleri
                "//a[contains(@href, '/logout')]",
                "//a[contains(@href, '/profile')]",
                "//a[contains(@href, '/account')]",
                "//span[contains(text(), 'My Account')]",
                "//span[contains(text(), 'Account')]",
                "//div[contains(@class, 'user-menu')]",
                "//div[contains(@class, 'user-info')]",
                "//a[contains(text(), 'Logout')]",
                "//a[contains(text(), 'Sign Out')]",
                "//button[contains(text(), 'Logout')]",
                # G2G.com özel elementler
                "//div[contains(@class, 'header-user')]",
                "//div[contains(@class, 'user-dropdown')]",
                "//a[contains(@class, 'user-avatar')]",
                # Genel giriş göstergeleri
                "//*[contains(@class, 'logged-in')]",
                "//*[contains(@class, 'user-logged')]"
            ]
            
            # Önce sayfanın yüklenmesini bekle
            time.sleep(2)
            
            for indicator in login_indicators:
                try:
                    elements = self.driver.find_elements(By.XPATH, indicator)
                    if elements:
                        logger.info(f"Giriş göstergesi bulundu: {indicator}")
                        logger.info("Kullanıcı giriş yapmış durumda")
                        return True
                except NoSuchElementException:
                    continue
            
            # Alternatif kontrol: Giriş yapmamış göstergelerini kontrol et
            logout_indicators = [
                "//a[contains(@href, '/login')]",
                "//a[contains(@href, '/signin')]",
                "//button[contains(text(), 'Login')]",
                "//button[contains(text(), 'Sign In')]",
                "//a[contains(text(), 'Login')]",
                "//a[contains(text(), 'Sign In')]"
            ]
            
            for indicator in logout_indicators:
                try:
                    elements = self.driver.find_elements(By.XPATH, indicator)
                    if elements:
                        logger.info(f"Çıkış göstergesi bulundu: {indicator}")
                        logger.info("Kullanıcı giriş yapmamış")
                        return False
                except NoSuchElementException:
                    continue
            
            # Son kontrol: URL'de giriş sayfası var mı?
            current_url = self.driver.current_url.lower()
            if 'login' in current_url or 'signin' in current_url:
                logger.info("URL'de giriş sayfası tespit edildi")
                return False
            
            logger.info("Giriş durumu belirsiz - manuel kontrol gerekli")
            return False
            
        except Exception as e:
            logger.error(f"Giriş durumu kontrol edilemedi: {e}")
            return False
    
    def wait_for_login(self):
        """Kullanıcının giriş yapmasını bekle"""
        logger.info("Giriş yapmanız bekleniyor...")
        logger.info("Giriş yaptıktan sonra bu pencereyi kapatmayın!")
        logger.info("Giriş yaptıktan sonra 'status' komutunu yazarak kontrol edebilirsiniz")
        
        max_wait_time = 600  # 10 dakika
        start_time = time.time()
        last_status = False
        
        while time.time() - start_time < max_wait_time:
            current_status = self.check_login_status()
            
            # Giriş durumu değiştiyse logla
            if current_status != last_status:
                if current_status:
                    logger.info("✅ Giriş başarılı tespit edildi!")
                    logger.info("Oturum kaydediliyor...")
                    self.save_session()
                    return True
                else:
                    logger.info("❌ Giriş yapılmamış durumda")
                last_status = current_status
            
            time.sleep(3)  # 3 saniyede bir kontrol et
        
        logger.warning("Giriş zaman aşımına uğradı")
        return False
    
    def get_authorization_code(self):
        """Authorization kodunu al"""
        try:
            # Önce giriş durumunu kontrol et
            if not self.check_login_status():
                logger.warning("Giriş yapılmamış, oturum yükleniyor...")
                if not self.load_session():
                    logger.error("Oturum yüklenemedi, manuel giriş gerekli")
                    return None
            
            logger.info("Authorization kodu alınıyor...")
            
            # Önce ana sayfaya git ve network isteklerini yakala
            logger.info("Ana sayfaya gidiliyor ve network istekleri yakalanıyor...")
            self.driver.get("https://www.g2g.com")
            time.sleep(5)  # Sayfanın tam yüklenmesini bekle
            
            # Network isteklerini yakala
            auth_code = self.extract_auth_code_from_network()
            
            if auth_code:
                logger.info(f"Authorization kodu başarıyla alındı: {auth_code[:50]}...")
                return auth_code
            
            # Eğer ana sayfadan bulunamazsa, API endpoint'ine git
            logger.info("API endpoint'ine gidiliyor...")
            api_url = "https://sls.g2g.com/offer/keyword_relation/service?include_settings=1&include_gc=1&v=v2"
            self.driver.get(api_url)
            time.sleep(3)
            
            # Tekrar dene
            auth_code = self.extract_auth_code_from_network()
            
            if auth_code:
                logger.info(f"Authorization kodu başarıyla alındı: {auth_code[:50]}...")
                return auth_code
            else:
                logger.error("Authorization kodu alınamadı")
                return None
                
        except Exception as e:
            logger.error(f"Authorization kodu alınırken hata: {e}")
            return None
    
    def extract_auth_code_from_network(self):
        """Network isteklerinden authorization kodunu çıkar"""
        try:
            # Yöntem 1: JavaScript ile network isteklerini yakala
            logger.info("JavaScript ile network istekleri yakalanıyor...")
            auth_token = self.driver.execute_script("""
                // XMLHttpRequest'i override et
                const originalXHROpen = XMLHttpRequest.prototype.open;
                const originalXHRSend = XMLHttpRequest.prototype.send;
                const originalFetch = window.fetch;
                let capturedToken = null;
                
                // XMLHttpRequest override
                XMLHttpRequest.prototype.open = function(method, url, ...args) {
                    this._url = url;
                    this._method = method;
                    return originalXHROpen.apply(this, [method, url, ...args]);
                };
                
                XMLHttpRequest.prototype.send = function(data) {
                    if (this._url && this._url.includes('sls.g2g.com')) {
                        const authHeader = this.getRequestHeader('authorization');
                        if (authHeader && authHeader.includes('eyJ')) {
                            capturedToken = authHeader;
                            console.log('XHR Token yakalandı:', authHeader);
                        }
                    }
                    return originalXHRSend.apply(this, [data]);
                };
                
                // Fetch override
                window.fetch = function(url, options = {}) {
                    if (url.includes('sls.g2g.com')) {
                        const authHeader = options.headers && options.headers.authorization;
                        if (authHeader && authHeader.includes('eyJ')) {
                            capturedToken = authHeader;
                            console.log('Fetch Token yakalandı:', authHeader);
                        }
                    }
                    return originalFetch.apply(this, [url, options]);
                };
                
                return capturedToken;
            """)
            
            if auth_token:
                logger.info("JavaScript ile token yakalandı!")
                return auth_token
            
            # Yöntem 2: Network log'larını kontrol et
            logger.info("Network log'ları kontrol ediliyor...")
            try:
                logs = self.driver.get_log('performance')
                for log in logs:
                    try:
                        message = json.loads(log['message'])
                        if message['message']['method'] == 'Network.requestWillBeSent':
                            request = message['message']['params']['request']
                            headers = request.get('headers', {})
                            if 'authorization' in headers:
                                auth_token = headers['authorization']
                                if 'eyJ' in auth_token:
                                    logger.info("Network log'undan token bulundu!")
                                    return auth_token
                    except:
                        continue
            except Exception as e:
                logger.warning(f"Network log'ları okunamadı: {e}")
            
            # Yöntem 3: Sayfayı yenile ve network isteklerini yakala
            logger.info("Sayfa yenileniyor ve network istekleri yakalanıyor...")
            self.driver.refresh()
            time.sleep(3)
            
            # Tekrar JavaScript ile kontrol et
            auth_token = self.driver.execute_script("""
                return window.capturedToken || null;
            """)
            
            if auth_token:
                logger.info("Yenileme sonrası token yakalandı!")
                return auth_token
            
            # Yöntem 4: LocalStorage ve SessionStorage kontrolü
            logger.info("Storage alanları kontrol ediliyor...")
            auth_token = self.driver.execute_script("""
                // LocalStorage kontrolü
                for (let i = 0; i < localStorage.length; i++) {
                    const key = localStorage.key(i);
                    const value = localStorage.getItem(key);
                    if (value && value.includes('eyJ')) {
                        return value;
                    }
                }
                
                // SessionStorage kontrolü
                for (let i = 0; i < sessionStorage.length; i++) {
                    const key = sessionStorage.key(i);
                    const value = sessionStorage.getItem(key);
                    if (value && value.includes('eyJ')) {
                        return value;
                    }
                }
                
                return null;
            """)
            
            if auth_token:
                logger.info("Storage'dan token bulundu!")
                return auth_token
            
            return None
            
        except Exception as e:
            logger.error(f"Token çıkarılırken hata: {e}")
            return None
    
    def start_session(self):
        """Oturumu başlat"""
        try:
            if not self.setup_driver():
                return False
            
            # Önce kaydedilmiş oturumu yüklemeyi dene
            if self.load_session():
                if self.check_login_status():
                    logger.info("Kaydedilmiş oturum başarıyla yüklendi")
                    return True
                else:
                    logger.info("Kaydedilmiş oturum geçersiz, yeni giriş gerekli")
            
            # G2G.com'a git
            self.driver.get(self.base_url)
            time.sleep(3)
            
            # Giriş yapmasını bekle
            if self.wait_for_login():
                logger.info("Oturum başarıyla başlatıldı")
                return True
            else:
                logger.error("Oturum başlatılamadı")
                return False
                
        except Exception as e:
            logger.error(f"Oturum başlatılırken hata: {e}")
            return False
    
    def close_session(self):
        """Oturumu kapat"""
        try:
            if self.driver:
                self.driver.quit()
                logger.info("Oturum kapatıldı")
            
            # Profil dizinini koru (kalıcı olması için)
            logger.info(f"Profil dizini korundu: {self.profile_dir}")
                    
        except Exception as e:
            logger.error(f"Oturum kapatılırken hata: {e}")

def main():
    """Ana fonksiyon"""
    g2g = G2GAutomation()
    
    try:
        print("G2G.com Oturum Yöneticisi Başlatılıyor...")
        print("=" * 50)
        
        if g2g.start_session():
            print("\n✅ Oturum başarıyla başlatıldı!")
            print("🔑 Authorization kodu almak için 'get_code' yazın")
            print("❌ Çıkmak için 'quit' yazın")
            print("=" * 50)
            
            while True:
                command = input("\nKomut girin: ").strip().lower()
                
                if command == 'get_code':
                    auth_code = g2g.get_authorization_code()
                    if auth_code:
                        print(f"🔑 Authorization Kodu: {auth_code}")
                    else:
                        print("❌ Authorization kodu alınamadı")
                
                elif command == 'quit':
                    break
                
                elif command == 'status':
                    if g2g.check_login_status():
                        print("✅ Giriş yapılmış")
                    else:
                        print("❌ Giriş yapılmamış")
                
                elif command == 'save':
                    if g2g.save_session():
                        print("✅ Oturum kaydedildi")
                    else:
                        print("❌ Oturum kaydedilemedi")
                
                else:
                    print("Geçersiz komut. Kullanılabilir komutlar: get_code, status, save, quit")
        
        else:
            print("❌ Oturum başlatılamadı")
    
    except KeyboardInterrupt:
        print("\n\nProgram kullanıcı tarafından durduruldu")
    
    finally:
        g2g.close_session()
        print("Program sonlandırıldı")

if __name__ == "__main__":
    main()
