"""Chatwoot initial setup scenario.

Automates the first-time setup for a fresh Chatwoot installation.
This scenario:
1. Navigates to the Chatwoot installation wizard
2. Fills in admin account details (name, company, email, password)
3. Unchecks the newsletter subscription
4. Completes the setup
"""

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 ChatwootInitialSetup(BaseScenario):
    """Automate Chatwoot first-time setup wizard.

    This scenario handles the initial super admin account creation when
    Chatwoot is freshly installed. It fills in the account details,
    unchecks the newsletter subscription, and completes the setup.

    Required inputs:
        base_url: The Chatwoot instance URL (e.g., https://chatwoot.example.com)
        admin_name: Full name for the admin account
        company_name: Company/organization name
        admin_email: Email address for the admin account

    Optional inputs:
        admin_password: Password for admin account (auto-generated if not provided)

    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 Chatwoot was already set up
    """

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

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

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

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

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

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

        Returns:
            ScenarioResult with setup status and credentials
        """
        base_url = inputs["base_url"].rstrip("/")
        admin_name = inputs["admin_name"]
        company_name = inputs["company_name"]
        admin_email = inputs["admin_email"]

        # Generate password if not provided
        admin_password = inputs.get("admin_password") or generate_secure_password()

        screenshots = []
        result_data = {
            "setup_completed": False,
            "admin_name": admin_name,
            "company_name": company_name,
            "admin_email": admin_email,
            "admin_password": admin_password,  # Return for secure storage
            "already_configured": False,
        }

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

            current_url = page.url

            # Check if we're on the setup page or already configured
            # Chatwoot setup page typically at /app/login or /super_admin/setup
            if "/app/login" in current_url and "installation" not in current_url:
                # Already configured - login page without setup
                result_data["already_configured"] = True
                result_data["setup_completed"] = True
                return ScenarioResult(
                    success=True,
                    data=result_data,
                    screenshots=screenshots,
                    error=None,
                )

            # Look for the super admin setup form
            # Try common setup URL patterns
            setup_urls = [
                f"{base_url}/super_admin/setup",
                f"{base_url}/installation/onboarding",
                base_url,  # Sometimes the root redirects to setup
            ]

            setup_found = False
            for setup_url in setup_urls:
                await page.goto(setup_url, wait_until="networkidle")

                # Check for setup form elements
                name_input = page.locator('input[name="name"], input[placeholder*="name" i]')
                if await name_input.count() > 0:
                    setup_found = True
                    break

            if not setup_found:
                # Check if already configured
                if "/app" in page.url or "/dashboard" in page.url:
                    result_data["already_configured"] = True
                    result_data["setup_completed"] = True
                    return ScenarioResult(
                        success=True,
                        data=result_data,
                        screenshots=screenshots,
                        error=None,
                    )

                return ScenarioResult(
                    success=False,
                    data=result_data,
                    screenshots=screenshots,
                    error="Could not find Chatwoot setup page",
                )

            # Fill in the setup form
            # Name field
            name_input = page.locator(
                'input[name="name"], '
                'input[placeholder*="name" i], '
                'input[id*="name" i]'
            ).first
            await name_input.wait_for(state="visible", timeout=10000)
            await name_input.fill(admin_name)

            # Company name field
            company_input = page.locator(
                'input[name="company_name"], '
                'input[name="account_name"], '
                'input[placeholder*="company" i], '
                'input[placeholder*="account" i]'
            ).first
            if await company_input.count() > 0:
                await company_input.fill(company_name)

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

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

            # Uncheck newsletter subscription if present
            newsletter_checkbox = page.locator(
                'input[type="checkbox"][name*="subscribe" i], '
                'input[type="checkbox"][name*="newsletter" i], '
                'input[type="checkbox"][id*="subscribe" i], '
                'label:has-text("Subscribe") input[type="checkbox"], '
                'label:has-text("newsletter") input[type="checkbox"]'
            )
            if await newsletter_checkbox.count() > 0:
                checkbox = newsletter_checkbox.first
                is_checked = await checkbox.is_checked()
                if is_checked:
                    await checkbox.uncheck()

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

            # Click Finish Setup / Submit button
            submit_button = page.locator(
                'button:has-text("Finish"), '
                'button:has-text("Setup"), '
                'button:has-text("Create"), '
                'button[type="submit"], '
                'input[type="submit"]'
            ).first
            await submit_button.click()

            # Wait for setup to complete - should redirect to login or dashboard
            try:
                await page.wait_for_url(
                    lambda url: "/app" in url or "/dashboard" in url or "/login" in url,
                    timeout=60000,
                )
                result_data["setup_completed"] = True
            except Exception:
                # Check if there's an error message
                error_el = page.locator('.error, .alert-danger, [class*="error"]')
                if await error_el.count() > 0:
                    error_text = await error_el.first.text_content()
                    return ScenarioResult(
                        success=False,
                        data=result_data,
                        screenshots=screenshots,
                        error=f"Setup failed: {error_text}",
                    )

                # Check if we're on a success page
                success_indicators = page.locator(
                    ':has-text("success"), '
                    ':has-text("Welcome"), '
                    ':has-text("Dashboard")'
                )
                if await success_indicators.count() > 0:
                    result_data["setup_completed"] = True

            # Take final screenshot
            if options.screenshot_on_success and options.artifacts_dir:
                final_path = options.artifacts_dir / "chatwoot_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:
            # Take error screenshot
            if options.screenshot_on_failure and options.artifacts_dir:
                error_path = options.artifacts_dir / "chatwoot_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"Chatwoot setup failed: {str(e)}",
            )
