#!/usr/bin/env python3
"""
DOM Locator Validation Script

Thoroughly validates all locators against the current DOM.
Checks if all data-testid attributes are present and correctly implemented.
"""
import sys
from pathlib import Path

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 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 utils.password_tracker import password_tracker
from config.config import TEST_USERNAME, TEST_PASSWORD, TEST_NEW_PASSWORD, BASE_URL
import time
import json


def get_all_data_testids_from_dom(driver):
    """Extract all data-testid attributes from the current DOM"""
    testids = {}
    
    # Get all elements with data-testid
    elements = driver.find_elements(By.CSS_SELECTOR, "[data-testid]")
    
    for element in elements:
        testid = element.get_attribute("data-testid")
        tag = element.tag_name
        element_type = element.get_attribute("type") or tag
        visible = element.is_displayed()
        
        if testid:
            testids[testid] = {
                "tag": tag,
                "type": element_type,
                "visible": visible,
                "text": element.text[:50] if element.text else "",
                "value": element.get_attribute("value")[:50] if element.get_attribute("value") else ""
            }
    
    return testids


def validate_profile_editor_locators(driver, profile_editor):
    """Validate all profile editor locators against DOM - Navigates through all tabs"""
    print("\n" + "="*80)
    print("DOM LOCATOR VALIDATION - PROFILE EDITOR")
    print("="*80 + "\n")
    
    # Navigate to profile editor
    profile_editor.navigate()
    profile_editor.wait_for_page_load()
    time.sleep(2)  # Wait for full render
    
    # Collect testids from ALL tabs (many attributes are tab-specific)
    print("📋 Extracting all data-testid attributes from ALL tabs...")
    print("   (Navigating through all 9 tabs to find tab-specific attributes)\n")
    
    dom_testids = {}
    tab_names = [
        "Personal Information", "Contact Information", "Parent/Guardian",
        "Education Details", "Focus Areas", "Self-Assessment",
        "Hobbies & Clubs", "Achievements", "Expectations"
    ]
    
    # Collect from each tab
    for tab_index, tab_name in enumerate(tab_names):
        try:
            print(f"   📝 Tab {tab_index + 1}/9: {tab_name}...")
            profile_editor.navigate_to_tab(tab_index)
            time.sleep(1)  # Wait for tab to load
            
            # Get testids from this tab
            tab_testids = get_all_data_testids_from_dom(driver)
            # Merge into main dict (overwrites duplicates, which is fine)
            dom_testids.update(tab_testids)
            print(f"      ✅ Found {len(tab_testids)} attributes (Total so far: {len(dom_testids)})")
        except Exception as e:
            print(f"      ⚠️  Error on tab {tab_index + 1}: {e}")
            continue
    
    print(f"\n✅ Total unique attributes found across all tabs: {len(dom_testids)}\n")
    
    # Define all expected locators
    expected_locators = {
        # Page-level
        "profile_editor__page": "PAGE",
        "profile_editor__progress_value": "PROGRESS_VALUE",
        "profile_editor__missing_fields_toggle": "MISSING_FIELDS_TOGGLE",
        
        # Navigation buttons
        "profile_editor__prev_button": "PREV_BUTTON",
        "profile_editor__next_button": "NEXT_BUTTON",
        "profile_editor__cancel_button": "CANCEL_BUTTON",
        "profile_editor__save_button": "SAVE_BUTTON",
        
        # Tabs
        "profile_editor__tab_personal_information": "TAB_PERSONAL_INFORMATION",
        "profile_editor__tab_contact_information": "TAB_CONTACT_INFORMATION",
        "profile_editor__tab_parent_guardian": "TAB_PARENT_GUARDIAN",
        "profile_editor__tab_education_details": "TAB_EDUCATION_DETAILS",
        "profile_editor__tab_focus_areas": "TAB_FOCUS_AREAS",
        "profile_editor__tab_self_assessment": "TAB_SELF_ASSESSMENT",
        "profile_editor__tab_hobbies_clubs": "TAB_HOBBIES_CLUBS",
        "profile_editor__tab_achievements": "TAB_ACHIEVEMENTS",
        "profile_editor__tab_expectations": "TAB_EXPECTATIONS",
        
        # Step 1: Personal Information
        "profile_editor__first_name_input": "FIRST_NAME_INPUT",
        "profile_editor__last_name_input": "LAST_NAME_INPUT",
        "profile_editor__gender_select": "GENDER_SELECT",
        "profile_editor__dob_input": "DOB_INPUT",
        "profile_editor__roll_number_input": "ROLL_NUMBER_INPUT",
        "profile_editor__nationality_input": "NATIONALITY_INPUT",
        "profile_editor__language_input": "LANGUAGE_INPUT",
        "profile_editor__student_id_input": "STUDENT_ID_INPUT",
        "profile_editor__student_cpid_input": "STUDENT_CPID_INPUT",
        "profile_editor__specially_abled_checkbox": "SPECIALLY_ABLED_CHECKBOX",
        
        # Step 2: Contact Information
        "profile_editor__email_input": "EMAIL_INPUT",
        "profile_editor__phone_input": "PHONE_INPUT",
        "profile_editor__address_input": "ADDRESS_INPUT",
        "profile_editor__city_input": "CITY_INPUT",
        "profile_editor__state_input": "STATE_INPUT",
        "profile_editor__zip_code_input": "ZIP_CODE_INPUT",
        "profile_editor__native_state_input": "NATIVE_STATE_INPUT",
        
        # Step 3: Parent/Guardian
        "profile_editor__father_full_name_input": "FATHER_FULL_NAME_INPUT",
        "profile_editor__father_age_range_select": "FATHER_AGE_RANGE_SELECT",
        "profile_editor__father_occupation_input": "FATHER_OCCUPATION_INPUT",
        "profile_editor__father_email_input": "FATHER_EMAIL_INPUT",
        "profile_editor__mother_full_name_input": "MOTHER_FULL_NAME_INPUT",
        "profile_editor__mother_age_range_select": "MOTHER_AGE_RANGE_SELECT",
        "profile_editor__mother_occupation_input": "MOTHER_OCCUPATION_INPUT",
        "profile_editor__mother_email_input": "MOTHER_EMAIL_INPUT",
        "profile_editor__guardian_different_checkbox": "GUARDIAN_DIFFERENT_CHECKBOX",
        "profile_editor__guardian_full_name_input": "GUARDIAN_FULL_NAME_INPUT",
        "profile_editor__guardian_age_range_select": "GUARDIAN_AGE_RANGE_SELECT",
        "profile_editor__guardian_occupation_input": "GUARDIAN_OCCUPATION_INPUT",
        "profile_editor__guardian_email_input": "GUARDIAN_EMAIL_INPUT",
        
        # Step 4: Education Details
        "profile_editor__full_name_input": "FULL_NAME_INPUT",
        "profile_editor__current_grade_input": "CURRENT_GRADE_INPUT",
        "profile_editor__section_input": "SECTION_INPUT",
        "profile_editor__board_stream_select": "BOARD_STREAM_SELECT",
        
        # Step 5-9: These are checked via patterns (checkboxes, textareas)
        # Focus Areas, Self-Assessment, Hobbies, Clubs, Expectations, Achievements
        # are validated via multi-select patterns below
    }
    
    # Check each expected locator
    print("🔍 Validating expected locators...\n")
    found = []
    missing = []
    found_but_not_expected = []
    
    for testid, constant_name in expected_locators.items():
        if testid in dom_testids:
            found.append({
                "testid": testid,
                "constant": constant_name,
                "info": dom_testids[testid]
            })
            print(f"✅ {testid} - {constant_name}")
        else:
            missing.append({
                "testid": testid,
                "constant": constant_name
            })
            print(f"❌ MISSING: {testid} - {constant_name}")
    
    # Check for profile_editor testids that we didn't expect
    print("\n🔍 Checking for unexpected profile_editor testids...\n")
    for testid in dom_testids:
        if testid.startswith("profile_editor__") and testid not in expected_locators:
            found_but_not_expected.append({
                "testid": testid,
                "info": dom_testids[testid]
            })
            print(f"⚠️  UNEXPECTED (but present): {testid}")
    
    # Summary
    print("\n" + "="*80)
    print("VALIDATION SUMMARY")
    print("="*80)
    print(f"✅ Found: {len(found)}/{len(expected_locators)}")
    print(f"❌ Missing: {len(missing)}")
    print(f"⚠️  Unexpected (but present): {len(found_but_not_expected)}")
    print("="*80 + "\n")
    
    # Check multi-select checkboxes (Focus Areas, Strengths, etc.)
    print("\n🔍 Checking Multi-Select Checkboxes...\n")
    multi_select_patterns = [
        "profile_editor__short_term_focus__",
        "profile_editor__long_term_focus__",
        "profile_editor__strength__",
        "profile_editor__improvement__",
        "profile_editor__hobby__",
        "profile_editor__club_",
        "profile_editor__expectation__"
    ]
    
    for pattern in multi_select_patterns:
        matching = [tid for tid in dom_testids if tid.startswith(pattern)]
        if matching:
            print(f"✅ Found {len(matching)} checkboxes matching '{pattern}*'")
            for tid in matching[:5]:  # Show first 5
                print(f"   - {tid}")
            if len(matching) > 5:
                print(f"   ... and {len(matching) - 5} more")
        else:
            print(f"❌ No checkboxes found matching '{pattern}*'")
    
    # Save results to file
    results = {
        "found": found,
        "missing": missing,
        "unexpected": found_but_not_expected,
        "all_dom_testids": list(dom_testids.keys()),
        "total_found": len(found),
        "total_expected": len(expected_locators),
        "total_missing": len(missing)
    }
    
    results_file = project_root / "analysis" / "dom_validation_results.json"
    results_file.parent.mkdir(exist_ok=True)
    with open(results_file, 'w') as f:
        json.dump(results, f, indent=2)
    
    print(f"\n📄 Results saved to: {results_file}")
    
    return results


