from playwright.sync_api import sync_playwright, expect
from playwright.sync_api._context_manager import PlaywrightContextManager
from playwright._impl._browser import Browser
from playwright._impl._page import Page
from utils.trace_cleaner import trace_cleaner


# Utility to generate an email
def generate_email():
    timestamp = '500005'
    return f"freelanceapptest+{timestamp}@gmail.com"


# Function to log in the user and complete onboarding steps
def login_user(p: PlaywrightContextManager, first_name="Milan", last_name="T") -> tuple[Browser, Page]:
    # Launch Chromium and open a new page
    browser = p.chromium.launch(
        channel="chrome",
        headless=False,
        args=[
            "--ignore-certificate-errors",
            "--disable-web-security",
            "--disable-features=IsolateOrigins,site-per-process"
        ],
        proxy={"server": "http://localhost:8080"},
        slow_mo=200
    )

    context = browser.new_context(ignore_https_errors=True, viewport={"width": 1200, "height": 600})
    page = context.new_page()
    user_email = generate_email()

    # Step 1: Open the Expensify URL
    page.goto('https://dev.new.expensify.com:8082/') 

    # Step 2: Enter a generated email and click continue
    page.locator('input[type="email"]').fill(user_email)
    page.locator('button[tabindex="0"]').click()
    page.wait_for_timeout(1000) 

    # Step 3: Click the join button if available, otherwise skip
    try:
        page.locator('button[tabindex="0"]').click()
        page.wait_for_timeout(1000)
    except Exception:
        pass

    # Step 4: Ensure that the user reaches the dashboard by checking for visible text
    expect(page.locator("text=What do you want to do today?")).to_be_visible()
        
    # Step 5: Select 'Track and budget expenses' in the onboarding page and click Continue
    page.locator("text='Track and budget expenses'").click()
    page.wait_for_timeout(1000) 

    # Step 6: Enter first name, last name, and continue
    page.locator('input[name="fname"]').fill(first_name)
    page.locator('input[name="lname"]').fill(last_name)
    page.get_by_role("button", name="Continue").last.click()
    page.wait_for_timeout(1000) 

    return browser, page


def create_expense(page, currency, amount):
    """Helper function to create an expense with the given currency and amount."""
    page.get_by_label("Create").click()
    track_expense_button = page.get_by_text("Track expense").nth(0)
    if track_expense_button.is_visible():
        track_expense_button.click()
    else:
        page.get_by_text("Create expense").click()
    page.get_by_label("Manual").click()
    page.get_by_label("Select a currency").click()
    page.get_by_test_id("selection-list-text-input").fill(currency.lower())
    page.get_by_label(f"{currency.upper()} - {get_currency_symbol(currency)}").click()
    page.get_by_placeholder("0").fill(str(amount))
    page.locator("#numPadContainerView").get_by_role("button", name="Next").click()
    page.get_by_role("button", name="Track expense").click()
    page.wait_for_timeout(1000)


def get_currency_symbol(currency):
    """Returns the correct currency symbol for a given currency code."""
    currency_map = {
        "usd": "$",
        "cad": "C$",
        "gbp": "£",
        "jpy": "¥"
    }
    return currency_map.get(currency.lower(), "?")


