"""
NAS Sharing Auth Module - Login flow với OTP modal support

EXTRACTED từ download_link.py, adapted cho modal OTP pattern
"""

import os
import time
from typing import Optional, Tuple, TYPE_CHECKING
from selenium import webdriver
from selenium.webdriver.common.by import By

if TYPE_CHECKING:
    from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


def get_dsm_credentials() -> Tuple[str, str]:
    """
    Get DSM credentials from environment
    
    Returns:
        (username, password) tuple
    
    Raises:
        ValueError: If credentials not set in .env.local
    """
    username = os.getenv("NAS_USERNAME")
    password = os.getenv("NAS_PASSWORD")
    
    if not username or not password:
        raise ValueError("NAS_USERNAME and NAS_PASSWORD must be set in .env.local")
    
    return username, password


def perform_login(
    driver: webdriver.Chrome,
    username: Optional[str] = None,
    password: Optional[str] = None,
    otp_callback=None
) -> bool:
    """
    Perform DSM login with OTP modal support
    
    EXTRACTED từ download_link.py DSMSeleniumLogin.login()
    MODIFIED: Dùng callback cho OTP thay vì manual input
    
    Args:
        driver: Selenium WebDriver instance
        username: DSM username (default: from env)
        password: DSM password (default: from env)
        otp_callback: Function() -> Optional[str] to get OTP code from modal
                     Should return None if timeout/cancelled
    
    Returns:
        True if login successful
    """
    if username is None or password is None:
        username, password = get_dsm_credentials()
    
    try:
        # Get DSM URL from env
        dsm_url = os.getenv("NAS_DSM_URL")
        if not dsm_url:
            raise ValueError("NAS_DSM_URL must be set in .env.local")
        
        print(f"\n🌐 Đang truy cập: {dsm_url}")
        print("   (Trang có thể mất 30-60s để load...)")
        
        # Navigate to DSM
        try:
            driver.get(dsm_url)
        except Exception as e:
            print(f"⚠️  Timeout khi load trang, nhưng tiếp tục thử...")
        
        time.sleep(5)
        
        wait = WebDriverWait(driver, 30)
        
        # === STEP 1: Enter USERNAME ===
        print("🔍 BƯỚC 1: Đang tìm form username...")
        
        # NO FALLBACK - Throw error nếu selector không match
        username_input = wait.until(
            EC.visibility_of_element_located((By.CSS_SELECTOR,
                "input#login_username, input[type='text'][name='username'], input.syno-ux-textfield[type='text']"))
        )
        
        print(f"📝 Nhập username: {username}")
        username_input.click()
        time.sleep(0.5)
        username_input.clear()
        time.sleep(0.5)
        username_input.send_keys(username)
        time.sleep(1)
        
        # Click Next button
        print("🖱️  Tìm nút Next...")
        next_button = _find_button(driver, [
            "div[syno-id='account-panel-next-btn']",  # DSM 7.x
            "div.login-btn[role='button']",
            "button#login-btn",
            "button[type='submit']",
        ])
        
        if not next_button:
            raise RuntimeError("Không tìm thấy nút Next")
        
        print("🖱️  Click nút Next...")
        next_button.click()
        time.sleep(3)
        
        # === STEP 2: Enter PASSWORD ===
        print("\n🔍 BƯỚC 2: Đang tìm form password...")
        
        try:
            password_input = wait.until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, "input[syno-id='password']"))
            )
        except:
            try:
                password_input = wait.until(
                    EC.visibility_of_element_located((By.CSS_SELECTOR, "input[type='password'][name='current-password']"))
                )
            except:
                password_input = wait.until(
                    EC.visibility_of_element_located((By.CSS_SELECTOR, "input[type='password']"))
                )
        
        print("🔑 Nhập password...")
        password_input.click()
        time.sleep(0.5)
        password_input.clear()
        time.sleep(0.5)
        password_input.send_keys(password)
        time.sleep(1)
        
        # Tick "Stay signed in" checkbox
        print("☑️  Tick checkbox 'Stay signed in'...")
        try:
            stay_signed_checkbox = driver.find_element(By.CSS_SELECTOR,
                "div.login-checkbox input[type='checkbox']")
            
            if not stay_signed_checkbox.is_selected():
                checkbox_label = driver.find_element(By.CSS_SELECTOR,
                    "div.login-checkbox label.box")
                checkbox_label.click()
                print("   ✅ Đã tick 'Stay signed in'")
                time.sleep(0.5)
            else:
                print("   ℹ️  Checkbox đã được tick sẵn")
        except Exception as e:
            print(f"   ⚠️  Không tìm thấy checkbox (không sao): {e}")
        
        time.sleep(0.5)
        
        # Click Sign In button
        print("🖱️  Tìm nút Sign In...")
        signin_button = _find_button(driver, [
            "div[syno-id='password-panel-next-btn']",  # DSM 7.x password panel
            "div[syno-id='account-panel-next-btn']",
            "div.login-btn[role='button']",
            "button#login-btn",
            "button[type='submit']",
        ])
        
        if not signin_button:
            raise RuntimeError("Không tìm thấy nút Sign In")
        
        print("🖱️  Click nút Sign In...")
        signin_button.click()
        time.sleep(3)
        
        # === STEP 3: Handle OTP if needed ===
        otp_required = detect_otp_modal(driver)
        
        if otp_required:
            print("\n" + "=" * 70)
            print("🔐 PHÁT HIỆN YÊU CẦU OTP (2-FACTOR AUTHENTICATION)")
            print("=" * 70)
            
            if otp_callback:
                print("⏳ Đang đợi OTP từ frontend modal...")
                otp_code = otp_callback()
                
                if not otp_code:
                    print("❌ Không nhận được OTP (timeout hoặc cancelled)")
                    return False
                
                # Submit OTP
                print(f"✅ Nhận OTP: {otp_code[:2]}***")
                if not submit_otp_code(driver, otp_code):
                    print("❌ Lỗi submit OTP")
                    return False
                
                time.sleep(3)
            else:
                print("⚠️  Không có OTP callback, bỏ qua...")
                return False
        else:
            print("ℹ️  Không phát hiện yêu cầu OTP")
        
        # === STEP 4: Wait for login success ===
        print("⏳ Đang chờ đăng nhập hoàn tất...")
        return wait_for_login_success(driver, timeout=15)
        
    except Exception as e:
        print(f"❌ Lỗi trong quá trình đăng nhập: {e}")
        import traceback
        traceback.print_exc()
        return False


