import type { Tool, ToolResult } from '../types.js';
import type { CronScheduler } from '../../automation/cron.js';

/**
 * Creates cron management tools bound to the given CronScheduler.
 */
export function createCronTools(scheduler: CronScheduler): Tool[] {
  const cronList: Tool = {
    name: 'cron.list',
    description:
      'List all configured cron jobs with their names, schedules, and messages.',
    inputSchema: {
      type: 'object',
      properties: {},
    },
    execute: async (_rawArgs: unknown): Promise<ToolResult> => {
      try {
        const jobNames = scheduler.getJobNames();

        if (jobNames.length === 0) {
          return { success: true, output: 'No cron jobs configured.' };
        }

        const lines = jobNames.map((name) => {
          const job = scheduler.getJob(name);
          if (!job) {return `- ${name}`;}
          return `- **${name}** — schedule: \`${job.schedule}\`, enabled: ${job.enabled}, output: ${job.output.channel}/${job.output.peer}\n  message: "${job.message.length > 80 ? job.message.slice(0, 80) + '...' : job.message}"`;
        });
        return {
          success: true,
          output: `${jobNames.length} cron job(s):\n\n${lines.join('\n')}`,
        };
      } catch (error) {
        return {
          success: false,
          output: '',
          error: error instanceof Error ? error.message : String(error),
        };
      }
    },
  };

  const cronTrigger: Tool = {
    name: 'cron.trigger',
    description:
      'Manually trigger a cron job by name, executing it immediately regardless of its schedule.',
    inputSchema: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          description: 'Name of the cron job to trigger',
        },
      },
      required: ['name'],
    },
    execute: async (rawArgs: unknown): Promise<ToolResult> => {
      const args = rawArgs as { name: string };

      try {
        const jobNames = scheduler.getJobNames();
        if (!jobNames.includes(args.name)) {
          return {
            success: false,
            output: '',
            error: `Cron job "${args.name}" not found. Available: ${jobNames.join(', ')}`,
          };
        }

        scheduler.triggerJob(args.name);
        return {
          success: true,
          output: `Cron job "${args.name}" triggered.`,
        };
      } catch (error) {
        return {
          success: false,
          output: '',
          error: error instanceof Error ? error.message : String(error),
        };
      }
    },
  };

  const cronCreate: Tool = {
    name: 'cron.create',
    description:
      'Create a new cron job that sends a message on a schedule. The job starts immediately and runs until the daemon restarts (ephemeral). Use standard cron syntax for the schedule (e.g. "0 9 * * *" for daily at 9am, "*/30 * * * *" for every 30 minutes).',
    inputSchema: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          description: 'Unique name for the cron job (kebab-case, e.g. "apartment-check")',
        },
        schedule: {
          type: 'string',
          description: 'Cron schedule expression (e.g. "0 9 * * *" for daily at 9am, "0 */6 * * *" for every 6 hours)',
        },
        message: {
          type: 'string',
          description: 'The message to send when the job fires. This message will be processed as if a user sent it, so you can include instructions for yourself.',
        },
        output_channel: {
          type: 'string',
          description: 'Channel to send output to (e.g. "telegram", "discord", "slack"). Defaults to "cron" (responses stay in the cron session).',
        },
        output_peer: {
          type: 'string',
          description: 'Peer ID on the output channel (e.g. Telegram chat ID). Required if output_channel is set.',
        },
        timezone: {
          type: 'string',
          description: 'IANA timezone (e.g. "America/Los_Angeles"). Defaults to system timezone.',
        },
      },
      required: ['name', 'schedule', 'message'],
    },
    execute: async (rawArgs: unknown): Promise<ToolResult> => {
      const args = rawArgs as {
        name: string;
        schedule: string;
        message: string;
        output_channel?: string;
        output_peer?: string;
        timezone?: string;
      };

      try {
        // Validate name format
        if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/.test(args.name)) {
          return {
            success: false,
            output: '',
            error: 'Job name must be kebab-case (lowercase letters, numbers, and hyphens, not starting/ending with hyphen)',
          };
        }

        const outputChannel = args.output_channel ?? 'cron';
        const outputPeer = args.output_peer ?? args.name;

        const created = scheduler.addJob({
          name: args.name,
          schedule: args.schedule,
          message: args.message,
          output: {
            channel: outputChannel,
            peer: outputPeer,
          },
          enabled: true,
          timezone: args.timezone,
        });

        if (!created) {
          return {
            success: false,
            output: '',
            error: `Cron job "${args.name}" already exists. Use a different name or delete the existing one first.`,
          };
        }

        return {
          success: true,
          output: `Cron job "${args.name}" created and started.\nSchedule: ${args.schedule}${args.timezone ? ` (${args.timezone})` : ''}\nOutput: ${outputChannel}/${outputPeer}\nMessage: "${args.message}"\n\nNote: This job is ephemeral and will not persist across daemon restarts. To make it permanent, add it to the config file.`,
        };
      } catch (error) {
        return {
          success: false,
          output: '',
          error: error instanceof Error ? error.message : String(error),
        };
      }
    },
  };

  const cronDelete: Tool = {
    name: 'cron.delete',
    description:
      'Delete a cron job by name. Stops the job immediately. Only works for runtime-created jobs; config-defined jobs will reappear on restart.',
    inputSchema: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          description: 'Name of the cron job to delete',
        },
      },
      required: ['name'],
    },
    execute: async (rawArgs: unknown): Promise<ToolResult> => {
      const args = rawArgs as { name: string };

      try {
        const removed = scheduler.removeJob(args.name);
        if (!removed) {
          return {
            success: false,
            output: '',
            error: `Cron job "${args.name}" not found. Available: ${scheduler.getJobNames().join(', ')}`,
          };
        }

        return {
          success: true,
          output: `Cron job "${args.name}" deleted and stopped.`,
        };
      } catch (error) {
        return {
          success: false,
          output: '',
          error: error instanceof Error ? error.message : String(error),
        };
      }
    },
  };

  return [cronList, cronTrigger, cronCreate, cronDelete];
}
