"""CI/CD Integration Configuration Generator for mcpaudit.

Generates pipeline configs for GitHub Actions, GitLab CI,
pre-commit hooks, and Jenkins to integrate mcpaudit scanning.
"""

from __future__ import annotations

from dataclasses import dataclass, field


@dataclass
class CIOptions:
    """Options for CI/CD configuration generation."""

    min_trust_score: int = 70
    fail_on_severity: str = "high"  # critical, high, medium, low
    formats: list[str] = field(default_factory=lambda: ["text"])
    targets: list[str] = field(default_factory=lambda: ["."])
    extra_flags: list[str] = field(default_factory=list)
    python_version: str = "3.11"
    mcpaudit_version: str = "latest"


def generate_github_action(options: CIOptions | None = None) -> str:
    """Generate a GitHub Actions workflow YAML for mcpaudit.

    Args:
        options: CI configuration options.

    Returns:
        YAML string for .github/workflows/mcpaudit.yml
    """
    opts = options or CIOptions()
    targets_str = " ".join(opts.targets)
    extra = " ".join(opts.extra_flags)
    if extra:
        extra = f" {extra}"

    format_flag = ""
    if opts.formats and opts.formats[0] != "text":
        format_flag = f" --format {opts.formats[0]}"

    severity_map = {
        "critical": "critical",
        "high": "high",
        "medium": "medium",
        "low": "low",
    }
    severity = severity_map.get(opts.fail_on_severity, "high")

    pip_version = ""
    if opts.mcpaudit_version != "latest":
        pip_version = f"=={opts.mcpaudit_version}"

    return f"""name: MCP Security Audit

on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

permissions:
  contents: read
  security-events: write

jobs:
  mcpaudit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python {opts.python_version}
        uses: actions/setup-python@v5
        with:
          python-version: "{opts.python_version}"

      - name: Install mcpaudit
        run: pip install mcpaudit{pip_version}

      - name: Run MCP Security Scan
        run: >
          mcpaudit {targets_str}
          --severity {severity}
          --min-score {opts.min_trust_score}{format_flag}{extra}

      - name: Upload SARIF (optional)
        if: always()
        run: |
          mcpaudit {targets_str} --format sarif --output results.sarif || true

      - name: Upload SARIF to GitHub Security
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: results.sarif
        continue-on-error: true
"""


def generate_gitlab_ci(options: CIOptions | None = None) -> str:
    """Generate a GitLab CI job YAML for mcpaudit.

    Args:
        options: CI configuration options.

    Returns:
        YAML string for .gitlab-ci.yml inclusion.
    """
    opts = options or CIOptions()
    targets_str = " ".join(opts.targets)
    extra = " ".join(opts.extra_flags)
    if extra:
        extra = f" {extra}"

    format_flag = ""
    if opts.formats and opts.formats[0] != "text":
        format_flag = f" --format {opts.formats[0]}"

    severity_map = {
        "critical": "critical",
        "high": "high",
        "medium": "medium",
        "low": "low",
    }
    severity = severity_map.get(opts.fail_on_severity, "high")

    pip_version = ""
    if opts.mcpaudit_version != "latest":
        pip_version = f"=={opts.mcpaudit_version}"

    return f"""mcpaudit:
  stage: test
  image: python:{opts.python_version}-slim
  before_script:
    - pip install --quiet mcpaudit{pip_version}
  script:
    - >
      mcpaudit {targets_str}
      --severity {severity}
      --min-score {opts.min_trust_score}{format_flag}{extra}
  artifacts:
    when: always
    paths:
      - mcpaudit-report.*
    reports:
      sast: mcpaudit-report.json
  allow_failure: false
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
"""


def generate_pre_commit(options: CIOptions | None = None) -> str:
    """Generate a pre-commit hook configuration for mcpaudit.

    Args:
        options: CI configuration options.

    Returns:
        YAML string for .pre-commit-config.yaml inclusion.
    """
    opts = options or CIOptions()
    targets_str = " ".join(opts.targets)
    extra = " ".join(opts.extra_flags)

    args_list = [
        f"--severity {opts.fail_on_severity}",
        f"--min-score {opts.min_trust_score}",
    ]
    if extra:
        args_list.append(extra)

    args_yaml = "\n".join(f"      - {a}" for a in args_list)

    rev = "latest"
    if opts.mcpaudit_version != "latest":
        rev = f"v{opts.mcpaudit_version}"

    return f"""repos:
  - repo: https://github.com/anthropics/mcpaudit
    rev: {rev}
    hooks:
      - id: mcpaudit
        name: MCP Security Audit
        entry: mcpaudit
        language: python
        types_or: [python, ts, javascript]
        args:
{args_yaml}
        pass_filenames: true
"""


def generate_jenkins(options: CIOptions | None = None) -> str:
    """Generate a Jenkins pipeline stage for mcpaudit.

    Args:
        options: CI configuration options.

    Returns:
        Groovy string for Jenkinsfile stage inclusion.
    """
    opts = options or CIOptions()
    targets_str = " ".join(opts.targets)
    extra = " ".join(opts.extra_flags)
    if extra:
        extra = f" {extra}"

    format_flag = ""
    if opts.formats and opts.formats[0] != "text":
        format_flag = f" --format {opts.formats[0]}"

    severity_map = {
        "critical": "critical",
        "high": "high",
        "medium": "medium",
        "low": "low",
    }
    severity = severity_map.get(opts.fail_on_severity, "high")

    pip_version = ""
    if opts.mcpaudit_version != "latest":
        pip_version = f"=={opts.mcpaudit_version}"

    return f"""stage('MCP Security Audit') {{
    steps {{
        sh '''
            pip install mcpaudit{pip_version}
            mcpaudit {targets_str} \\
                --severity {severity} \\
                --min-score {opts.min_trust_score}{format_flag}{extra}
        '''
    }}
    post {{
        always {{
            sh 'mcpaudit {targets_str} --format sarif --output mcpaudit-results.sarif || true'
            archiveArtifacts artifacts: 'mcpaudit-results.sarif', allowEmptyArchive: true
        }}
    }}
}}
"""


def format_ci_config(platform: str, options: CIOptions | None = None) -> str:
    """Generate CI config for the specified platform.

    Args:
        platform: One of 'github', 'gitlab', 'pre-commit', 'jenkins'.
        options: CI configuration options.

    Returns:
        Configuration string.

    Raises:
        ValueError: If platform is not supported.
    """
    generators = {
        "github": generate_github_action,
        "gitlab": generate_gitlab_ci,
        "pre-commit": generate_pre_commit,
        "jenkins": generate_jenkins,
    }
    if platform not in generators:
        valid = ", ".join(sorted(generators.keys()))
        raise ValueError(f"Unknown platform '{platform}'. Valid: {valid}")
    return generators[platform](options)