def test_lhn_scrollable():
    with sync_playwright() as p:
        browser, page = login_user(p)
        context = page.context()
        context.tracing.start(screenshots=True, snapshots=True, sources=True)
        try:
            page.locator('span:has-text("Milan T (you)")').click()
            
            # Step 2: Create multiple tracked expenses
            create_expense(page, "usd", 10)
        
            # Step 3: Navigate to Search
            page.get_by_test_id("CustomBottomTabNavigator").get_by_label("Search").click()
        
            # Step 4: Apply filters and save searches
            # Each filter is applied differently based on its type
            page.get_by_role("button", name="Filters").click()
        
            # Filter by Currency (USD)
            page.get_by_text("Currency").click()
            page.get_by_test_id("selection-list-text-input").fill("usd")
            page.locator("[id=\"USD\\ -\\ \\$"]").click()
            page.get_by_role("button", name="Save").click()
            page.get_by_role("button", name="Save search").click()
            page.wait_for_timeout(1000)
           
            # Filter by Expense Type (Cash)
            page.get_by_role("button", name="Filters").click()
            page.get_by_role("link", name="Reset filters").click()
            page.get_by_text("Expense type").click()
            page.locator("#Cash").click()
            page.get_by_role("button", name="Save").click()
            page.get_by_role("button", name="Save search").click()
            page.wait_for_timeout(1000)
            
            # Filter by Total Amount (Between 10 and 1000)
            page.get_by_role("button", name="Filters").click()
            page.get_by_role("link", name="Reset filters").click()
            page.get_by_test_id("SearchAdvancedFiltersPage").get_by_text("Total").click()
            page.get_by_role("textbox", name="Greater than").fill("10")
            page.get_by_role("textbox", name="Less than").click()
            page.get_by_role("textbox", name="Less than").fill("1000")
            page.get_by_role("button", name="Save").click()
            page.get_by_role("button", name="Save search").click()
            page.wait_for_timeout(1000)

            # Filter by Currency (AED)       
            page.get_by_role("button", name="Filters").click()
            page.get_by_role("link", name="Reset filters").click()
            page.get_by_test_id("SearchAdvancedFiltersPage").get_by_text("Currency").click()
            page.locator("[id=\"AED\\ -\\ Dhs\"]").get_by_label("AED - Dhs").click()
            page.get_by_role("button", name="Save").click()
            page.get_by_role("button", name="Save search").click()
            page.wait_for_timeout(1000)
            
            # Filter by Currency (JPY)
            page.get_by_role("button", name="Filters").click()
            page.get_by_role("link", name="Reset filters").click()
            page.get_by_test_id("SearchAdvancedFiltersPage").get_by_text("Currency").click()
            page.get_by_test_id("selection-list-text-input").fill("j")
            page.locator("[id=\"JPY\\ -\\ ¥\"]").click()
            page.get_by_role("button", name="Save").click()
            page.get_by_role("button", name="Save search").click()
            page.wait_for_timeout(1000)
            
            # Filter by Currency (AOA)
            page.get_by_role("button", name="Filters").click()
            page.get_by_role("link", name="Reset filters").click()
            page.get_by_test_id("SearchAdvancedFiltersPage").get_by_text("Currency").click()
            page.locator("button").filter(has_text="AOA - Kz").click()
            page.get_by_role("button", name="Save").click()
            page.get_by_role("button", name="Save search").click()
            page.wait_for_timeout(1000)
            
            # Filter by Currency (AUD)
            page.get_by_role("button", name="Filters").click()
            page.get_by_test_id("SearchAdvancedFiltersPage").get_by_text("AOA").click()
            page.locator("button").filter(has_text="AUD - A$").click()
            page.locator("button").filter(has_text="AOA - Kz").get_by_label("AOA - Kz").click()
            page.get_by_role("button", name="Save").click()
            page.get_by_role("button", name="Save search").click()
            page.wait_for_timeout(1000)

            # Filter by Currency (ALL)
            page.get_by_role("button", name="Filters").click()
            page.get_by_role("link", name="Reset filters").click()
            page.get_by_test_id("SearchAdvancedFiltersPage").get_by_text("Currency").click()
            page.locator("[id=\"ALL\\ -\\ ALL\"]").click()
            page.get_by_role("button", name="Save").click()
            page.get_by_role("button", name="Save search").click()

            # Step 5: Click "Expenses" in the bottom tab
            expenses_tab = page.get_by_test_id("SearchPageBottomTab").get_by_text("Expenses")
            expenses_tab.click()
            page.wait_for_timeout(1000)  # Allow UI to stabilize

            page.set_viewport_size({"width": 1200, "height": 500})

            # Step 6: Scroll the LHN to the bottom 
            aud_saved_search = page.get_by_text("type:expense status:all currency:AUD")
            aud_saved_search.hover()
            page.mouse.wheel(0, 600)     
            page.wait_for_timeout(1000)
        
            # Step 7: Verify the "Expenses" tab is not visible after scrolling
            locator = page.get_by_test_id("SearchPageBottomTab").get_by_text("Expenses")
            expect(locator).to_be_visible()

            # Get bounding box of the "Expenses" element
            bounding_box = locator.bounding_box()
           
            # Get current scroll position
            scroll_y = page.evaluate("window.scrollY")

            # Assert that the Expenses tab is not within the viewport
            assert not bounding_box["y"] >= scroll_y, f"Expense tab should not be inside the viewport but is at {bounding_box['y']} while scrollY is {scroll_y}"
            
            page.wait_for_timeout(2000)
        finally:
            # Stop tracing and export trace file
            trace_path = "/app/expensify/user_tool/output_browser1.zip"
            context.tracing.stop(path=trace_path)
            trace_cleaner(trace_path)
            browser.close()


if __name__ == "__main__":
    test_lhn_scrollable()