"""CI/CD configuration templates.

This module provides functions to generate CI/CD configuration files
for various platforms.
"""

from __future__ import annotations

from pathlib import Path
from typing import Any


def generate_github_workflow(
    checkpoint_name: str = "data_validation",
    config_file: str = "truthound.yaml",
    data_path: str = "data/",
    schedule: str = "0 0 * * *",  # Daily at midnight
    python_version: str = "3.11",
    notify_slack: bool = False,
    slack_webhook_secret: str = "SLACK_WEBHOOK_URL",
    fail_on_issues: bool = True,
    min_severity: str = "high",
) -> str:
    """Generate a GitHub Actions workflow for Truthound.

    Args:
        checkpoint_name: Name of the checkpoint to run.
        config_file: Path to checkpoint config file.
        data_path: Path to data directory.
        schedule: Cron schedule for the workflow.
        python_version: Python version to use.
        notify_slack: Whether to include Slack notification.
        slack_webhook_secret: Name of the secret containing Slack webhook.
        fail_on_issues: Whether to fail the workflow on issues.
        min_severity: Minimum severity to fail on.

    Returns:
        YAML content for the workflow file.
    """
    slack_step = ""
    if notify_slack:
        slack_step = f"""
      - name: Notify Slack on Failure
        if: failure()
        uses: slackapi/slack-github-action@v1.24.0
        with:
          payload: |
            {{
              "text": "Data Quality Check Failed",
              "blocks": [
                {{
                  "type": "section",
                  "text": {{
                    "type": "mrkdwn",
                    "text": ":x: *Data Quality Check Failed*\\n*Checkpoint:* {checkpoint_name}\\n*Repository:* ${{{{ github.repository }}}}\\n*Run:* ${{{{ github.server_url }}}}/${{{{ github.repository }}}}/actions/runs/${{{{ github.run_id }}}}"
                  }}
                }}
              ]
            }}
        env:
          SLACK_WEBHOOK_URL: ${{{{ secrets.{slack_webhook_secret} }}}}
          SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
"""

    return f"""# Truthound Data Quality Workflow
# Generated by Truthound CI/CD Templates

name: Data Quality Check

on:
  schedule:
    - cron: '{schedule}'
  push:
    paths:
      - '{data_path}**'
      - '{config_file}'
  pull_request:
    paths:
      - '{data_path}**'
      - '{config_file}'
  workflow_dispatch:
    inputs:
      checkpoint:
        description: 'Checkpoint to run'
        required: false
        default: '{checkpoint_name}'

jobs:
  data-quality:
    runs-on: ubuntu-latest

    permissions:
      contents: read
      checks: write
      pull-requests: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

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

      - name: Install Truthound
        run: |
          python -m pip install --upgrade pip
          pip install truthound[all]

      - name: Run Data Quality Check
        id: truthound
        run: |
          truthound checkpoint run ${{{{ github.event.inputs.checkpoint || '{checkpoint_name}' }}}} \\
            --config {config_file} \\
            --github-summary \\
            {'--strict' if fail_on_issues else ''}
        env:
          GITHUB_TOKEN: ${{{{ secrets.GITHUB_TOKEN }}}}

      - name: Upload Results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: data-quality-report
          path: |
            truthound_results/
            truthound_docs/
          retention-days: 30

      - name: Comment on PR
        if: github.event_name == 'pull_request' && always()
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const status = '${{{{ steps.truthound.outcome }}}}';
            const emoji = status === 'success' ? ':white_check_mark:' : ':x:';

            github.rest.issues.createComment({{
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `## ${{emoji}} Data Quality Report\\n\\nCheckpoint: **{checkpoint_name}**\\nStatus: **${{status.toUpperCase()}}**\\n\\nSee the [workflow run](${{{{ github.server_url }}}}/${{{{ github.repository }}}}/actions/runs/${{{{ github.run_id }}}}) for details.`
            }});
{slack_step}
"""


def generate_gitlab_ci(
    checkpoint_name: str = "data_validation",
    config_file: str = "truthound.yaml",
    schedule: str = "0 0 * * *",
    python_image: str = "python:3.11-slim",
    stages: list[str] | None = None,
) -> str:
    """Generate a GitLab CI configuration for Truthound.

    Args:
        checkpoint_name: Name of the checkpoint to run.
        config_file: Path to checkpoint config file.
        schedule: Cron schedule.
        python_image: Docker image to use.
        stages: Pipeline stages.

    Returns:
        YAML content for .gitlab-ci.yml.
    """
    stages = stages or ["validate", "report"]

    return f"""# Truthound Data Quality Pipeline
# Generated by Truthound CI/CD Templates

stages:
  - validate
  - report

variables:
  TRUTHOUND_CONFIG: {config_file}
  CHECKPOINT_NAME: {checkpoint_name}
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"

.truthound-base:
  image: {python_image}
  cache:
    paths:
      - .pip-cache/
  before_script:
    - pip install --upgrade pip
    - pip install truthound[all]

data-quality:
  extends: .truthound-base
  stage: validate
  script:
    - truthound checkpoint run $CHECKPOINT_NAME --config $TRUTHOUND_CONFIG --format json --output result.json
    - |
      if [ -f result.json ]; then
        echo "Validation completed"
        cat result.json | python -c "import json,sys; d=json.load(sys.stdin); exit(1 if d['status'] in ['failure','error'] else 0)"
      fi
  artifacts:
    when: always
    paths:
      - result.json
      - truthound_results/
      - truthound.env
    reports:
      dotenv: truthound.env
    expire_in: 30 days
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_PIPELINE_SOURCE == "push"
      changes:
        - "data/**/*"
        - $TRUTHOUND_CONFIG
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      changes:
        - "data/**/*"
        - $TRUTHOUND_CONFIG

generate-docs:
  extends: .truthound-base
  stage: report
  needs:
    - data-quality
  script:
    - truthound checkpoint run $CHECKPOINT_NAME --config $TRUTHOUND_CONFIG --store ./docs
  artifacts:
    paths:
      - docs/
    expire_in: 30 days
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
"""


