#!/usr/bin/env python3
"""
Comprehensive DOM Verification Script

Systematically verifies ALL data-testid attributes by:
1. Logging in
2. Navigating through each tab of profile editor
3. Waiting for elements to load
4. Scrolling to make elements visible
5. Checking all attributes in each step
6. Reporting detailed findings
"""
import sys
from pathlib import Path
import json
import time

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

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.common.action_chains import ActionChains
from pages.login_page import LoginPage
from pages.mandatory_reset_page import MandatoryResetPage
from pages.profile_incomplete_page import ProfileIncompletePage
from pages.profile_editor_page import ProfileEditorPage
from utils.driver_manager import DriverManager
from config.config import TEST_NEW_PASSWORD, BASE_URL


def get_all_data_testids(driver, scroll_into_view=True):
    """Get all data-testid attributes from DOM, optionally scrolling elements into view"""
    elements = driver.find_elements(By.CSS_SELECTOR, "[data-testid]")
    testids = {}
    
    for elem in elements:
        try:
            testid = elem.get_attribute("data-testid")
            if testid:
                # Scroll into view if requested
                if scroll_into_view:
                    try:
                        driver.execute_script("arguments[0].scrollIntoView({block: 'center', behavior: 'smooth'});", elem)
                        time.sleep(0.1)  # Brief wait for scroll
                    except:
                        pass
                
                testids[testid] = {
                    "tag": elem.tag_name,
                    "type": elem.get_attribute("type") or elem.tag_name,
                    "visible": elem.is_displayed(),
                    "enabled": elem.is_enabled() if hasattr(elem, 'is_enabled') else True,
                    "text": elem.text[:50] if elem.text else "",
                    "value": elem.get_attribute("value")[:50] if elem.get_attribute("value") else ""
                }
        except Exception as e:
            # Element might have been removed from DOM
            continue
    
    return testids


def wait_for_tab_to_load(driver, tab_name, timeout=10):
    """Wait for a specific tab to be fully loaded"""
    try:
        # Wait for tab to be active/visible
        tab_locator = (By.CSS_SELECTOR, f"[data-testid='profile_editor__tab_{tab_name}']")
        WebDriverWait(driver, timeout).until(
            EC.presence_of_element_located(tab_locator)
        )
        
        # Wait a bit more for content to render
        time.sleep(1)
        
        # Scroll to top of form
        driver.execute_script("window.scrollTo(0, 0);")
        time.sleep(0.5)
        
        return True
    except Exception as e:
        print(f"⚠️  Warning: Could not verify tab {tab_name} loaded: {e}")
        return False


def navigate_to_tab_and_check(driver, tab_index, tab_name, expected_attributes):
    """Navigate to a specific tab and check for expected attributes"""
    print(f"\n{'='*80}")
    print(f"TAB {tab_index + 1}: {tab_name.upper().replace('_', ' ')}")
    print(f"{'='*80}")
    
    try:
        # Navigate to tab
        profile_editor = ProfileEditorPage(driver)
        profile_editor.navigate_to_tab(tab_index)
        time.sleep(2)  # Wait for tab content to load
        
        # Scroll through the tab to trigger lazy loading
        driver.execute_script("window.scrollTo(0, 0);")
        time.sleep(0.5)
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(1)
        driver.execute_script("window.scrollTo(0, 0);")
        time.sleep(0.5)
        
        # Get all testids in this tab
        all_testids = get_all_data_testids(driver, scroll_into_view=True)
        
        # Filter for profile_editor testids
        profile_testids = {tid: info for tid, info in all_testids.items() if tid.startswith("profile_editor__")}
        
        print(f"📋 Found {len(profile_testids)} profile_editor attributes in this tab")
        
        # Check expected attributes
        found = []
        missing = []
        
        for attr in expected_attributes:
            if attr in profile_testids:
                info = profile_testids[attr]
                status = "✅" if info["visible"] else "⚠️  (hidden)"
                print(f"{status} {attr}")
                found.append(attr)
            else:
                print(f"❌ MISSING: {attr}")
                missing.append(attr)
        
        # Check for unexpected attributes
        unexpected = [tid for tid in profile_testids if tid not in expected_attributes]
        if unexpected:
            print(f"\n⚠️  UNEXPECTED attributes found ({len(unexpected)}):")
            for tid in sorted(unexpected)[:10]:
                print(f"   - {tid}")
            if len(unexpected) > 10:
                print(f"   ... and {len(unexpected) - 10} more")
        
        return {
            "tab_name": tab_name,
            "found": found,
            "missing": missing,
            "unexpected": unexpected,
            "all_testids": list(profile_testids.keys())
        }
        
    except Exception as e:
        print(f"❌ Error checking tab {tab_name}: {e}")
        import traceback
        traceback.print_exc()
        return {
            "tab_name": tab_name,
            "found": [],
            "missing": expected_attributes,
            "unexpected": [],
            "all_testids": [],
            "error": str(e)
        }


