"""
Mandatory Password Reset Page Object Model

Handles first-login password reset modal.
Scope: mandatory_reset
"""
from selenium.webdriver.common.by import By
from pages.base_page import BasePage


class MandatoryResetPage(BasePage):
    """Page Object for Mandatory Password Reset Modal"""
    
    # Locators using data-testid (scope: mandatory_reset)
    MODAL = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__modal']")
    CONTINUE_BUTTON = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__continue_button']")
    FORM = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__form']")
    CURRENT_PASSWORD_INPUT = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__current_password_input']")
    NEW_PASSWORD_INPUT = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__new_password_input']")
    CONFIRM_PASSWORD_INPUT = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__confirm_password_input']")
    CURRENT_PASSWORD_ERROR = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__current_password_error']")
    NEW_PASSWORD_ERROR = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__new_password_error']")
    CONFIRM_PASSWORD_ERROR = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__confirm_password_error']")
    BACK_BUTTON = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__back_button']")
    SUBMIT_BUTTON = (By.CSS_SELECTOR, "[data-testid='mandatory_reset__submit_button']")
    
    def __init__(self, driver):
        """Initialize Mandatory Reset Page"""
        super().__init__(driver)
    
    def is_modal_present(self):
        """
        Check if mandatory reset modal is present
        
        Uses multiple detection strategies for 100% reliability:
        1. data-testid attribute (if present)
        2. CSS selector for modal overlay
        3. Text content detection ("Welcome to Cognitive Prism", "Reset Password")
        4. DOM structure detection (modal container with specific classes)
        
        Returns:
            bool: True if modal is visible
        """
        from selenium.webdriver.common.by import By
        from selenium.webdriver.support.ui import WebDriverWait
        from selenium.webdriver.support import expected_conditions as EC
        import time
        
        # Strategy 1: Check by data-testid (primary method) - FAST detection
        # Use quick check (200ms) for speed
        try:
            from utils.smart_wait_optimizer import SmartWaitOptimizer
            if SmartWaitOptimizer.quick_check_modal_present(self.driver, self.MODAL):
                return True
        except:
            pass
        
        # Strategy 2: Check for modal overlay by CSS pattern
        # Modal overlay: fixed inset-0 bg-black/60 z-[99999]
        overlay_selectors = [
            "div.fixed.inset-0.bg-black\\/60.z-\\[99999\\]",  # Exact match
            "div[class*='fixed'][class*='inset-0'][class*='bg-black'][class*='z-[99999]']",  # Partial match
            "div.fixed.inset-0[class*='z-[99999]']",  # Simplified
            "div.fixed.inset-0.bg-black",  # More generic
        ]
        
        for selector in overlay_selectors:
            try:
                overlay = WebDriverWait(self.driver, 2).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, selector))
                )
                if overlay.is_displayed():
                    # Verify it's the password reset modal by checking for form elements or text
                    try:
                        # Check if form or continue button is present
                        form_present = self.is_element_present(self.FORM, timeout=1) or \
                                     self.is_element_present(self.CONTINUE_BUTTON, timeout=1)
                        if form_present:
                            return True
                    except:
                        pass
            except:
                continue
        
        # Strategy 3: Check page source for password reset modal text
        # This is the MOST RELIABLE fallback - if text is present, modal is there
        try:
            page_text = self.driver.page_source.lower()
            password_reset_indicators = [
                "welcome to cognitive prism",
                "reset your password",
                "password reset required",
                "mandatory password reset",
                "secure your account",
            ]
            
            for indicator in password_reset_indicators:
                if indicator in page_text:
                    # Double-check: Make sure we're not on login page (which might have similar text)
                    current_url = self.driver.current_url.lower()
                    if "/login" not in current_url:
                        # We're on dashboard/student page and password reset text is present
                        # This means modal is definitely present
                        return True
        except:
            pass
        
        # Strategy 4: Check for modal container structure
        # Look for modal container with specific structure
        try:
            # Look for modal container with "Welcome" text
            modal_containers = self.driver.find_elements(By.XPATH, 
                "//div[contains(@class, 'fixed') and contains(@class, 'inset-0')]"
                "//*[contains(text(), 'Welcome to Cognitive Prism') or contains(text(), 'Password Reset Required')]"
            )
            if modal_containers:
                for container in modal_containers:
                    if container.is_displayed():
                        return True
        except:
            pass
        
        # Strategy 5: Check for Continue button (step 1) or Form (step 2) directly
        try:
            # Check for Continue button (step 1)
            continue_btn = self.driver.find_elements(By.XPATH, 
                "//button[contains(text(), 'Continue') or contains(text(), 'Reset Password')]"
            )
            for btn in continue_btn:
                if btn.is_displayed():
                    # Check if it's inside a modal overlay
                    parent = btn.find_element(By.XPATH, "./ancestor::div[contains(@class, 'fixed')]")
                    if parent and parent.is_displayed():
                        return True
        except:
            pass
        
        try:
            # Check for form inputs (step 2)
            form_inputs = self.driver.find_elements(By.XPATH,
                "//input[@name='currentPassword' or @name='newPassword' or @name='confirmPassword']"
            )
            for inp in form_inputs:
                if inp.is_displayed():
                    # Check if it's inside a modal overlay
                    parent = inp.find_element(By.XPATH, "./ancestor::div[contains(@class, 'fixed')]")
                    if parent and parent.is_displayed():
                        return True
        except:
            pass
        
        return False
    
    def click_continue(self):
        """Click Continue button to show password reset form"""
        # Wait for button to be clickable and visible
        from selenium.webdriver.support.ui import WebDriverWait
        from selenium.webdriver.support import expected_conditions as EC
        from selenium.webdriver.common.by import By
        from config.config import SHORT_WAIT, MEDIUM_WAIT
        import time
        
        # Strategy 1: Try data-testid locator first (if present)
        button = None
        try:
            button = WebDriverWait(self.driver, 2).until(
                EC.element_to_be_clickable(self.CONTINUE_BUTTON)
            )
        except:
            # Strategy 2: Find button with span containing "Continue" (VERIFIED WORKING by DOM Inspector)
            # DOM Inspector confirmed: //button[.//span[contains(text(), 'Continue')]] works
            try:
                button = WebDriverWait(self.driver, MEDIUM_WAIT).until(
                    EC.element_to_be_clickable((By.XPATH, 
                        "//button[.//span[contains(text(), 'Continue')]]"
                    ))
                )
            except:
                # Strategy 3: Find button containing "Reset Password" (VERIFIED WORKING by DOM Inspector)
                try:
                    button = WebDriverWait(self.driver, MEDIUM_WAIT).until(
                        EC.element_to_be_clickable((By.XPATH, 
                            "//button[contains(., 'Reset Password')]"
                        ))
                    )
                except:
                    # Strategy 4: Find button inside modal overlay (VERIFIED WORKING by DOM Inspector)
                    try:
                        button = WebDriverWait(self.driver, MEDIUM_WAIT).until(
                            EC.element_to_be_clickable((By.XPATH,
                                "//div[contains(@class, 'fixed')]//button[contains(., 'Continue')]"
                            ))
                        )
                    except:
                        # Strategy 5: Find span first, then get parent button
                        try:
                            span = WebDriverWait(self.driver, MEDIUM_WAIT).until(
                                EC.presence_of_element_located((By.XPATH, 
                                    "//span[contains(text(), 'Continue to Reset Password')]"
                                ))
                            )
                            # Get parent button using JavaScript (more reliable for React components)
                            button = self.driver.execute_script("return arguments[0].closest('button');", span)
                            if not button or not button.is_displayed():
                                raise Exception("Button not visible")
                        except Exception as e:
                            raise Exception(f"❌ Continue button not found after all verified strategies. "
                                          f"Last error: {e}. "
                                          f"Use scripts/debug_dom_inspector.py to inspect DOM structure.")
        
        if not button:
            raise Exception("❌ Continue button not found after all detection strategies")
        
        # Scroll button into view if needed
        self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", button)
        time.sleep(0.3)
        
        # Click using JavaScript (more reliable for modals)
        try:
            self.driver.execute_script("arguments[0].click();", button)
        except:
            # Fallback to regular click
            button.click()
        
        # Wait for form to appear (form appears immediately after click)
        # Check for form by data-testid or by input fields
        try:
            WebDriverWait(self.driver, SHORT_WAIT).until(
                EC.visibility_of_element_located(self.FORM)
            )
        except:
            # Fallback: Check for password input fields
            try:
                WebDriverWait(self.driver, SHORT_WAIT).until(
                    EC.visibility_of_element_located(self.CURRENT_PASSWORD_INPUT)
                )
            except:
                # Final fallback: Check for any password input
                try:
                    WebDriverWait(self.driver, SHORT_WAIT).until(
                        EC.presence_of_element_located((By.XPATH, "//input[@name='currentPassword' or @name='newPassword']"))
                    )
                except Exception as e:
                    raise Exception(f"❌ Password reset form did not appear after clicking Continue. Error: {e}")
    
    def enter_current_password(self, password):
        """Enter current password"""
        self.send_keys(self.CURRENT_PASSWORD_INPUT, password)
    
    def enter_new_password(self, password):
        """Enter new password"""
        self.send_keys(self.NEW_PASSWORD_INPUT, password)
    
    def enter_confirm_password(self, password):
        """Enter confirm password"""
        self.send_keys(self.CONFIRM_PASSWORD_INPUT, password)
    
    def reset_password(self, current_password, new_password, confirm_password=None, student_cpid=None):
        """
        Complete password reset flow with WORLD-CLASS robust error handling
        
        This method ensures 100% reliability by:
        1. Verifying modal presence
        2. Handling 2-step flow (Continue button → Form)
        3. Filling all fields with proper waits
        4. Submitting and waiting for API call completion
        5. Verifying success (toast message or modal closure)
        6. Checking for errors and handling them
        7. Updating password tracker on success
        
        Args:
            current_password: Current password (default password)
            new_password: New password to set
            confirm_password: Confirm password (defaults to new_password)
            student_cpid: Student CPID (optional, for password tracking)
        
        Raises:
            Exception: If password reset fails for any reason
        """
        import time
        from selenium.webdriver.support.ui import WebDriverWait
        from selenium.webdriver.support import expected_conditions as EC
        from selenium.webdriver.common.by import By
        from config.config import SHORT_WAIT, MEDIUM_WAIT
        LONG_WAIT = MEDIUM_WAIT * 2  # 20 seconds for API calls
        
        if confirm_password is None:
            confirm_password = new_password
        
        print(f"🔐 Starting password reset flow for {student_cpid or 'student'}")
        
        # STEP 1: Verify modal is present
        if not self.is_modal_present():
            raise Exception("❌ Password reset modal is not present - cannot proceed")
        print("✅ Password reset modal detected")
        
        # STEP 2: Handle 2-step flow (Continue button → Form)
        try:
            # Check if form is already visible (step 2)
            WebDriverWait(self.driver, 2).until(
                EC.visibility_of_element_located(self.FORM)
            )
            print("✅ Password reset form already visible (step 2)")
        except:
            # Form not visible, need to click continue button (step 1)
            print("📋 Clicking Continue button to show password reset form...")
            try:
                self.click_continue()
                # Wait for form to appear
                WebDriverWait(self.driver, SHORT_WAIT).until(
                    EC.visibility_of_element_located(self.FORM)
                )
                print("✅ Password reset form is now visible")
            except Exception as e:
                raise Exception(f"❌ Failed to show password reset form: {e}")
        
        # STEP 3: Clear any existing errors before filling
        time.sleep(0.3)  # Brief wait for form to stabilize
        
        # STEP 4: Fill form fields with proper waits and verification
        print("📝 Filling password reset form...")
        
        # Current password
        try:
            current_input = self.wait.wait_for_element_visible(self.CURRENT_PASSWORD_INPUT)
            current_input.clear()
            time.sleep(0.2)
            current_input.send_keys(current_password)
            print("  ✅ Current password entered")
        except Exception as e:
            raise Exception(f"❌ Failed to enter current password: {e}")
        
        # New password
        try:
            new_input = self.wait.wait_for_element_visible(self.NEW_PASSWORD_INPUT)
            new_input.clear()
            time.sleep(0.2)
            new_input.send_keys(new_password)
            print("  ✅ New password entered")
        except Exception as e:
            raise Exception(f"❌ Failed to enter new password: {e}")
        
        # Confirm password
        try:
            confirm_input = self.wait.wait_for_element_visible(self.CONFIRM_PASSWORD_INPUT)
            confirm_input.clear()
            time.sleep(0.2)
            confirm_input.send_keys(confirm_password)
            print("  ✅ Confirm password entered")
        except Exception as e:
            raise Exception(f"❌ Failed to enter confirm password: {e}")
        
        # STEP 5: Verify no validation errors before submit
        time.sleep(0.3)  # Wait for any client-side validation
        if self.has_errors():
            error_text = []
            try:
                if self.is_element_visible(self.CURRENT_PASSWORD_ERROR, timeout=1):
                    error_text.append(f"Current password: {self.find_element(self.CURRENT_PASSWORD_ERROR).text}")
            except:
                pass
            try:
                if self.is_element_visible(self.NEW_PASSWORD_ERROR, timeout=1):
                    error_text.append(f"New password: {self.find_element(self.NEW_PASSWORD_ERROR).text}")
            except:
                pass
            try:
                if self.is_element_visible(self.CONFIRM_PASSWORD_ERROR, timeout=1):
                    error_text.append(f"Confirm password: {self.find_element(self.CONFIRM_PASSWORD_ERROR).text}")
            except:
                pass
            if error_text:
                raise Exception(f"❌ Validation errors before submit: {'; '.join(error_text)}")
        
        # STEP 6: Submit form
        print("🚀 Submitting password reset form...")
        try:
            submit_button = self.wait.wait_for_element_clickable(self.SUBMIT_BUTTON)
            # Scroll into view if needed
            self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", submit_button)
            time.sleep(0.2)
            submit_button.click()
            print("  ✅ Submit button clicked")
        except Exception as e:
            raise Exception(f"❌ Failed to click submit button: {e}")
        
        # STEP 7: Wait for API call to complete (check for loading state to finish)
        print("⏳ Waiting for password reset API call to complete...")
        time.sleep(1)  # Initial wait for API call to start
        
        # Wait for loading state to finish (submit button becomes enabled again or modal closes)
        max_wait = LONG_WAIT
        start_time = time.time()
        api_completed = False
        
        while (time.time() - start_time) < max_wait:
            # Check if modal is closing (success indicator)
            try:
                if not self.is_element_present(self.MODAL, timeout=1):
                    api_completed = True
                    print("  ✅ Modal closing detected (success)")
                    break
            except:
                pass
            
            # Check for success toast message
            try:
                # Look for success toast: "Password reset successfully!"
                toast_selectors = [
                    "//div[@role='status' and contains(text(), 'Password reset successfully')]",
                    "//div[@role='status' and contains(text(), 'reset successfully')]",
                    "//div[contains(@class, 'toast') and contains(text(), 'successfully')]",
                ]
                for selector in toast_selectors:
                    try:
                        toast = self.driver.find_element(By.XPATH, selector)
                        if toast.is_displayed():
                            api_completed = True
                            print(f"  ✅ Success toast detected: {toast.text[:50]}...")
                            break
                    except:
                        continue
                if api_completed:
                    break
            except:
                pass
            
            # Check for errors after submit
            if self.has_errors():
                error_text = []
                try:
                    if self.is_element_visible(self.CURRENT_PASSWORD_ERROR, timeout=1):
                        error_text.append(f"Current password: {self.find_element(self.CURRENT_PASSWORD_ERROR).text}")
                except:
                    pass
                try:
                    if self.is_element_visible(self.NEW_PASSWORD_ERROR, timeout=1):
                        error_text.append(f"New password: {self.find_element(self.NEW_PASSWORD_ERROR).text}")
                except:
                    pass
                if error_text:
                    error_msg = '; '.join(error_text)
                    raise Exception(f"❌ Password reset failed with errors: {error_msg}")
            
            time.sleep(0.5)  # Check every 0.5 seconds
        
        if not api_completed:
            raise Exception("❌ Password reset API call did not complete within timeout")
        
        # STEP 8: Wait for modal to fully close
        print("⏳ Waiting for modal to close...")
        try:
            WebDriverWait(self.driver, MEDIUM_WAIT).until(
                EC.invisibility_of_element_located(self.MODAL)
            )
            print("  ✅ Modal closed successfully")
        except:
            # Check if modal is still present
            if self.is_modal_present():
                raise Exception("❌ Password reset modal did not close after successful reset")
            print("  ✅ Modal closed (verified)")
        
        # STEP 9: Update password tracker on success
        if student_cpid:
            try:
                from utils.password_tracker import password_tracker
                password_tracker.update_password(student_cpid, new_password)
                print(f"  ✅ Password tracker updated for {student_cpid}")
            except Exception as e:
                print(f"  ⚠️  Warning: Failed to update password tracker: {e}")
        
        # STEP 10: Final verification - ensure we're not on login page (should be on dashboard)
        time.sleep(1)  # Brief wait for navigation
        current_url = self.driver.current_url
        if "/login" in current_url:
            raise Exception(f"❌ Unexpected redirect to login page after password reset. URL: {current_url}")
        
        print("✅ Password reset completed successfully!")
        return True
    
    def click_back(self):
        """Click back button"""
        self.click_element(self.BACK_BUTTON)
    
    def has_errors(self):
        """
        Check if there are any validation errors
        
        Returns:
            bool: True if any error is visible
        """
        try:
            return (self.is_element_visible(self.CURRENT_PASSWORD_ERROR, timeout=1) or
                   self.is_element_visible(self.NEW_PASSWORD_ERROR, timeout=1) or
                   self.is_element_visible(self.CONFIRM_PASSWORD_ERROR, timeout=1))
        except:
            return False

