import argparse
import asyncio
import json
import logging
import sys
from pathlib import Path

from dotenv import load_dotenv
from playwright.async_api import async_playwright

from cli_utils import (
    find_workspace_root,
    resolve_test_by_partial_id,
    resolve_environment_by_name,
    resolve_fixture_from_id,
    list_tests_in_folder,
    list_available_environments,
)
from src.run import run_test_from_file
from src.config import Config
import os

logger = logging.getLogger(__name__)


async def run_single_test(
    test_path: Path,
    environment_path: Path,
    workspace_folder: Path,
) -> dict:
    """Execute a single test"""
    # Load test to get fixture ID and generate cache path
    with open(test_path, "r", encoding="utf-8") as f:
        test_data = json.load(f)
        fixture_id = test_data.get("fixtureId", "")
        test_id = test_data.get("id", "")
        test_name = test_data.get("name", "Unnamed Test")

    # Load environment to get ID for cache path
    with open(environment_path, "r", encoding="utf-8") as f:
        env_data = json.load(f)
        environment_id = env_data.get("id", "")

    fixture_path = resolve_fixture_from_id(workspace_folder, fixture_id)
    cache_path = (
        workspace_folder
        / ".webtestpilot"
        / ".cache"
        / f"{test_id} - {environment_id}"
        / "cache.json"
    )

    config_path = str(Path(__file__).parent / "src" / "config.yaml")
    cdp_endpoint = "http://localhost:9222"

    async with async_playwright() as playwright:
        browser = await playwright.chromium.connect_over_cdp(cdp_endpoint)
        result = await run_test_from_file(
            browser=browser,
            test_file_path=str(test_path),
            config_path=config_path,
            target_id=None,
            fixture_file_path=str(fixture_path) if fixture_path else None,
            environment_file_path=str(environment_path),
            enable_assertions=True,
            cache_path=cache_path,
        )
        # Add test metadata to result for logging
        result["test_name"] = test_name
        result["test_id"] = test_id
        return result


def main():
    """Main CLI entry point with simplified syntax"""
    parser = argparse.ArgumentParser(
        description="WebTestPilot CLI - Run automated web tests",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  gui-test 1.1.1 --env production
  gui-test ieee-gui /12306/dining-service --env staging
  gui-test ieee-gui "test name with spaces" --env dev
        """,
    )

    parser.add_argument(
        "test_id",
        type=str,
        help="Test ID (1.1.1, ...), exact test name, or folder path (starting with /, e.g. /ctrip/manage-addresses)",
    )

    parser.add_argument(
        "--env",
        type=str,
        required=True,
        help="Environment name (e.g., production, staging, dev)",
    )

    parser.add_argument(
        "--openai_api_key",
        type=str,
        required=False,
        help="OpenAI API key (will be set to OPENAI_QQ_API_KEY environment variable)",
    )

    args = parser.parse_args()

    # Set OpenAI API key if provided
    if args.openai_api_key:
        os.environ["OPENAI_QQ_API_KEY"] = args.openai_api_key

    # os.environ["BAML_LOG"] = "error"

    # Load config early to initialize logging before any operations
    config_path = Path(__file__).parent / "src" / "config.yaml"
    Config.load(config_path)

    # Find workspace root
    current_dir = Path.cwd()
    
    # Load environment variables from current_dir/.env
    load_dotenv(current_dir / ".env")
    
    # Print OpenAI QQ API key status
    openai_key = os.environ.get("OPENAI_QQ_API_KEY")
    if openai_key:
        print(f"OPENAI_QQ_API_KEY: {openai_key[:10]}...{openai_key[-4:] if len(openai_key) > 14 else ''}")
    else:
        print("OPENAI_QQ_API_KEY: Not set")
    
    workspace_folder = find_workspace_root(current_dir)

    if not workspace_folder:
        print(
            """Error: Could not find .webtestpilot folder in current directory
Hint: Go to folder with .webtestpilot inside or move .webtestpilot folder here."""
        )
        sys.exit(1)
        
    

    print(f"Using workspace: {workspace_folder}")

    # Resolve environment
    environment_path = resolve_environment_by_name(workspace_folder, args.env)
    if not environment_path:
        available_envs = list_available_environments(workspace_folder)
        print(f"Error: Environment '{args.env}' not found")
        if available_envs:
            print("\nAvailable environments:")
            for env in available_envs:
                print(f"  - {env}")
        else:
            print("  No environments found in workspace")
        sys.exit(1)

    print(f"Using environment: {args.env} ({environment_path})")

    # Determine if test_id is a folder path or test ID
    is_folder = args.test_id.startswith("/")

    if is_folder:
        # Handle folder mode - run all tests in folder
        folder_path = args.test_id.lstrip("/")
        test_files = list_tests_in_folder(workspace_folder, folder_path)

        if not test_files:
            print(f"Error: No tests found in folder '{folder_path}'")
            sys.exit(1)

        print(f"Found {len(test_files)} test(s) in folder '{folder_path}'")
        print()

        # Run all tests sequentially
        async def run_all():
            results = []
            for i, test_file in enumerate(test_files, 1):
                # Load test to get name
                with open(test_file, "r", encoding="utf-8") as f:
                    test_data = json.load(f)
                    test_name = test_data.get("name", test_file.stem)
                    test_id = test_data.get("id", "")

                print(f"\n[{i}/{len(test_files)}] Running: {test_name}")
                print(f"ID: {test_id}")
                print(f"File: {test_file.name}")

                result = await run_single_test(
                    test_file,
                    environment_path,
                    workspace_folder,
                )
                results.append(result)

                status = "\033[92m✓ PASSED\033[0m" if result["success"] else "\033[91m✗ FAILED\033[0m"
                print(f"  Result: {status}")
            return results

        all_results = asyncio.run(run_all())

        # Print summary
        passed = sum(1 for r in all_results if r["success"])
        failed = len(all_results) - passed

        print("\n" + "=" * 60)
        print("TEST SUMMARY")
        print("=" * 60)
        for r in all_results:
            status_text = "\033[92mPASSED\033[0m" if r["success"] else "\033[91mFAILED\033[0m"
            print(f"  {r['test_name']}: {status_text}")
        print("=" * 60)
        print(
            f"Total: {passed} passed, {failed} failed out of {len(all_results)} tests"
        )
        print("=" * 60)

        # Exit with failure if any test failed
        sys.exit(0 if failed == 0 else 1)

    else:
        # Handle single test mode
        test_path = resolve_test_by_partial_id(workspace_folder, args.test_id)

        if not test_path:
            print(f"Error: No test found with ID containing '{args.test_id}'")
            sys.exit(1)

        # Load test to get name
        with open(test_path, "r", encoding="utf-8") as f:
            test_data = json.load(f)
            test_name = test_data.get("name", test_path.stem)
            test_id = test_data.get("id", "")

        print(f"\nRunning: {test_name}")
        print(f"ID: {test_id}")
        print(f"File: {test_path.name}")
        print()

        async def run():
            return await run_single_test(
                test_path,
                environment_path,
                workspace_folder,
            )

        result = asyncio.run(run())

        # Print result
        status = "\033[92m✓ PASSED\033[0m" if result["success"] else "\033[91m✗ FAILED\033[0m"
        print(f"Result: {status}\n")
        # print(json.dumps(result, indent=2))

        # Exit with appropriate code
        sys.exit(0 if result["success"] else 1)


if __name__ == "__main__":
    main()
