import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { ConfigManager } from '../../config/config-manager.js';
import { RepoTemplates } from './templates.js';
import { GitHubActionsTemplate, GitLabCITemplate, RepoConfig } from './types.js';
import { promises as fs } from 'fs';
import path from 'path';

let configManager: ConfigManager;

export async function setupRepositoryTools(server: Server, config?: ConfigManager) {
  configManager = config || new ConfigManager();

  server.setRequestHandler(CallToolRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;

    if (!args) {
      throw new Error('No arguments provided');
    }

    switch (name) {
      case 'setup_git_repository': {
        const { 
          platform = 'github',
          includeCI = true,
          includeLinting = true,
          includePreCommit = true,
          branchProtection = true,
          projectType = 'node'
        } = args as {
          platform?: string;
          includeCI?: boolean;
          includeLinting?: boolean;
          includePreCommit?: boolean;
          branchProtection?: boolean;
          projectType?: string;
        };

        try {
          const storageManager = configManager.getStorageManager();
          storageManager.validateNotInAtlasRepo();

          const config: RepoConfig = {
            platform,
            includeCI,
            includeLinting,
            includePreCommit,
            branchProtection,
            projectType,
          };

          const setupResults = await setupRepository(config);

          return {
            content: [
              {
                type: 'text',
                text: `✅ Repository setup complete!

📋 Configuration:
• Platform: ${platform}
• CI/CD: ${includeCI ? '✅ Enabled' : '❌ Disabled'}
• Linting: ${includeLinting ? '✅ Enabled' : '❌ Disabled'}
• Pre-commit hooks: ${includePreCommit ? '✅ Enabled' : '❌ Disabled'}
• Branch protection: ${branchProtection ? '✅ Recommended' : '❌ Not configured'}

📄 Files created:
${setupResults.filesCreated.map(file => `• ${file}`).join('\n')}

${setupResults.nextSteps.length > 0 ? `
🚀 Next steps:
${setupResults.nextSteps.map((step, i) => `${i + 1}. ${step}`).join('\n')}` : ''}`,
              },
            ],
            structured: {
              platform,
              filesCreated: setupResults.filesCreated,
              nextSteps: setupResults.nextSteps,
              config,
            },
          };
        } catch (error) {
          return {
            content: [
              {
                type: 'text',
                text: `❌ Error setting up repository: ${(error as Error).message}`,
              },
            ],
          };
        }
      }

      case 'generate_github_actions': {
        const { 
          workflowType = 'ci',
          nodeVersion = '18',
          includeTests = true,
          includeLinting = true,
          includeSecurity = true,
          deployTarget,
        } = args as {
          workflowType?: string;
          nodeVersion?: string;
          includeTests?: boolean;
          includeLinting?: boolean;
          includeSecurity?: boolean;
          deployTarget?: string;
        };

        try {
          const template = RepoTemplates.getGitHubActionsTemplate(workflowType as any);
          if (!template) {
            const available = RepoTemplates.getAvailableGitHubTemplates();
            return {
              content: [
                {
                  type: 'text',
                  text: `❌ Workflow type "${workflowType}" not found.\n\nAvailable types: ${available.join(', ')}`,
                },
              ],
            };
          }

          const variables = {
            nodeVersion,
            includeTests: includeTests.toString(),
            includeLinting: includeLinting.toString(),
            includeSecurity: includeSecurity.toString(),
            deployTarget: deployTarget || '',
          };

          const workflowContent = RepoTemplates.processTemplate(template.content, variables);
          const workflowPath = path.join(process.cwd(), '.github', 'workflows', `${workflowType}.yml`);

          await fs.mkdir(path.dirname(workflowPath), { recursive: true });
          await fs.writeFile(workflowPath, workflowContent);

          return {
            content: [
              {
                type: 'text',
                text: `✅ GitHub Actions workflow created!

📄 File: .github/workflows/${workflowType}.yml
🔧 Template: ${template.name}
📋 Description: ${template.description}

⚙️ Configuration:
• Node.js version: ${nodeVersion}
• Tests: ${includeTests ? '✅' : '❌'}
• Linting: ${includeLinting ? '✅' : '❌'}
• Security scanning: ${includeSecurity ? '✅' : '❌'}
${deployTarget ? `• Deploy target: ${deployTarget}` : ''}

🚀 The workflow will run on:
${template.triggers.map(trigger => `• ${trigger}`).join('\n')}`,
              },
            ],
            structured: {
              workflowType,
              filePath: `.github/workflows/${workflowType}.yml`,
              template: template.name,
              configuration: variables,
            },
          };
        } catch (error) {
          return {
            content: [
              {
                type: 'text',
                text: `❌ Error creating GitHub Actions workflow: ${(error as Error).message}`,
              },
            ],
          };
        }
      }

      case 'setup_pre_commit_hooks': {
        const { 
          includeESLint = true,
          includePrettier = true,
          includeTypeCheck = true,
          includeTests = false,
          customHooks = []
        } = args as {
          includeESLint?: boolean;
          includePrettier?: boolean;
          includeTypeCheck?: boolean;
          includeTests?: boolean;
          customHooks?: string[];
        };

        try {
          const config = {
            includeESLint,
            includePrettier,
            includeTypeCheck,
            includeTests,
            customHooks,
          };

          const hookConfig = RepoTemplates.generatePreCommitConfig(config);
          const huskyConfig = RepoTemplates.generateHuskyConfig(config);

          // Create .pre-commit-config.yaml
          await fs.writeFile(
            path.join(process.cwd(), '.pre-commit-config.yaml'),
            hookConfig
          );

          // Create husky configuration
          await fs.mkdir(path.join(process.cwd(), '.husky'), { recursive: true });
          await fs.writeFile(
            path.join(process.cwd(), '.husky', 'pre-commit'),
            huskyConfig,
            { mode: 0o755 }
          );

          const nextSteps = [
            'npm install --save-dev husky',
            'npm install --save-dev pre-commit',
            'npx husky install',
          ];

          if (includeESLint) nextSteps.push('Ensure ESLint is configured in your project');
          if (includePrettier) nextSteps.push('Ensure Prettier is configured in your project');

          return {
            content: [
              {
                type: 'text',
                text: `✅ Pre-commit hooks configured!

📄 Files created:
• .pre-commit-config.yaml
• .husky/pre-commit

⚙️ Configuration:
• ESLint: ${includeESLint ? '✅' : '❌'}
• Prettier: ${includePrettier ? '✅' : '❌'}
• TypeScript check: ${includeTypeCheck ? '✅' : '❌'}
• Test runner: ${includeTests ? '✅' : '❌'}
${customHooks.length > 0 ? `• Custom hooks: ${customHooks.join(', ')}` : ''}

🚀 Next steps:
${nextSteps.map((step, i) => `${i + 1}. ${step}`).join('\n')}`,
              },
            ],
            structured: {
              filesCreated: ['.pre-commit-config.yaml', '.husky/pre-commit'],
              configuration: config,
              nextSteps,
            },
          };
        } catch (error) {
          return {
            content: [
              {
                type: 'text',
                text: `❌ Error setting up pre-commit hooks: ${(error as Error).message}`,
              },
            ],
          };
        }
      }

      case 'generate_gitignore': {
        const { 
          projectType = 'node',
          includeOS = true,
          includeIDE = true,
          customEntries = []
        } = args as {
          projectType?: string;
          includeOS?: boolean;
          includeIDE?: boolean;
          customEntries?: string[];
        };

        try {
          const gitignoreContent = RepoTemplates.generateGitignore({
            projectType,
            includeOS,
            includeIDE,
            customEntries,
          });

          const gitignorePath = path.join(process.cwd(), '.gitignore');
          
          // Check if .gitignore already exists
          let existingContent = '';
          try {
            existingContent = await fs.readFile(gitignorePath, 'utf-8');
          } catch {
            // File doesn't exist, which is fine
          }

          let finalContent = gitignoreContent;
          if (existingContent) {
            finalContent = `${existingContent}\n\n# Generated by Atlas MCP\n${gitignoreContent}`;
          }

          await fs.writeFile(gitignorePath, finalContent);

          return {
            content: [
              {
                type: 'text',
                text: `✅ .gitignore ${existingContent ? 'updated' : 'created'}!

📋 Project type: ${projectType}
⚙️ Includes:
• OS-specific files: ${includeOS ? '✅' : '❌'}
• IDE files: ${includeIDE ? '✅' : '❌'}
${customEntries.length > 0 ? `• Custom entries: ${customEntries.length}` : ''}

📄 File: .gitignore
${existingContent ? 'ℹ️ Existing content preserved and new rules appended.' : ''}`,
              },
            ],
            structured: {
              projectType,
              includeOS,
              includeIDE,
              customEntries,
              wasUpdated: !!existingContent,
            },
          };
        } catch (error) {
          return {
            content: [
              {
                type: 'text',
                text: `❌ Error generating .gitignore: ${(error as Error).message}`,
              },
            ],
          };
        }
      }

      case 'setup_branch_protection': {
        const { 
          mainBranch = 'main',
          requiredReviews = 1,
          requireStatusChecks = true,
          requireUpToDate = true,
          restrictPush = true
        } = args as {
          mainBranch?: string;
          requiredReviews?: number;
          requireStatusChecks?: boolean;
          requireUpToDate?: boolean;
          restrictPush?: boolean;
        };

        const config = {
          mainBranch,
          requiredReviews,
          requireStatusChecks,
          requireUpToDate,
          restrictPush,
        };

        const instructions = RepoTemplates.generateBranchProtectionInstructions(config);

        return {
          content: [
            {
              type: 'text',
              text: `🛡️ Branch Protection Setup Instructions

Since branch protection rules must be configured on the repository platform,
here are the instructions for ${mainBranch} branch:

${instructions}

⚙️ Recommended settings:
• Required reviewers: ${requiredReviews}
• Require status checks: ${requireStatusChecks ? '✅' : '❌'}
• Require up-to-date branches: ${requireUpToDate ? '✅' : '❌'}
• Restrict push access: ${restrictPush ? '✅' : '❌'}

💡 These settings help ensure code quality and prevent accidental changes to your main branch.`,
            },
          ],
          structured: {
            config,
            instructions,
          },
        };
      }

      default:
        return null as any;
    }
  });

  return {
    tools: [
      {
        name: 'setup_git_repository',
        description: 'Set up a Git repository with best practices, CI/CD, and security',
        inputSchema: {
          type: 'object',
          properties: {
            platform: { 
              type: 'string', 
              enum: ['github', 'gitlab', 'bitbucket'],
              default: 'github',
              description: 'Git platform'
            },
            includeCI: { 
              type: 'boolean', 
              default: true,
              description: 'Include CI/CD workflows'
            },
            includeLinting: { 
              type: 'boolean', 
              default: true,
              description: 'Include linting configuration'
            },
            includePreCommit: { 
              type: 'boolean', 
              default: true,
              description: 'Include pre-commit hooks'
            },
            branchProtection: { 
              type: 'boolean', 
              default: true,
              description: 'Generate branch protection recommendations'
            },
            projectType: {
              type: 'string',
              enum: ['node', 'python', 'react', 'vue', 'angular', 'generic'],
              default: 'node',
              description: 'Project type for specific configurations'
            },
          },
          required: [],
        },
      },
      {
        name: 'generate_github_actions',
        description: 'Generate GitHub Actions workflow files',
        inputSchema: {
          type: 'object',
          properties: {
            workflowType: {
              type: 'string',
              enum: ['ci', 'cd', 'security', 'release', 'test'],
              default: 'ci',
              description: 'Type of workflow to generate'
            },
            nodeVersion: {
              type: 'string',
              default: '18',
              description: 'Node.js version for the workflow'
            },
            includeTests: { type: 'boolean', default: true },
            includeLinting: { type: 'boolean', default: true },
            includeSecurity: { type: 'boolean', default: true },
            deployTarget: {
              type: 'string',
              description: 'Deployment target (e.g., vercel, netlify, aws)'
            },
          },
          required: [],
        },
      },
      {
        name: 'setup_pre_commit_hooks',
        description: 'Configure pre-commit hooks for code quality',
        inputSchema: {
          type: 'object',
          properties: {
            includeESLint: { type: 'boolean', default: true },
            includePrettier: { type: 'boolean', default: true },
            includeTypeCheck: { type: 'boolean', default: true },
            includeTests: { type: 'boolean', default: false },
            customHooks: {
              type: 'array',
              items: { type: 'string' },
              description: 'Custom hook commands'
            },
          },
          required: [],
        },
      },
      {
        name: 'generate_gitignore',
        description: 'Generate or update .gitignore file',
        inputSchema: {
          type: 'object',
          properties: {
            projectType: {
              type: 'string',
              enum: ['node', 'python', 'react', 'vue', 'angular', 'java', 'csharp', 'generic'],
              default: 'node',
              description: 'Project type for specific ignore rules'
            },
            includeOS: { 
              type: 'boolean', 
              default: true,
              description: 'Include OS-specific files (macOS, Windows, Linux)'
            },
            includeIDE: { 
              type: 'boolean', 
              default: true,
              description: 'Include IDE files (VSCode, IntelliJ, etc.)'
            },
            customEntries: {
              type: 'array',
              items: { type: 'string' },
              description: 'Custom entries to add'
            },
          },
          required: [],
        },
      },
      {
        name: 'setup_branch_protection',
        description: 'Generate instructions for setting up branch protection rules',
        inputSchema: {
          type: 'object',
          properties: {
            mainBranch: { 
              type: 'string', 
              default: 'main',
              description: 'Main branch name'
            },
            requiredReviews: { 
              type: 'number', 
              default: 1,
              description: 'Number of required reviewers'
            },
            requireStatusChecks: { type: 'boolean', default: true },
            requireUpToDate: { type: 'boolean', default: true },
            restrictPush: { type: 'boolean', default: true },
          },
          required: [],
        },
      },
    ],
    resources: [],
  };
}

