"""
koci Init Controller

Generates starter koci.yml files based on project detection.
"""

from pathlib import Path
from cement import Controller, ex


# Project templates
TEMPLATES = {
    'node': '''version: "1"
name: {name}

stages:
  - build
  - test

jobs:
  install:
    stage: build
    image: node:20-alpine
    steps:
      - name: Install dependencies
        run: npm ci
    artifacts:
      paths:
        - node_modules/

  lint:
    stage: build
    image: node:20-alpine
    needs: [install]
    steps:
      - run: npm run lint
    artifacts:
      consume: [install]

  test:
    stage: test
    image: node:20-alpine
    needs: [install]
    steps:
      - name: Run tests
        run: npm test
    artifacts:
      consume: [install]

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
''',

    'python': '''version: "1"
name: {name}

stages:
  - build
  - test

jobs:
  install:
    stage: build
    image: python:3.11-slim
    steps:
      - name: Install dependencies
        run: |
          pip install --upgrade pip
          pip install -r requirements.txt
    artifacts:
      paths:
        - .venv/

  lint:
    stage: build
    image: python:3.11-slim
    needs: [install]
    steps:
      - name: Run linter
        run: |
          pip install flake8
          flake8 .
    artifacts:
      consume: [install]

  test:
    stage: test
    image: python:3.11-slim
    needs: [install]
    steps:
      - name: Run tests
        run: |
          pip install pytest
          pytest
    artifacts:
      consume: [install]

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
''',

    'go': '''version: "1"
name: {name}

stages:
  - build
  - test

jobs:
  build:
    stage: build
    image: golang:1.21-alpine
    steps:
      - name: Download dependencies
        run: go mod download
      - name: Build
        run: go build -v ./...
    artifacts:
      paths:
        - bin/

  test:
    stage: test
    image: golang:1.21-alpine
    needs: [build]
    steps:
      - name: Run tests
        run: go test -v ./...
    artifacts:
      consume: [build]

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
''',

    'rust': '''version: "1"
name: {name}

stages:
  - build
  - test

jobs:
  build:
    stage: build
    image: rust:1.73-slim
    steps:
      - name: Build
        run: cargo build --release
    artifacts:
      paths:
        - target/release/

  test:
    stage: test
    image: rust:1.73-slim
    needs: [build]
    steps:
      - name: Run tests
        run: cargo test
    artifacts:
      consume: [build]

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
''',

    'docker': '''version: "1"
name: {name}

stages:
  - build
  - test
  - publish

jobs:
  build:
    stage: build
    image: docker:24-dind
    steps:
      - name: Build Docker image
        run: docker build -t {name}:$CI_COMMIT_SHA .

  test:
    stage: test
    image: docker:24-dind
    needs: [build]
    steps:
      - name: Test container
        run: |
          docker run --rm {name}:$CI_COMMIT_SHA --version

  publish:
    stage: publish
    image: docker:24-dind
    needs: [test]
    when: branch == 'main'
    steps:
      - name: Push to registry
        run: |
          docker tag {name}:$CI_COMMIT_SHA registry.example.com/{name}:latest
          docker push registry.example.com/{name}:latest

on:
  push:
    branches: [main]
''',

    'generic': '''version: "1"
name: {name}

stages:
  - build
  - test
  - deploy

jobs:
  build:
    stage: build
    image: alpine:latest
    steps:
      - name: Build
        run: echo "Add your build commands here"

  test:
    stage: test
    image: alpine:latest
    needs: [build]
    steps:
      - name: Test
        run: echo "Add your test commands here"

  deploy:
    stage: deploy
    image: alpine:latest
    needs: [test]
    when: branch == 'main'
    steps:
      - name: Deploy
        run: echo "Add your deployment commands here"

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
'''
}


class Init(Controller):
    """Controller for the 'init' command."""

    class Meta:
        label = 'init'
        stacked_on = 'base'
        stacked_type = 'nested'
        description = 'Initialize a new koci pipeline'
        help = 'Create a starter koci.yml file'

        arguments = [
            (['-t', '--type'],
             {'help': 'Project type (node, python, go, rust, docker, generic)',
              'action': 'store',
              'dest': 'type',
              'choices': ['node', 'python', 'go', 'rust', 'docker', 'generic'],
              'default': None}),

            (['-n', '--name'],
             {'help': 'Pipeline name',
              'action': 'store',
              'dest': 'name',
              'default': None}),

            (['-o', '--output'],
             {'help': 'Output file path',
              'action': 'store',
              'dest': 'output',
              'default': 'koci.yml'}),

            (['-f', '--force'],
             {'help': 'Overwrite existing file',
              'action': 'store_true',
              'dest': 'force',
              'default': False}),
        ]

    @ex(help='Initialize pipeline')
    def _default(self):
        """Create a new koci.yml file."""
        workspace = Path.cwd()
        output_path = workspace / self.app.pargs.output

        # Check if file exists
        if output_path.exists() and not self.app.pargs.force:
            print(f"Error: {output_path} already exists. Use -f to overwrite.")
            self.app.exit_code = 1
            return

        # Detect or get project type
        project_type = self.app.pargs.type or self._detect_project_type(workspace)

        # Get project name
        name = self.app.pargs.name or workspace.name

        # Generate content
        template = TEMPLATES.get(project_type, TEMPLATES['generic'])
        content = template.format(name=name)

        # Write file
        output_path.write_text(content)

        print(f"✓ Created {output_path}")
        print(f"  Project type: {project_type}")
        print(f"  Pipeline name: {name}")
        print("\nNext steps:")
        print(f"  1. Review and customize {self.app.pargs.output}")
        print("  2. Run: koci validate")
        print("  3. Run: koci run")

    def _detect_project_type(self, workspace: Path) -> str:
        """Detect project type from files."""
        # Node.js
        if (workspace / 'package.json').exists():
            return 'node'

        # Python
        if any((workspace / f).exists() for f in ['requirements.txt', 'setup.py', 'pyproject.toml']):
            return 'python'

        # Go
        if (workspace / 'go.mod').exists():
            return 'go'

        # Rust
        if (workspace / 'Cargo.toml').exists():
            return 'rust'

        # Docker
        if (workspace / 'Dockerfile').exists():
            return 'docker'

        return 'generic'
