"""
DSL Parser API Routes

Validates DSL YAML syntax and schema.
"""

import yaml
from fastapi import APIRouter, HTTPException, status
from pydantic import BaseModel, ValidationError

from opentester.models.dsl import DSLScript

router = APIRouter()


class ValidateDSLRequest(BaseModel):
    """Request to validate DSL YAML."""
    dsl_yaml: str


class ValidateDSLResponse(BaseModel):
    """Response with validation result."""
    valid: bool
    message: str
    error_type: str | None = None
    details: list | None = None
    line: int | None = None
    hint: str | None = None


@router.post("/validate", response_model=ValidateDSLResponse)
async def validate_dsl(data: ValidateDSLRequest) -> ValidateDSLResponse:
    """Validate DSL YAML syntax and schema.

    This endpoint checks if the DSL YAML is valid and can be executed.
    Returns detailed error information for invalid DSL.
    """
    if not data.dsl_yaml or not data.dsl_yaml.strip():
        return ValidateDSLResponse(
            valid=False,
            message="DSL content is empty",
            error_type="empty_input",
            hint="Provide a non-empty DSL YAML string"
        )

    # Parse YAML
    try:
        dsl_data = yaml.safe_load(data.dsl_yaml)
    except yaml.YAMLError as e:
        line = None
        if hasattr(e, 'problem_mark') and e.problem_mark:
            line = e.problem_mark.line

        return ValidateDSLResponse(
            valid=False,
            message=f"YAML syntax error: {str(e)}",
            error_type="yaml_syntax",
            line=line,
            hint="Check YAML indentation and syntax"
        )

    # Validate with Pydantic model
    try:
        script = DSLScript.model_validate(dsl_data)

        return ValidateDSLResponse(
            valid=True,
            message="DSL is valid",
            details={
                "case_name": script.meta.get("name", "Unnamed") if script.meta else "Unnamed",
                "step_count": len(script.steps),
                "variables": list(script.vars.keys()) if script.vars else []
            }
        )

    except ValidationError as e:
        errors = []
        for err in e.errors():
            errors.append({
                "field": ".".join(str(x) for x in err["loc"]),
                "error": err["msg"],
                "type": err["type"]
            })

        return ValidateDSLResponse(
            valid=False,
            message="DSL schema validation failed",
            error_type="dsl_schema",
            details=errors,
            hint="Check field types and required fields. See DSL_SPEC.md for reference."
        )
