"""
GitLab CI template generator for Warden.

Generates GitLab CI pipeline files for running Warden in CI/CD.
"""

from dataclasses import dataclass
from typing import Dict, List, Optional
from pathlib import Path


@dataclass
class GitLabCIConfig:
    """Configuration for GitLab CI pipeline."""

    stage_name: str = "analysis"
    image: str = "python:3.11"
    warden_version: Optional[str] = None
    fail_on_issues: bool = True
    cache_dependencies: bool = True
    frames: Optional[List[str]] = None
    rules: Optional[List[Dict[str, str]]] = None

    def __post_init__(self):
        if self.frames is None:
            self.frames = ["security", "fuzz", "property"]
        if self.rules is None:
            self.rules = [{"if": "$CI_PIPELINE_SOURCE == 'merge_request_event'"}]


class GitLabCITemplate:
    """Generates GitLab CI pipeline templates for Warden."""

    @staticmethod
    def generate(config: GitLabCIConfig) -> str:
        """
        Generate GitLab CI YAML content.

        Args:
            config: Configuration for the pipeline

        Returns:
            YAML content as string
        """
        warden_install = (
            f"pip install warden-core=={config.warden_version}"
            if config.warden_version
            else "pip install warden-core"
        )

        frames_arg = (
            " ".join(f"--frame {frame}" for frame in config.frames)
            if config.frames
            else ""
        )

        fail_arg = "--fail-on-issues" if config.fail_on_issues else ""

        cache_section = (
            GitLabCITemplate._generate_cache() if config.cache_dependencies else ""
        )

        rules_section = GitLabCITemplate._generate_rules(config.rules)

        template = f"""# GitLab CI Pipeline for Warden Analysis
# Auto-generated by Warden Infrastructure Module

stages:
  - {config.stage_name}

{cache_section}

warden-analysis:
  stage: {config.stage_name}
  image: {config.image}

  before_script:
    - python --version
    - pip install --upgrade pip
    - {warden_install}

  script:
    - warden analyze {frames_arg} {fail_arg} --ci --output warden-report.json

  artifacts:
    reports:
      # GitLab doesn't support custom report types, use generic artifact
      junit: warden-report.json
    paths:
      - warden-report.json
    expire_in: 30 days
    when: always

  {rules_section}

  # Optional: Fail job if critical issues found
  after_script:
    - |
      if [ -f warden-report.json ]; then
        echo "Warden analysis complete. Check artifacts for details."
      fi
"""

        return template

    @staticmethod
    def _generate_cache() -> str:
        """Generate cache configuration."""
        return """# Cache pip dependencies
cache:
  paths:
    - .cache/pip
  key: warden-pip-cache
"""

    @staticmethod
    def _generate_rules(rules: List[Dict[str, str]]) -> str:
        """Generate rules section."""
        if not rules:
            return ""

        lines = ["rules:"]
        for rule in rules:
            for key, value in rule.items():
                lines.append(f"    - {key}: {value}")

        return "\n  ".join(lines)

    @staticmethod
    def save_to_file(config: GitLabCIConfig, output_path: Path) -> None:
        """
        Generate and save pipeline to file.

        Args:
            config: Pipeline configuration
            output_path: Path to save pipeline file
        """
        content = GitLabCITemplate.generate(config)
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_text(content)

    @staticmethod
    def validate_pipeline(pipeline_path: Path) -> bool:
        """
        Validate GitLab CI pipeline file.

        Args:
            pipeline_path: Path to pipeline file

        Returns:
            True if valid, False otherwise
        """
        if not pipeline_path.exists():
            return False

        try:
            import yaml

            content = pipeline_path.read_text()
            data = yaml.safe_load(content)

            # Basic validation
            if not isinstance(data, dict):
                return False

            # Check for stages or jobs
            has_stages = "stages" in data
            has_jobs = any(
                isinstance(v, dict) and "script" in v for v in data.values()
            )

            return has_stages or has_jobs

        except Exception:
            return False
