import { GitHubActionsTemplate, GitLabCITemplate, PreCommitConfig, GitignoreConfig, BranchProtectionConfig } from './types.js';

export class RepoTemplates {
  static readonly GITHUB_CI: GitHubActionsTemplate = {
    name: 'Node.js CI',
    description: 'Continuous Integration for Node.js projects with testing and linting',
    workflowType: 'ci',
    triggers: ['push', 'pull_request'],
    content: `name: CI

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

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [{{nodeVersion}}, 20]
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Use Node.js \${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: \${{ matrix.node-version }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    {{#if includeTests}}
    - name: Run tests
      run: npm test
    {{/if}}
    
    {{#if includeLinting}}
    - name: Run linting
      run: npm run lint
    {{/if}}
    
    - name: Build project
      run: npm run build --if-present
    
    {{#if includeSecurity}}
    - name: Run security audit
      run: npm audit --audit-level moderate
    {{/if}}
`,
  };

  static readonly GITHUB_CD: GitHubActionsTemplate = {
    name: 'Continuous Deployment',
    description: 'Deploy to production on main branch',
    workflowType: 'cd',
    triggers: ['push to main'],
    content: `name: Deploy

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Use Node.js {{nodeVersion}}
      uses: actions/setup-node@v4
      with:
        node-version: {{nodeVersion}}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test
    
    - name: Build project
      run: npm run build
    
    {{#if deployTarget}}
    {{#eq deployTarget "vercel"}}
    - name: Deploy to Vercel
      uses: amondnet/vercel-action@v25
      with:
        vercel-token: \${{ secrets.VERCEL_TOKEN }}
        vercel-org-id: \${{ secrets.ORG_ID }}
        vercel-project-id: \${{ secrets.PROJECT_ID }}
        vercel-args: '--prod'
    {{/eq}}
    
    {{#eq deployTarget "netlify"}}
    - name: Deploy to Netlify
      uses: nwtgck/actions-netlify@v2.0
      with:
        publish-dir: './dist'
        production-branch: main
        github-token: \${{ secrets.GITHUB_TOKEN }}
        deploy-message: "Deploy from GitHub Actions"
      env:
        NETLIFY_AUTH_TOKEN: \${{ secrets.NETLIFY_AUTH_TOKEN }}
        NETLIFY_SITE_ID: \${{ secrets.NETLIFY_SITE_ID }}
    {{/eq}}
    {{/if}}
`,
  };

  static readonly GITHUB_SECURITY: GitHubActionsTemplate = {
    name: 'Security Scan',
    description: 'Security scanning with CodeQL and dependency checks',
    workflowType: 'security',
    triggers: ['push', 'pull_request', 'schedule'],
    content: `name: Security

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
  schedule:
    - cron: '0 2 * * 1'  # Weekly on Monday at 2 AM

jobs:
  security-scan:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v2
      with:
        languages: javascript
    
    - name: Use Node.js {{nodeVersion}}
      uses: actions/setup-node@v4
      with:
        node-version: {{nodeVersion}}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Build project
      run: npm run build --if-present
    
    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v2
    
    - name: Run npm audit
      run: npm audit --audit-level moderate
    
    - name: Check for known vulnerabilities
      run: |
        npm install -g snyk
        snyk test --severity-threshold=medium
      env:
        SNYK_TOKEN: \${{ secrets.SNYK_TOKEN }}
`,
  };

  static readonly GITHUB_RELEASE: GitHubActionsTemplate = {
    name: 'Release',
    description: 'Automated release creation and publishing',
    workflowType: 'release',
    triggers: ['tag creation'],
    content: `name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Use Node.js {{nodeVersion}}
      uses: actions/setup-node@v4
      with:
        node-version: {{nodeVersion}}
        cache: 'npm'
        registry-url: 'https://registry.npmjs.org'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test
    
    - name: Build project
      run: npm run build
    
    - name: Create Release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: \${{ github.ref }}
        release_name: Release \${{ github.ref }}
        draft: false
        prerelease: false
    
    - name: Publish to NPM
      run: npm publish
      env:
        NODE_AUTH_TOKEN: \${{ secrets.NPM_TOKEN }}
`,
  };

  static readonly GITHUB_TEST: GitHubActionsTemplate = {
    name: 'Test Suite',
    description: 'Comprehensive testing with coverage reporting',
    workflowType: 'test',
    triggers: ['push', 'pull_request'],
    content: `name: Test

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

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [16, 18, 20]
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Use Node.js \${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: \${{ matrix.node-version }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests with coverage
      run: npm run test:coverage
    
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage/lcov.info
        flags: unittests
        name: codecov-umbrella
        fail_ci_if_error: true
`,
  };

  static getGitHubActionsTemplate(type: string): GitHubActionsTemplate | undefined {
    switch (type) {
      case 'ci': return this.GITHUB_CI;
      case 'cd': return this.GITHUB_CD;
      case 'security': return this.GITHUB_SECURITY;
      case 'release': return this.GITHUB_RELEASE;
      case 'test': return this.GITHUB_TEST;
      default: return undefined;
    }
  }

  static getAvailableGitHubTemplates(): string[] {
    return ['ci', 'cd', 'security', 'release', 'test'];
  }

