import type { CommandDefinition, CommandResult } from '../types.js';
import type { CommandRegistry } from '../registry.js';

function notAvailable(label: string): CommandResult {
  return {
    handled: true,
    text: `${label} is not available in this session.`,
  };
}

export function createHelpCommand(registry: CommandRegistry): CommandDefinition {
  return {
    name: 'help',
    description: 'Show available commands',
    execute: async () => {
      const lines = ['Available commands:'];
      for (const command of registry.list()) {
        const aliases = command.aliases && command.aliases.length > 0
          ? ` (aliases: ${command.aliases.map(alias => `/${alias}`).join(', ')})`
          : '';
        lines.push(`- /${command.name}: ${command.description}${aliases}`);
      }
      return {
        handled: true,
        text: lines.join('\n'),
      };
    },
  };
}

export function createStatusCommand(): CommandDefinition {
  return {
    name: 'status',
    description: 'Show current status',
    execute: async (_args, ctx) => {
      if (!ctx.services?.getStatus) {
        return {
          handled: true,
          text: 'Flynn is running.',
        };
      }

      return {
        handled: true,
        text: await ctx.services.getStatus(),
      };
    },
  };
}

export function createUsageCommand(): CommandDefinition {
  return {
    name: 'usage',
    description: 'Show token usage',
    execute: async (_args, ctx) => {
      if (!ctx.services?.getUsage) {
        return notAvailable('Usage command');
      }

      return {
        handled: true,
        text: await ctx.services.getUsage(),
      };
    },
  };
}

export function createModelCommand(): CommandDefinition {
  return {
    name: 'model',
    description: 'Show or change model tier',
    execute: async (args, ctx) => {
      if (args.length === 0) {
        if (!ctx.services?.getModel) {
          return notAvailable('Model command');
        }
        return {
          handled: true,
          text: await ctx.services.getModel(),
        };
      }

      if (!ctx.services?.setModel) {
        return notAvailable('Model command');
      }

      return {
        handled: true,
        // Pass through the full argument string so frontends can support
        // richer syntax like: /model <tier> <provider/model>
        text: await ctx.services.setModel(args.join(' ')),
      };
    },
  };
}

export function createCompactCommand(): CommandDefinition {
  return {
    name: 'compact',
    description: 'Compact conversation context',
    execute: async (_args, ctx) => {
      if (!ctx.services?.compact) {
        return notAvailable('Compact command');
      }

      return {
        handled: true,
        text: await ctx.services.compact(),
      };
    },
  };
}

export function createResetCommand(): CommandDefinition {
  return {
    name: 'reset',
    description: 'Reset current session',
    execute: async (_args, ctx) => {
      if (!ctx.services?.reset) {
        return notAvailable('Reset command');
      }

      return {
        handled: true,
        text: await ctx.services.reset(),
      };
    },
  };
}

export function createElevateCommand(): CommandDefinition {
  return {
    name: 'elevate',
    description: 'Enable or disable time-bounded elevated host mode',
    execute: async (args, ctx) => {
      if (args.length === 0) {
        if (!ctx.services?.getElevation) {
          return notAvailable('Elevate command');
        }
        return { handled: true, text: await ctx.services.getElevation() };
      }

      if (!ctx.services?.setElevation) {
        return notAvailable('Elevate command');
      }

      return { handled: true, text: await ctx.services.setElevation(args.join(' ')) };
    },
  };
}

export function registerBuiltinCommands(registry: CommandRegistry): void {
  registry.register(createHelpCommand(registry));
  registry.register(createStatusCommand());
  registry.register(createUsageCommand());
  registry.register(createModelCommand());
  registry.register(createCompactCommand());
  registry.register(createResetCommand());
  registry.register(createElevateCommand());
}