def check_dynamic_checkboxes(driver, pattern_prefix, expected_count=None):
    """Check for dynamic checkboxes matching a pattern"""
    try:
        # Scroll through page to load all checkboxes
        driver.execute_script("window.scrollTo(0, 0);")
        time.sleep(0.3)
        
        # Find all checkboxes with matching pattern
        checkboxes = driver.find_elements(
            By.CSS_SELECTOR, 
            f"input[type='checkbox'][data-testid^='{pattern_prefix}']"
        )
        
        found_testids = []
        for cb in checkboxes:
            try:
                # Scroll checkbox into view
                driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", cb)
                time.sleep(0.1)
                
                testid = cb.get_attribute("data-testid")
                if testid and testid.startswith(pattern_prefix):
                    found_testids.append(testid)
            except:
                continue
        
        # Also try finding by CSS selector with wildcard
        all_elements = driver.find_elements(By.CSS_SELECTOR, "[data-testid]")
        for elem in all_elements:
            testid = elem.get_attribute("data-testid")
            if testid and testid.startswith(pattern_prefix) and testid not in found_testids:
                found_testids.append(testid)
        
        found_count = len(found_testids)
        status = "✅" if found_count > 0 else "❌"
        
        if expected_count:
            status = "✅" if found_count >= expected_count else "⚠️"
            print(f"{status} {pattern_prefix}: {found_count}/{expected_count} found")
        else:
            print(f"{status} {pattern_prefix}: {found_count} found")
        
        if found_testids:
            for tid in sorted(found_testids)[:5]:
                print(f"   - {tid}")
            if len(found_testids) > 5:
                print(f"   ... and {len(found_testids) - 5} more")
        
        return found_testids
        
    except Exception as e:
        print(f"❌ Error checking {pattern_prefix}: {e}")
        return []