def detect_otp_modal(driver: webdriver.Chrome) -> bool:
    """
    Detect if OTP modal is shown
    
    EXTRACTED từ download_link.py logic
    
    Returns:
        True if OTP input is visible
    """
    try:
        # Method 1: Find title "Enter verification code"
        otp_title = driver.find_element(By.XPATH,
            "//*[contains(text(), 'Enter verification code') or contains(text(), 'verification code')]")
        if otp_title.is_displayed():
            return True
    except:
        pass
    
    try:
        # Method 2: Find input with name='one-time-code'
        otp_input = driver.find_element(By.CSS_SELECTOR, "input[name='one-time-code']")
        if otp_input.is_displayed():
            return True
    except:
        pass
    
    try:
        # Method 3: Find OTP button with syno-id
        otp_button = driver.find_element(By.CSS_SELECTOR, "div[syno-id='otp-panel-next-btn']")
        if otp_button.is_displayed():
            return True
    except:
        pass
    
    return False


def submit_otp_code(driver: webdriver.Chrome, otp_code: str) -> bool:
    """
    Submit OTP code to form
    
    Args:
        driver: Selenium WebDriver
        otp_code: 6-digit OTP code
    
    Returns:
        True if submitted successfully
    """
    try:
        # Find OTP input
        otp_input = driver.find_element(By.CSS_SELECTOR, "input[name='one-time-code']")
        
        if not otp_input.is_displayed():
            print("❌ OTP input không visible")
            return False
        
        # Clear and enter OTP
        otp_input.clear()
        otp_input.send_keys(otp_code)
        time.sleep(0.5)
        
        # Click submit or press Enter
        try:
            otp_button = driver.find_element(By.CSS_SELECTOR, "div[syno-id='otp-panel-next-btn']")
            otp_button.click()
        except:
            # Fallback: press Enter
            otp_input.send_keys("\n")
        
        print("✅ OTP đã submit")
        return True
        
    except Exception as e:
        print(f"❌ Lỗi submit OTP: {e}")
        return False


def wait_for_login_success(driver: webdriver.Chrome, timeout: int = 15) -> bool:
    """
    Wait for login to complete
    
    EXTRACTED từ download_link.py is_logged_in() check
    
    Args:
        driver: Selenium WebDriver
        timeout: Max seconds to wait
    
    Returns:
        True if "Synology Drive" div detected (indicates successful login)
        
    Raises:
        RuntimeError: If login not detected after timeout
    """
    for i in range(timeout):
        try:
            # Check for "Synology Drive" text - only appears after login
            elem = driver.find_element(By.XPATH, "//div[contains(text(), 'Synology Drive')]")
            if elem is not None:
                print("✅ Đăng nhập thành công!")
                return True
        except Exception as e:
            # Log specific error for debugging
            if i == 0:  # Only log on first attempt
                print(f"🔍 Chưa thấy 'Synology Drive', đang đợi... (Error: {type(e).__name__})")
        
        time.sleep(1)
    
    # Timeout - throw error thay vì return False
    print("❌ KHÔNG phát hiện đăng nhập thành công sau timeout")
    raise RuntimeError(
        f"Login verification failed: 'Synology Drive' element not found after {timeout}s. "
        f"Login may have failed or page structure changed."
    )


def is_logged_in(driver: webdriver.Chrome) -> bool:
    """
    Quick check if already logged in
    
    EXACT COPY từ download_link.py DSMSeleniumLogin.is_logged_in()
    
    Returns:
        True if "Synology Drive" div found
    """
    if not driver:
        return False
    
    try:
        elem = driver.find_element(By.XPATH, "//div[contains(text(), 'Synology Drive')]")
        return elem is not None
    except:
        return False


def _find_button(driver: webdriver.Chrome, selectors: list) -> Optional['WebElement']:
    """
    Helper: Find first visible button from selector list
    
    Args:
        driver: Selenium WebDriver
        selectors: List of CSS selectors to try
    
    Returns:
        WebElement if found, None otherwise
    """
    for selector in selectors:
        try:
            if selector.startswith("//"):
                button = driver.find_element(By.XPATH, selector)
            else:
                button = driver.find_element(By.CSS_SELECTOR, selector)
            
            if button and button.is_displayed():
                return button
        except:
            continue
    
    return None