def main():
    """Main validation function"""
    driver = None
    try:
        print("🚀 Starting DOM Locator Validation...")
        print(f"🌐 Environment: {BASE_URL}\n")
        
        # Initialize driver
        driver_manager = DriverManager()
        driver = driver_manager.get_driver(headless=False)
        
        # Step 1: Login
        print("[STEP 1] LOGIN")
        print("-" * 80)
        login_page = LoginPage(driver)
        login_page.login(identifier=TEST_USERNAME, password=None)
        print(f"✅ Login successful - URL: {driver.current_url}\n")
        
        # Step 2: Handle Password Reset
        print("[STEP 2] PASSWORD RESET CHECK")
        print("-" * 80)
        reset_page = MandatoryResetPage(driver)
        if reset_page.is_modal_present():
            current_password = password_tracker.get_password(TEST_USERNAME, TEST_PASSWORD)
            reset_page.reset_password(
                current_password=current_password,
                new_password=TEST_NEW_PASSWORD,
                confirm_password=TEST_NEW_PASSWORD,
                student_cpid=TEST_USERNAME
            )
            print("✅ Password reset completed\n")
        else:
            print("✅ No password reset required\n")
        
        # Step 3: Navigate to Profile Editor
        print("[STEP 3] NAVIGATE TO PROFILE EDITOR")
        print("-" * 80)
        profile_incomplete = ProfileIncompletePage(driver)
        if profile_incomplete.is_modal_present():
            profile_incomplete.click_complete()
            time.sleep(2)
            print("✅ Clicked Complete Profile button\n")
        else:
            # Navigate directly to profile editor
            profile_editor = ProfileEditorPage(driver)
            profile_editor.navigate()
            time.sleep(2)
            print("✅ Navigated directly to profile editor\n")
        
        # Step 4: Validate Locators
        profile_editor = ProfileEditorPage(driver)
        results = validate_profile_editor_locators(driver, profile_editor)
        
        # Keep browser open for inspection
        print("\n⏸️  Browser will remain open for 60 seconds for manual inspection...")
        print("   Press Ctrl+C to close early\n")
        time.sleep(60)
        
    except KeyboardInterrupt:
        print("\n\n⚠️  Validation interrupted by user")
    except Exception as e:
        print(f"\n\n❌ Error during validation: {e}")
        import traceback
        traceback.print_exc()
    finally:
        if driver:
            driver.quit()
            print("\n✅ Browser closed")


if __name__ == "__main__":
    main()