def main():
    driver = None
    try:
        print("🚀 COMPREHENSIVE DOM VERIFICATION")
        print("="*80)
        print(f"🌐 Environment: {BASE_URL}")
        print(f"🔑 Credentials: BATBAT311A")
        print("="*80)
        
        # Initialize driver
        driver_manager = DriverManager()
        driver = driver_manager.get_driver(headless=False)
        driver.maximize_window()
        
        results = {
            "login": {},
            "dashboard": {},
            "student_nav": {},
            "password_reset": {},
            "profile_editor": {
                "tabs": {},
                "dynamic_checkboxes": {},
                "summary": {}
            }
        }
        
        # ============================================================
        # STEP 1: LOGIN
        # ============================================================
        print("\n" + "="*80)
        print("STEP 1: LOGIN")
        print("="*80)
        
        login_page = LoginPage(driver)
        login_page.login(identifier="BATBAT311A", password="17k*o@yReCUA")
        time.sleep(3)
        
        # Check login page attributes (if still on login)
        if "/login" in driver.current_url or driver.current_url.rstrip("/") == BASE_URL.rstrip("/"):
            login_testids = get_all_data_testids(driver)
            login_expected = [
                "student_login__form",
                "student_login__identifier_input",
                "student_login__password_input",
                "student_login__remember_checkbox",
                "student_login__error_banner",
                "student_login__submit_button"
            ]
            
            found = [tid for tid in login_expected if tid in login_testids]
            print(f"📊 Login Page: {len(found)}/{len(login_expected)} found")
            results["login"] = {"found": found, "missing": [tid for tid in login_expected if tid not in found]}
        else:
            print("✅ Login successful - redirected to dashboard")
            results["login"] = {"status": "success"}
        
        # ============================================================
        # STEP 2: PASSWORD RESET (if needed)
        # ============================================================
        print("\n" + "="*80)
        print("STEP 2: PASSWORD RESET CHECK")
        print("="*80)
        
        reset_page = MandatoryResetPage(driver)
        if reset_page.is_modal_present():
            print("🔄 Password reset modal present - resetting...")
            reset_page.reset_password("17k*o@yReCUA", TEST_NEW_PASSWORD, TEST_NEW_PASSWORD, "BATBAT311A")
            time.sleep(3)
            results["password_reset"] = {"status": "completed"}
        else:
            print("✅ No password reset required")
            results["password_reset"] = {"status": "not_required"}
        
        # ============================================================
        # STEP 3: NAVIGATE TO PROFILE EDITOR
        # ============================================================
        print("\n" + "="*80)
        print("STEP 3: NAVIGATING TO PROFILE EDITOR")
        print("="*80)
        
        # Handle profile incomplete modal
        profile_incomplete = ProfileIncompletePage(driver)
        if profile_incomplete.is_modal_present():
            print("⚠️  Profile incomplete modal present - clicking Complete Profile...")
            profile_incomplete.click_complete()
            time.sleep(3)
        else:
            profile_editor = ProfileEditorPage(driver)
            profile_editor.navigate()
            time.sleep(3)
        
        # Wait for profile editor to fully load
        profile_editor = ProfileEditorPage(driver)
        profile_editor.wait_for_page_load()
        time.sleep(2)
        
        # ============================================================
        # STEP 4: CHECK PAGE-LEVEL ATTRIBUTES
        # ============================================================
        print("\n" + "="*80)
        print("STEP 4: PAGE-LEVEL ATTRIBUTES")
        print("="*80)
        
        all_testids = get_all_data_testids(driver)
        page_level_expected = [
            "profile_editor__page",
            "profile_editor__progress_value",
            "profile_editor__missing_fields_toggle",
            "profile_editor__prev_button",
            "profile_editor__next_button",
            "profile_editor__cancel_button",
            "profile_editor__save_button"
        ]
        
        page_level_found = []
        for attr in page_level_expected:
            if attr in all_testids:
                print(f"✅ {attr}")
                page_level_found.append(attr)
            else:
                print(f"❌ MISSING: {attr}")
        
        print(f"\n📊 Page-Level: {len(page_level_found)}/{len(page_level_expected)} found")
        
        # ============================================================
        # STEP 5: CHECK TAB NAVIGATION
        # ============================================================
        print("\n" + "="*80)
        print("STEP 5: TAB NAVIGATION")
        print("="*80)
        
        tab_expected = [
            "profile_editor__tab_personal_information",
            "profile_editor__tab_contact_information",
            "profile_editor__tab_parent_guardian",
            "profile_editor__tab_education_details",
            "profile_editor__tab_focus_areas",
            "profile_editor__tab_self_assessment",
            "profile_editor__tab_hobbies_clubs",
            "profile_editor__tab_achievements",
            "profile_editor__tab_expectations",
            "profile_editor__tabs_scroll_left_button",
            "profile_editor__tabs_scroll_right_button"
        ]
        
        tab_found = []
        for attr in tab_expected:
            if attr in all_testids:
                print(f"✅ {attr}")
                tab_found.append(attr)
            else:
                print(f"❌ MISSING: {attr}")
        
        print(f"\n📊 Tab Navigation: {len(tab_found)}/{len(tab_expected)} found")
        
        # ============================================================
        # STEP 6: SYSTEMATICALLY CHECK EACH TAB
        # ============================================================
        
        # Tab 0: Personal Information
        tab0_result = navigate_to_tab_and_check(driver, 0, "personal_information", [
            "profile_editor__first_name_input",
            "profile_editor__last_name_input",
            "profile_editor__gender_select",
            "profile_editor__dob_input",
            "profile_editor__roll_number_input",
            "profile_editor__nationality_input",
            "profile_editor__language_input",
            "profile_editor__student_id_input",
            "profile_editor__student_cpid_input",
            "profile_editor__specially_abled_checkbox",
            "profile_editor__specially_abled_details_textarea"
        ])
        results["profile_editor"]["tabs"]["personal_information"] = tab0_result
        
        # Tab 1: Contact Information
        tab1_result = navigate_to_tab_and_check(driver, 1, "contact_information", [
            "profile_editor__email_input",
            "profile_editor__phone_input",
            "profile_editor__address_input",
            "profile_editor__city_input",
            "profile_editor__state_input",
            "profile_editor__zip_code_input",
            "profile_editor__native_state_input"
        ])
        results["profile_editor"]["tabs"]["contact_information"] = tab1_result
        
        # Tab 2: Parent/Guardian
        tab2_result = navigate_to_tab_and_check(driver, 2, "parent_guardian", [
            "profile_editor__father_full_name_input",
            "profile_editor__father_age_range_select",
            "profile_editor__father_occupation_input",
            "profile_editor__father_email_input",
            "profile_editor__mother_full_name_input",
            "profile_editor__mother_age_range_select",
            "profile_editor__mother_occupation_input",
            "profile_editor__mother_email_input",
            "profile_editor__guardian_different_checkbox",
            "profile_editor__guardian_full_name_input",
            "profile_editor__guardian_relationship_input",
            "profile_editor__guardian_phone_input",
            "profile_editor__guardian_email_input",
            "profile_editor__guardian_address_input"
        ])
        results["profile_editor"]["tabs"]["parent_guardian"] = tab2_result
        
        # Tab 3: Education Details
        tab3_result = navigate_to_tab_and_check(driver, 3, "education_details", [
            "profile_editor__full_name_input",
            "profile_editor__current_grade_input",
            "profile_editor__section_input",
            "profile_editor__board_stream_select"
        ])
        results["profile_editor"]["tabs"]["education_details"] = tab3_result
        
        # Tab 4: Focus Areas (with dynamic checkboxes)
        print("\n" + "="*80)
        print("TAB 5: FOCUS AREAS")
        print("="*80)
        profile_editor.navigate_to_tab(4)
        time.sleep(2)
        
        # Scroll to load all checkboxes
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(1)
        driver.execute_script("window.scrollTo(0, 0);")
        time.sleep(1)
        
        # Check dynamic checkboxes
        print("\n🔍 Checking Short-term Focus Areas...")
        short_term = check_dynamic_checkboxes(driver, "profile_editor__short_term_focus__", expected_count=11)
        
        print("\n🔍 Checking Long-term Focus Areas...")
        long_term = check_dynamic_checkboxes(driver, "profile_editor__long_term_focus__", expected_count=11)
        
        # Check "Others" text inputs
        others_expected = [
            "profile_editor__short_term_focus_others_text",
            "profile_editor__long_term_focus_others_text"
        ]
        all_testids_tab4 = get_all_data_testids(driver)
        for attr in others_expected:
            if attr in all_testids_tab4:
                print(f"✅ {attr}")
            else:
                print(f"❌ MISSING: {attr}")
        
        results["profile_editor"]["tabs"]["focus_areas"] = {
            "short_term_focus": short_term,
            "long_term_focus": long_term,
            "others_text": [tid for tid in others_expected if tid in all_testids_tab4]
        }
        
        # Tab 5: Self-Assessment (with dynamic checkboxes)
        print("\n" + "="*80)
        print("TAB 6: SELF-ASSESSMENT")
        print("="*80)
        profile_editor.navigate_to_tab(5)
        time.sleep(2)
        
        # Scroll to load all checkboxes
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(1)
        driver.execute_script("window.scrollTo(0, 0);")
        time.sleep(1)
        
        print("\n🔍 Checking Strengths...")
        strengths = check_dynamic_checkboxes(driver, "profile_editor__strength__", expected_count=19)
        
        print("\n🔍 Checking Areas of Improvement...")
        improvements = check_dynamic_checkboxes(driver, "profile_editor__improvement__", expected_count=19)
        
        # Check "Others" text inputs
        others_expected = [
            "profile_editor__strength_others_text",
            "profile_editor__improvement_others_text"
        ]
        all_testids_tab5 = get_all_data_testids(driver)
        for attr in others_expected:
            if attr in all_testids_tab5:
                print(f"✅ {attr}")
            else:
                print(f"❌ MISSING: {attr}")
        
        results["profile_editor"]["tabs"]["self_assessment"] = {
            "strengths": strengths,
            "improvements": improvements,
            "others_text": [tid for tid in others_expected if tid in all_testids_tab5]
        }
        
        # Tab 6: Hobbies & Clubs (with dynamic checkboxes)
        print("\n" + "="*80)
        print("TAB 7: HOBBIES & CLUBS")
        print("="*80)
        profile_editor.navigate_to_tab(6)
        time.sleep(2)
        
        # Scroll to load all checkboxes
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(1)
        driver.execute_script("window.scrollTo(0, 0);")
        time.sleep(1)
        
        print("\n🔍 Checking Hobbies...")
        hobbies = check_dynamic_checkboxes(driver, "profile_editor__hobby__", expected_count=12)
        
        print("\n🔍 Checking Clubs...")
        clubs = check_dynamic_checkboxes(driver, "profile_editor__club_", expected_count=12)  # Single underscore
        
        # Check "Others" text inputs
        others_expected = [
            "profile_editor__hobby_other_text",
            "profile_editor__club_other_text"
        ]
        all_testids_tab6 = get_all_data_testids(driver)
        for attr in others_expected:
            if attr in all_testids_tab6:
                print(f"✅ {attr}")
            else:
                print(f"❌ MISSING: {attr}")
        
        results["profile_editor"]["tabs"]["hobbies_clubs"] = {
            "hobbies": hobbies,
            "clubs": clubs,
            "others_text": [tid for tid in others_expected if tid in all_testids_tab6]
        }
        
        # Tab 7: Achievements
        tab7_result = navigate_to_tab_and_check(driver, 7, "achievements", [
            "profile_editor__achievement_academics_textarea",
            "profile_editor__achievement_sports_textarea",
            "profile_editor__achievement_cultural_textarea",
            "profile_editor__achievement_trained_textarea",
            "profile_editor__achievement_others_textarea"
        ])
        results["profile_editor"]["tabs"]["achievements"] = tab7_result
        
        # Tab 8: Expectations (with dynamic checkboxes)
        print("\n" + "="*80)
        print("TAB 9: EXPECTATIONS")
        print("="*80)
        profile_editor.navigate_to_tab(8)
        time.sleep(2)
        
        # Scroll to load all checkboxes
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(1)
        driver.execute_script("window.scrollTo(0, 0);")
        time.sleep(1)
        
        print("\n🔍 Checking Expectations...")
        expectations = check_dynamic_checkboxes(driver, "profile_editor__expectation__", expected_count=10)
        
        # Check "Others" text input
        others_expected = ["profile_editor__expectation_others_text"]
        all_testids_tab8 = get_all_data_testids(driver)
        for attr in others_expected:
            if attr in all_testids_tab8:
                print(f"✅ {attr}")
            else:
                print(f"❌ MISSING: {attr}")
        
        results["profile_editor"]["tabs"]["expectations"] = {
            "expectations": expectations,
            "others_text": [tid for tid in others_expected if tid in all_testids_tab8]
        }
        
        # ============================================================
        # FINAL SUMMARY
        # ============================================================
        print("\n" + "="*80)
        print("FINAL VERIFICATION SUMMARY")
        print("="*80)
        
        # Count all found attributes
        total_found = 0
        total_expected = 0
        
        # Page-level
        total_found += len(page_level_found)
        total_expected += len(page_level_expected)
        
        # Tab navigation
        total_found += len(tab_found)
        total_expected += len(tab_expected)
        
        # Tab-specific attributes
        for tab_name, tab_result in results["profile_editor"]["tabs"].items():
            if "found" in tab_result:
                total_found += len(tab_result["found"])
                total_expected += len(tab_result.get("missing", [])) + len(tab_result["found"])
            if "short_term_focus" in tab_result:
                total_found += len(tab_result["short_term_focus"])
            if "long_term_focus" in tab_result:
                total_found += len(tab_result["long_term_focus"])
            if "strengths" in tab_result:
                total_found += len(tab_result["strengths"])
            if "improvements" in tab_result:
                total_found += len(tab_result["improvements"])
            if "hobbies" in tab_result:
                total_found += len(tab_result["hobbies"])
            if "clubs" in tab_result:
                total_found += len(tab_result["clubs"])
            if "expectations" in tab_result:
                total_found += len(tab_result["expectations"])
        
        print(f"\n📊 TOTAL ATTRIBUTES FOUND: {total_found}")
        print(f"📊 TOTAL ATTRIBUTES EXPECTED: ~250+")
        print(f"📊 COVERAGE: {(total_found/250)*100:.1f}%")
        
        # Save results
        results["profile_editor"]["summary"] = {
            "total_found": total_found,
            "total_expected": total_expected,
            "page_level_found": len(page_level_found),
            "tab_navigation_found": len(tab_found)
        }
        
        results_file = project_root / "analysis" / "comprehensive_dom_verification_results.json"
        with open(results_file, 'w') as f:
            json.dump(results, f, indent=2, default=str)
        
        print(f"\n📄 Detailed results saved to: {results_file}")
        print("\n⏸️  Browser will remain open for 120 seconds for manual inspection...")
        print("   Press Ctrl+C to close early\n")
        time.sleep(120)
        
    except KeyboardInterrupt:
        print("\n\n⚠️  Verification interrupted by user")
    except Exception as e:
        print(f"\n\n❌ Error during verification: {e}")
        import traceback
        traceback.print_exc()
    finally:
        if driver:
            driver.quit()
            print("\n✅ Browser closed")


if __name__ == "__main__":
    main()






