"""Cal.com initial setup scenario.

Automates the first-time setup for a fresh Cal.com installation.
This scenario:
1. Navigates to the Cal.com setup page
2. Creates the admin account
3. Completes onboarding steps
"""

import secrets
import string
from typing import Any

from playwright.async_api import Page

from app.playwright_scenarios import register_scenario
from app.playwright_scenarios.base import BaseScenario, ScenarioOptions, ScenarioResult


def generate_secure_password(length: int = 24) -> str:
    """Generate a cryptographically secure password.

    Args:
        length: Password length (default: 24)

    Returns:
        A secure random password with mixed characters
    """
    alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
    password = [
        secrets.choice(string.ascii_lowercase),
        secrets.choice(string.ascii_uppercase),
        secrets.choice(string.digits),
        secrets.choice("!@#$%^&*"),
    ]
    password.extend(secrets.choice(alphabet) for _ in range(length - 4))
    password_list = list(password)
    secrets.SystemRandom().shuffle(password_list)
    return "".join(password_list)


@register_scenario
class CalcomInitialSetup(BaseScenario):
    """Automate Cal.com first-time admin account setup.

    This scenario handles the initial account creation when
    Cal.com is freshly installed. It navigates to the signup page,
    fills in account details, and completes the onboarding wizard.

    Required inputs:
        base_url: The Cal.com instance URL (e.g., https://cal.example.com)
        admin_email: Email address for the admin account

    Optional inputs:
        admin_password: Password for admin account (auto-generated if not provided)
        admin_username: Username for the admin account (default: "admin")
        admin_name: Display name for the admin account (default: "Admin")

    Result data:
        setup_completed: Whether initial setup was completed
        admin_email: The configured admin email address
        admin_password: The password (generated or provided) - STORE SECURELY
        already_configured: True if Cal.com was already set up
    """

    @property
    def name(self) -> str:
        return "calcom_initial_setup"

    @property
    def required_inputs(self) -> list[str]:
        return ["base_url", "admin_email"]

    @property
    def optional_inputs(self) -> list[str]:
        return ["admin_password", "admin_username", "admin_name"]

    @property
    def description(self) -> str:
        return "Automate Cal.com first-time admin account setup"

    async def execute(
        self,
        page: Page,
        inputs: dict[str, Any],
        options: ScenarioOptions,
    ) -> ScenarioResult:
        """Execute the Cal.com initial setup.

        Args:
            page: Playwright Page object
            inputs: Scenario inputs (base_url, admin_email)
            options: Scenario options

        Returns:
            ScenarioResult with setup status and credentials
        """
        base_url = inputs["base_url"].rstrip("/")
        admin_email = inputs["admin_email"]
        admin_password = inputs.get("admin_password") or generate_secure_password()
        admin_username = inputs.get("admin_username", "admin")
        admin_name = inputs.get("admin_name", "Admin")

        screenshots = []
        result_data = {
            "setup_completed": False,
            "admin_email": admin_email,
            "admin_password": admin_password,
            "already_configured": False,
        }

        try:
            # Navigate to Cal.com
            await page.goto(base_url, wait_until="networkidle")

            current_url = page.url

            # Check if already configured (redirects to login)
            if "/auth/login" in current_url:
                result_data["already_configured"] = True
                result_data["setup_completed"] = True
                return ScenarioResult(
                    success=True,
                    data=result_data,
                    screenshots=screenshots,
                    error=None,
                )

            # Navigate to signup page
            signup_url = f"{base_url}/signup"
            await page.goto(signup_url, wait_until="networkidle")

            # If redirected to login, the instance may already be set up
            if "/auth/login" in page.url and "/signup" not in page.url:
                result_data["already_configured"] = True
                result_data["setup_completed"] = True
                return ScenarioResult(
                    success=True,
                    data=result_data,
                    screenshots=screenshots,
                    error=None,
                )

            # Fill in the signup form
            # Username
            username_input = page.locator(
                'input[name="username"], '
                'input[id="username"], '
                'input[placeholder*="username" i]'
            ).first
            if await username_input.count() > 0:
                await username_input.wait_for(state="visible", timeout=10000)
                await username_input.fill(admin_username)

            # Full name
            name_input = page.locator(
                'input[name="name"], '
                'input[name="full_name"], '
                'input[placeholder*="name" i]'
            ).first
            if await name_input.count() > 0:
                await name_input.fill(admin_name)

            # Email
            email_input = page.locator(
                'input[name="email"], '
                'input[type="email"], '
                'input[placeholder*="email" i]'
            ).first
            await email_input.wait_for(state="visible", timeout=10000)
            await email_input.fill(admin_email)

            # Password
            password_input = page.locator(
                'input[name="password"], '
                'input[type="password"]'
            ).first
            await password_input.fill(admin_password)

            # Take screenshot before submitting
            if options.screenshot_on_success and options.artifacts_dir:
                pre_submit_path = options.artifacts_dir / "calcom_pre_submit.png"
                await page.screenshot(path=str(pre_submit_path))
                screenshots.append(str(pre_submit_path))

            # Click Sign up / Create Account button
            submit_button = page.locator(
                'button:has-text("Sign up"), '
                'button:has-text("Create"), '
                'button:has-text("Register"), '
                'button[type="submit"]'
            ).first
            await submit_button.click()

            # Wait for onboarding or dashboard
            await page.wait_for_timeout(3000)

            # Cal.com has an onboarding wizard after signup
            # Skip through onboarding steps
            for _ in range(5):
                skip_button = page.locator(
                    'button:has-text("Skip"), '
                    'a:has-text("Skip"), '
                    'button:has-text("Next"), '
                    'button:has-text("Continue"), '
                    'button:has-text("Finish")'
                )
                if await skip_button.count() > 0:
                    await skip_button.first.click()
                    await page.wait_for_timeout(2000)
                else:
                    break

            # Check if we reached the dashboard or event types page
            await page.wait_for_timeout(2000)
            current_url = page.url

            if any(kw in current_url for kw in ["/event-types", "/dashboard", "/bookings", "/settings"]):
                result_data["setup_completed"] = True
            else:
                # Check for dashboard indicators
                dashboard_el = page.locator(
                    '[class*="event-type"], '
                    '[class*="dashboard"], '
                    ':has-text("Event Types")'
                )
                if await dashboard_el.count() > 0:
                    result_data["setup_completed"] = True

            # Take final screenshot
            if options.screenshot_on_success and options.artifacts_dir:
                final_path = options.artifacts_dir / "calcom_setup_complete.png"
                await page.screenshot(path=str(final_path))
                screenshots.append(str(final_path))

            return ScenarioResult(
                success=result_data["setup_completed"],
                data=result_data,
                screenshots=screenshots,
                error=None if result_data["setup_completed"] else "Setup may not have completed",
            )

        except Exception as e:
            if options.screenshot_on_failure and options.artifacts_dir:
                error_path = options.artifacts_dir / "calcom_setup_error.png"
                await page.screenshot(path=str(error_path))
                screenshots.append(str(error_path))

            return ScenarioResult(
                success=False,
                data=result_data,
                screenshots=screenshots,
                error=f"Cal.com setup failed: {str(e)}",
            )
