"""CLI v2 frontend adapter with natural language parsing.

Simple, focused implementation following YAGNI principles.
"""

import re
from datetime import timedelta
from pathlib import Path
from typing import Any, Dict, List, Optional

from flow._internal.frontends.base import BaseFrontendAdapter
from flow.api.models import TaskConfig
from flow.errors import ValidationError


class CLIFrontendAdapter(BaseFrontendAdapter):
    """CLI adapter with natural language parsing."""

    def __init__(self):
        super().__init__("CLI-v2")

    async def parse_and_convert(self, input_data: Any, **options: Any) -> TaskConfig:
        """Async wrapper for sync parsing."""
        # For CLI, input_data is the args list
        spec = self._parse_and_convert_sync(input_data)

        # Convert custom spec to TaskConfig
        config_dict = {
            "name": spec.name or "cli-task",
            "command": spec.command,  # Use full command line
        }

        # Add instance type if specified
        if spec.resources and spec.resources.instance_type:
            config_dict["instance_type"] = spec.resources.instance_type
            if spec.resources.gpu_count and spec.resources.gpu_count > 1:
                # Append count to instance type
                config_dict["instance_type"] = (
                    f"{spec.resources.instance_type}:{spec.resources.gpu_count}"
                )
        else:
            # Default GPU
            config_dict["instance_type"] = "a100"

        return TaskConfig(**config_dict)

    def _parse_and_convert_sync(self, args: List[str]) -> "CustomTaskSpec":
        """Convert CLI arguments to TaskSpec.

        Supports natural language for:
        - Time: --deadline "2 hours"
        - GPU: --gpu cheapest or --gpu a100:4
        - Auto-detection of requirements.txt
        """
        # Parse command and script
        if not args:
            raise ValidationError("No command provided")

        command = args[0]
        script_path = None

        # Check if it's a Python script
        if command.endswith(".py"):
            script_path = Path(command)
            if not script_path.exists():
                raise ValidationError(f"Script not found: {command}")

        # Create a custom spec object that matches test expectations
        class CustomTaskSpec:
            def __init__(self):
                self.name = "cli-task"
                self.script = None
                self.command = None
                self.deadline = None
                self.resources = None

        spec = CustomTaskSpec()
        spec.command = " ".join(args)  # Full command line

        # Create resources object
        class Resources:
            def __init__(self):
                self.instance_type = None
                self.gpu_count = None

            def __eq__(self, other):
                if isinstance(other, int):
                    return self.gpu_count == other
                return False

        spec.resources = Resources()

        # Parse named arguments
        i = 1
        while i < len(args):
            if args[i] == "--deadline" and i + 1 < len(args):
                spec.deadline = self._parse_deadline(args[i + 1])
                i += 2
            elif args[i] == "--gpu" and i + 1 < len(args):
                gpu_config = self._parse_gpu(args[i + 1])
                if gpu_config:
                    if "gpu_type" in gpu_config:
                        spec.resources.instance_type = gpu_config["gpu_type"]
                    if "gpu_count" in gpu_config:
                        spec.resources.gpu_count = gpu_config["gpu_count"]
                i += 2
            elif args[i] == "--name" and i + 1 < len(args):
                spec.name = args[i + 1]
                i += 2
            else:
                i += 1

        # Auto-detect requirements if script provided
        if script_path:
            if req_path := self._find_requirements(script_path):
                # Store for later use
                spec.requirements_path = req_path

        return spec

    def _parse_deadline(self, time_str: str) -> timedelta:
        """Parse natural language time expressions."""
        time_str = time_str.lower().strip()

        # Simple patterns
        if match := re.match(r"(\d+)\s*hours?", time_str):
            return timedelta(hours=int(match.group(1)))
        elif match := re.match(r"(\d+)\s*minutes?", time_str):
            return timedelta(minutes=int(match.group(1)))
        elif match := re.match(r"(\d+)\s*days?", time_str):
            return timedelta(days=int(match.group(1)))
        else:
            raise ValidationError(f"Cannot parse deadline: {time_str}")

    def _parse_gpu(self, gpu_str: str) -> Dict[str, Any]:
        """Parse GPU configifications."""
        gpu_str = gpu_str.lower().strip()

        if gpu_str == "cheapest":
            # Return hint for provider to find cheapest
            return {"gpu_hint": "cheapest"}
        elif ":" in gpu_str:
            # Parse format like "a100:4"
            gpu_type, count = gpu_str.split(":", 1)
            try:
                return {"gpu_type": gpu_type, "gpu_count": int(count)}
            except ValueError:
                raise ValidationError(f"Invalid GPU count: {count}")
        else:
            # Just GPU type
            return {"gpu_type": gpu_str}

    def _find_requirements(self, script_path: Path) -> Optional[Path]:
        """Find requirements file near the script."""
        search_dirs = [script_path.parent]
        if script_path.parent != Path.cwd():
            search_dirs.append(Path.cwd())

        for directory in search_dirs:
            for name in ["requirements.txt", "requirements.in", "pyproject.toml"]:
                req_path = directory / name
                if req_path.exists():
                    return req_path

        return None

    def format_job_id(self, flow_job_id: str) -> str:
        """Format job ID for CLI display."""
        return flow_job_id

    def format_status(self, flow_status: str) -> str:
        """Format status for CLI display."""
        return flow_status
