import XCTest

/// Critical path tests for authentication flows.
/// Tests login, logout, registration entry, forgot password entry.
final class AuthCriticalPathTests: BaseUITestCase {
    override var relaunchBetweenTests: Bool { true }

    // MARK: - Helpers

    private func navigateToLogin() {
        let loginField = app.textFields[AccessibilityIdentifiers.Authentication.usernameField]
        if loginField.waitForExistence(timeout: defaultTimeout) { return }

        // On onboarding — tap login button
        let onboardingLogin = app.buttons[AccessibilityIdentifiers.Onboarding.loginButton]
        if onboardingLogin.waitForExistence(timeout: navigationTimeout) {
            onboardingLogin.tap()
        }

        loginField.waitForExistenceOrFail(timeout: navigationTimeout, message: "Login screen should appear")
    }

    private func loginAsTestUser() {
        navigateToLogin()

        let login = LoginScreenObject(app: app)
        login.enterUsername("testuser")
        login.enterPassword("TestPass123!")
        app.buttons[AccessibilityIdentifiers.Authentication.loginButton].tap()

        // Wait for main app or verification gate
        let tabBar = app.tabBars.firstMatch
        let verification = VerificationScreen(app: app)

        let deadline = Date().addingTimeInterval(loginTimeout)
        while Date() < deadline {
            if tabBar.exists { return }
            if verification.codeField.exists {
                verification.enterCode(TestAccountAPIClient.debugVerificationCode)
                verification.submitCode()
                _ = tabBar.waitForExistence(timeout: loginTimeout)
                return
            }
            RunLoop.current.run(until: Date().addingTimeInterval(0.5))
        }

        XCTAssertTrue(tabBar.exists, "Should reach main app after login")
    }

    // MARK: - Login

    func testLoginWithValidCredentials() {
        loginAsTestUser()
        XCTAssertTrue(app.tabBars.firstMatch.exists, "Tab bar should be visible after login")
    }

    func testLoginWithInvalidCredentials() {
        navigateToLogin()

        let login = LoginScreenObject(app: app)
        login.enterUsername("invaliduser")
        login.enterPassword("wrongpassword")
        app.buttons[AccessibilityIdentifiers.Authentication.loginButton].tap()

        // Should stay on login screen
        let loginField = app.textFields[AccessibilityIdentifiers.Authentication.usernameField]
        XCTAssertTrue(loginField.waitForExistence(timeout: navigationTimeout), "Should remain on login screen after invalid credentials")
        XCTAssertFalse(app.tabBars.firstMatch.exists, "Tab bar should not appear after failed login")
    }

    // MARK: - Logout

    func testLogoutFlow() {
        loginAsTestUser()
        UITestHelpers.logout(app: app)

        let loginField = app.textFields[AccessibilityIdentifiers.Authentication.usernameField]
        let onboardingLogin = app.buttons[AccessibilityIdentifiers.Onboarding.loginButton]
        let loggedOut = loginField.waitForExistence(timeout: loginTimeout)
            || onboardingLogin.waitForExistence(timeout: navigationTimeout)
        XCTAssertTrue(loggedOut, "Should return to login or onboarding after logout")
    }

    // MARK: - Registration Entry

    func testSignUpButtonNavigatesToRegistration() {
        navigateToLogin()
        app.buttons[AccessibilityIdentifiers.Authentication.signUpButton].tap()

        let registerUsername = app.textFields[AccessibilityIdentifiers.Authentication.registerUsernameField]
        XCTAssertTrue(registerUsername.waitForExistence(timeout: navigationTimeout), "Registration form should appear")
    }

    // MARK: - Forgot Password

    func testForgotPasswordButtonExists() {
        navigateToLogin()
        let forgotButton = app.buttons[AccessibilityIdentifiers.Authentication.forgotPasswordButton]
        XCTAssertTrue(forgotButton.waitForExistence(timeout: defaultTimeout), "Forgot password button should exist")
    }
}