async function setupRepository(config: RepoConfig): Promise<{
  filesCreated: string[];
  nextSteps: string[];
}> {
  const filesCreated: string[] = [];
  const nextSteps: string[] = [];

  // Initialize git if not already initialized
  try {
    await fs.access(path.join(process.cwd(), '.git'));
  } catch {
    nextSteps.push('Run "git init" to initialize the repository');
    nextSteps.push('Run "git add ." and "git commit -m "Initial commit"');
  }

  // Generate .gitignore
  if (config.includeLinting || config.projectType !== 'generic') {
    const gitignoreContent = RepoTemplates.generateGitignore({
      projectType: config.projectType,
      includeOS: true,
      includeIDE: true,
      customEntries: ['.atlas/', '.atlas'],
    });

    const gitignorePath = path.join(process.cwd(), '.gitignore');
    try {
      const existing = await fs.readFile(gitignorePath, 'utf-8');
      if (!existing.includes('.atlas')) {
        await fs.writeFile(gitignorePath, `${existing}\n\n${gitignoreContent}`);
        filesCreated.push('.gitignore (updated)');
      }
    } catch {
      await fs.writeFile(gitignorePath, gitignoreContent);
      filesCreated.push('.gitignore');
    }
  }

  // Generate CI/CD workflows
  if (config.includeCI) {
    if (config.platform === 'github') {
      const ciTemplate = RepoTemplates.getGitHubActionsTemplate('ci');
      if (ciTemplate) {
        const workflowPath = path.join(process.cwd(), '.github', 'workflows', 'ci.yml');
        await fs.mkdir(path.dirname(workflowPath), { recursive: true });
        
        const content = RepoTemplates.processTemplate(ciTemplate.content, {
          nodeVersion: '18',
          includeTests: 'true',
          includeLinting: config.includeLinting.toString(),
          includeSecurity: 'true',
        });
        
        await fs.writeFile(workflowPath, content);
        filesCreated.push('.github/workflows/ci.yml');
      }
    }
  }

  // Setup pre-commit hooks
  if (config.includePreCommit) {
    const hookConfig = RepoTemplates.generatePreCommitConfig({
      includeESLint: config.includeLinting,
      includePrettier: config.includeLinting,
      includeTypeCheck: true,
      includeTests: false,
      customHooks: [],
    });

    await fs.writeFile(path.join(process.cwd(), '.pre-commit-config.yaml'), hookConfig);
    filesCreated.push('.pre-commit-config.yaml');

    nextSteps.push('Install pre-commit: npm install --save-dev husky pre-commit');
    nextSteps.push('Initialize husky: npx husky install');
  }

  // Add platform-specific instructions
  if (config.branchProtection) {
    nextSteps.push(`Configure branch protection rules on ${config.platform} for the main branch`);
  }

  if (config.platform === 'github') {
    nextSteps.push('Create repository on GitHub and add remote: git remote add origin <url>');
  }

  return { filesCreated, nextSteps };
}