import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { Logger } from '../utils/logger.js';
import { LudusCliWrapper } from '../ludusMCP/cliWrapper.js';

export interface DeployRangeArgs {
  user?: string;
  configPath?: string;
  force?: boolean;
  tags?: string;           // --tags "tag1,tag2" 
  limit?: string;          // --limit "pattern"
  onlyRoles?: string;      // --only-roles "role1,role2"
  verboseAnsible?: boolean; // --verbose-ansible
  help?: boolean;          // --help
}

export function createDeployRangeTool(logger: Logger, cliWrapper: LudusCliWrapper): Tool {
  return {
    name: 'deploy_range',
    description: `Deploy a Ludus range from a configuration file. This creates a new virtualized training environment based on the specified configuration.

CREDENTIAL SECURITY REMINDER 
Ensure range configurations use credential placeholders: {{LudusCredName-<targetUser>-<credName>}}
DO NOT deploy ranges with non-range-specific credentials such as API keys for external services, passwords not specific to the cyber range environment, or similar credentials embedded in config files!

IMPORTANT LLM BEHAVIORAL PROMPTS:
- SAFETY FIRST: Ludus operations can be destructive and time-consuming
- VERIFY DESTRUCTIVE ACTIONS: Always confirm with user before destroy/delete operations  
- CHECK EXISTING STATE: Use list_user_ranges or get_range_status before major operations
- DESTRUCTION IS PERMANENT: Destroying ranges deletes all VMs and data irreversibly
- ADMIN vs USER: Admin operations (--user flag) affect other users' ranges - be explicit

DEPLOYMENT CONSIDERATIONS:
- Deployments take 10-45 minutes depending on complexity
- Windows domains take longer than simple Linux deployments  
- Users should monitor progress with get_range_status
- Failed deployments can be debugged with range logs

CRITICAL WORKFLOW REMINDER:
- deploy_range uses the currently SET configuration, not any specific file
- If deploying with a NEW config, you must first use set_range_config to make it active
- Typical workflow: write_range_config → validate_range_config → set_range_config → deploy_range`,
    inputSchema: {
      type: 'object',
      properties: {
        user: {
          type: 'string',
          description: 'User ID to deploy range for (admin only). If omitted, deploys for current user.'
        },
        configPath: {
          type: 'string',
          description: 'Path to range configuration YAML file. If omitted, uses existing configuration. ENSURE: Config must use credential placeholders {{LudusCredName-<user>-<cred>}}, NOT actual credentials!'
        },
        force: {
          type: 'boolean',
          description: 'Force deployment even if range already exists',
          default: false
        },
        tags: {
          type: 'string',
          description: 'Ansible tags to run for this deploy (comma-separated, e.g. "dns,custom-groups"). Default: all tags'
        },
        limit: {
          type: 'string', 
          description: 'Limit deployment to VMs matching the specified pattern (must include localhost or no plays will run)'
        },
        onlyRoles: {
          type: 'string',
          description: 'Limit user-defined roles to this comma-separated list (e.g. "role1,role2")'
        },
        verboseAnsible: {
          type: 'boolean',
          description: 'Enable verbose output from Ansible during deployment',
          default: false
        },
        help: {
          type: 'boolean',
          description: 'Show help information for the deploy_range command',
          default: false
        }
      },
      required: []
    }
  };
}

export async function handleDeployRange(
  args: DeployRangeArgs,
  logger: Logger,
  cliWrapper: LudusCliWrapper
): Promise<any> {
  const { 
    user, 
    configPath, 
    force = false, 
    tags, 
    limit, 
    onlyRoles, 
    verboseAnsible = false,
    help = false 
  } = args;

  // Handle help request
  if (help) {
    logger.info('Getting help for deploy_range command', { user });
    const result = await cliWrapper.executeArbitraryCommand('range', ['deploy', '--help']);
    
    if (result.success) {
      return {
        success: true,
        message: 'Help information for deploy_range command',
        help: true,
        content: result.rawOutput || result.message
      };
    } else {
      throw new Error(`Failed to get help: ${result.message}`);
    }
  }

  try {
    logger.info('Starting range deployment', { 
      user, 
      configPath, 
      force, 
      tags, 
      limit, 
      onlyRoles, 
      verboseAnsible 
    });

    // Deploy the range with all options (deployRange handles config setting internally)
    logger.info('Deploying range');
    
    // Build options object, filtering out undefined values
    const deployOptions: any = { force, verboseAnsible };
    if (user !== undefined) deployOptions.user = user;
    if (configPath !== undefined) deployOptions.configPath = configPath;
    if (tags !== undefined) deployOptions.tags = tags;
    if (limit !== undefined) deployOptions.limit = limit;
    if (onlyRoles !== undefined) deployOptions.onlyRoles = onlyRoles;
    
    const deployResult = await cliWrapper.deployRange(deployOptions);

    if (!deployResult.success) {
      throw new Error(`Deployment failed: ${deployResult.message}`);
    }

    const successMessage = user 
      ? `Range deployment initiated for user ${user}`
      : 'Range deployment initiated for current user';

    return {
      success: true,
      message: successMessage,
      details: deployResult.data,
      user: user || 'current',
      configPath: configPath || 'existing configuration',
      rawOutput: deployResult.rawOutput
    };

  } catch (error: any) {
    logger.error('Range deployment failed', { 
      user, 
      configPath, 
      error: error.message 
    });

    return {
      success: false,
      message: error.message,
      user: user || 'current',
      configPath: configPath || 'existing configuration'
    };
  }
} 