def generate_jenkinsfile(
    checkpoint_name: str = "data_validation",
    config_file: str = "truthound.yaml",
    python_version: str = "3.11",
    agent: str = "any",
    notify_email: str | None = None,
) -> str:
    """Generate a Jenkinsfile for Truthound.

    Args:
        checkpoint_name: Name of the checkpoint to run.
        config_file: Path to checkpoint config file.
        python_version: Python version to use.
        agent: Jenkins agent label.
        notify_email: Email for notifications.

    Returns:
        Groovy content for Jenkinsfile.
    """
    email_step = ""
    if notify_email:
        email_step = f"""
        failure {{
            emailext (
                subject: "Data Quality Check Failed: ${{env.JOB_NAME}} #${{env.BUILD_NUMBER}}",
                body: '''
                    <h2>Data Quality Check Failed</h2>
                    <p><b>Checkpoint:</b> {checkpoint_name}</p>
                    <p><b>Build:</b> ${{env.BUILD_URL}}</p>
                    <p>See attached report for details.</p>
                ''',
                to: '{notify_email}',
                attachmentsPattern: 'truthound-junit.xml,truthound-result.json'
            )
        }}
"""

    return f"""// Truthound Data Quality Pipeline
// Generated by Truthound CI/CD Templates

pipeline {{
    agent {{ label '{agent}' }}

    triggers {{
        cron('H 0 * * *')  // Daily at midnight
    }}

    environment {{
        TRUTHOUND_CONFIG = '{config_file}'
        CHECKPOINT_NAME = '{checkpoint_name}'
    }}

    stages {{
        stage('Setup') {{
            steps {{
                sh '''
                    python{python_version} -m venv venv
                    . venv/bin/activate
                    pip install --upgrade pip
                    pip install truthound[all]
                '''
            }}
        }}

        stage('Data Quality Check') {{
            steps {{
                sh '''
                    . venv/bin/activate
                    truthound checkpoint run $CHECKPOINT_NAME \\
                        --config $TRUTHOUND_CONFIG \\
                        --format json \\
                        --output truthound-result.json \\
                        --store ./truthound_results
                '''
            }}
            post {{
                always {{
                    // Archive results
                    archiveArtifacts artifacts: 'truthound-result.json,truthound-junit.xml,truthound_results/**/*',
                                     allowEmptyArchive: true

                    // Publish JUnit results
                    junit allowEmptyResults: true,
                          testResults: 'truthound-junit.xml'
                }}
            }}
        }}
    }}

    post {{
        always {{
            cleanWs()
        }}
{email_step}
    }}
}}
"""


def generate_circleci_config(
    checkpoint_name: str = "data_validation",
    config_file: str = "truthound.yaml",
    python_version: str = "3.11",
    resource_class: str = "medium",
) -> str:
    """Generate a CircleCI configuration for Truthound.

    Args:
        checkpoint_name: Name of the checkpoint to run.
        config_file: Path to checkpoint config file.
        python_version: Python version to use.
        resource_class: CircleCI resource class.

    Returns:
        YAML content for .circleci/config.yml.
    """
    return f"""# Truthound Data Quality Pipeline
# Generated by Truthound CI/CD Templates

version: 2.1

orbs:
  python: circleci/python@2.1

jobs:
  data-quality:
    docker:
      - image: cimg/python:{python_version}
    resource_class: {resource_class}

    steps:
      - checkout

      - python/install-packages:
          pkg-manager: pip
          packages: truthound[all]

      - run:
          name: Run Data Quality Check
          command: |
            truthound checkpoint run {checkpoint_name} \\
              --config {config_file} \\
              --format json \\
              --output artifacts/result.json \\
              --store ./truthound_results

      - store_test_results:
          path: test-results

      - store_artifacts:
          path: artifacts
          destination: truthound-results

      - store_artifacts:
          path: truthound_results
          destination: validation-results

workflows:
  version: 2

  daily-validation:
    triggers:
      - schedule:
          cron: "0 0 * * *"
          filters:
            branches:
              only:
                - main
    jobs:
      - data-quality

  on-push:
    jobs:
      - data-quality:
          filters:
            branches:
              only:
                - main
                - /feature-.*/
"""


def write_ci_config(
    platform: str,
    output_dir: str | Path = ".",
    **kwargs: Any,
) -> Path:
    """Write CI configuration file for a platform.

    Args:
        platform: CI platform ("github", "gitlab", "jenkins", "circleci").
        output_dir: Directory to write the file.
        **kwargs: Arguments to pass to the generator function.

    Returns:
        Path to the generated file.
    """
    output_dir = Path(output_dir)

    generators = {
        "github": (generate_github_workflow, ".github/workflows/data-quality.yml"),
        "gitlab": (generate_gitlab_ci, ".gitlab-ci.yml"),
        "jenkins": (generate_jenkinsfile, "Jenkinsfile"),
        "circleci": (generate_circleci_config, ".circleci/config.yml"),
    }

    if platform not in generators:
        raise ValueError(f"Unknown platform: {platform}. Supported: {list(generators.keys())}")

    generator, filename = generators[platform]
    content = generator(**kwargs)

    output_path = output_dir / filename
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_text(content)

    return output_path