  static processTemplate(content: string, variables: Record<string, string>): string {
    let processed = content;
    
    // Replace simple variables
    for (const [key, value] of Object.entries(variables)) {
      const regex = new RegExp(`{{${key}}}`, 'g');
      processed = processed.replace(regex, value);
    }
    
    // Handle conditional blocks (simplified)
    processed = processed.replace(/{{#if (\w+)}}([\s\S]*?){{\/if}}/g, (match, condition, block) => {
      return variables[condition] === 'true' ? block : '';
    });
    
    // Handle equality checks
    processed = processed.replace(/{{#eq (\w+) "([^"]+)"}}([\s\S]*?){{\/eq}}/g, (match, variable, value, block) => {
      return variables[variable] === value ? block : '';
    });
    
    return processed;
  }

  static generatePreCommitConfig(config: PreCommitConfig): string {
    const repos: string[] = [];
    
    if (config.includeESLint) {
      repos.push(`  - repo: local
    hooks:
      - id: eslint
        name: eslint
        entry: npx eslint
        language: system
        files: \\.(js|ts|tsx)$
        args: [--fix]`);
    }
    
    if (config.includePrettier) {
      repos.push(`  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v3.0.0-alpha.4
    hooks:
      - id: prettier
        additional_dependencies: [prettier@2.8.4]`);
    }
    
    if (config.includeTypeCheck) {
      repos.push(`  - repo: local
    hooks:
      - id: typescript
        name: typescript
        entry: npx tsc
        language: system
        files: \\.(ts|tsx)$
        args: [--noEmit]`);
    }
    
    if (config.includeTests) {
      repos.push(`  - repo: local
    hooks:
      - id: jest
        name: jest
        entry: npm test
        language: system
        pass_filenames: false
        always_run: false
        files: \\.(test|spec)\\.(js|ts|tsx)$`);
    }
    
    for (const hook of config.customHooks) {
      repos.push(`  - repo: local
    hooks:
      - id: custom-${hook.toLowerCase().replace(/\s+/g, '-')}
        name: ${hook}
        entry: ${hook}
        language: system`);
    }

    return `# See https://pre-commit.com for more information
repos:
${repos.join('\n')}
`;
  }

  static generateHuskyConfig(config: PreCommitConfig): string {
    return `#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx pre-commit run --all-files
`;
  }

  static generateGitignore(config: GitignoreConfig): string {
    let content = '';
    
    // Project-specific ignores
    switch (config.projectType) {
      case 'node':
        content += `# Node.js
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.npm
.yarn/

# Runtime data
pids/
*.pid
*.seed
*.pid.lock

# Coverage directory used by tools like istanbul
coverage/
*.lcov

# nyc test coverage
.nyc_output

# Build outputs
dist/
build/
out/

# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

`;
        break;
        
      case 'react':
        content += `# React
node_modules/
build/
dist/
.env.local
.env.development.local
.env.test.local
.env.production.local

# React specific
.eslintcache

`;
        break;
        
      case 'python':
        content += `# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
ENV/
env.bak/
venv.bak/
.venv

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

`;
        break;
    }
    
    // OS-specific ignores
    if (config.includeOS) {
      content += `# Operating Systems
# macOS
.DS_Store
.AppleDouble
.LSOverride
Icon?
._*
.Spotlight-V100
.Trashes

# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.cab
*.msi
*.msm
*.msp
*.lnk

# Linux
*~
.fuse_hidden*
.directory
.Trash-*
.nfs*

`;
    }
    
    // IDE-specific ignores
    if (config.includeIDE) {
      content += `# IDEs and Editors
.vscode/
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

.idea/
*.swp
*.swo
*~

# Sublime Text
*.sublime-workspace

# Vim
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]

`;
    }
    
    // Common ignores
    content += `# Logs
logs/
*.log

# Temporary files
tmp/
temp/
.tmp/

# Cache
.cache/
.parcel-cache/

# Atlas MCP
.atlas/
.atlas

`;
    
    // Custom entries
    if (config.customEntries.length > 0) {
      content += `# Custom entries\n`;
      for (const entry of config.customEntries) {
        content += `${entry}\n`;
      }
      content += '\n';
    }
    
    return content;
  }

  static generateBranchProtectionInstructions(config: BranchProtectionConfig): string {
    return `
**For GitHub:**

1. Go to your repository settings
2. Click "Branches" in the left sidebar
3. Click "Add rule" or edit existing rule for \`${config.mainBranch}\`
4. Configure the following settings:

   ✅ **Require pull request reviews before merging**
   - Required approving reviews: ${config.requiredReviews}
   - Dismiss stale PR approvals when new commits are pushed

   ${config.requireStatusChecks ? '✅' : '❌'} **Require status checks to pass before merging**
   ${config.requireStatusChecks ? `   - ${config.requireUpToDate ? '✅' : '❌'} Require branches to be up to date before merging` : ''}

   ${config.restrictPush ? '✅' : '❌'} **Restrict pushes to matching branches**
   ${config.restrictPush ? '   - Include administrators: ❌ (recommended)' : ''}

   ✅ **Require conversation resolution before merging**

**For GitLab:**

1. Go to Settings > Repository
2. Expand "Push Rules"
3. Configure branch protection for \`${config.mainBranch}\`:
   - Allowed to merge: Developers + Maintainers
   - Allowed to push: No one (force MR workflow)

**For Bitbucket:**

1. Go to Repository settings > Branch permissions
2. Add restriction for \`${config.mainBranch}\`:
   - Restrict pushes: ✅
   - Restrict merges: ✅
   - Require approvals: ${config.requiredReviews}
`;
  }
}