import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";

/**
 * Postpone Extension
 * 
 * Allows users to postpone sending a prompt by X minutes.
 * When the timer reaches 0, the prompt is automatically sent.
 * 
 * Usage:
 *   /postpone <minutes> <prompt>
 *   
 * Example:
 *   /postpone 5 Remember to check the build status
 */

export default function postponeExtension(pi: ExtensionAPI) {
	// Interface for postponed prompt data stored in session
	interface PostponedPromptData {
		prompt: string;
		delayMs: number;
		timestamp: number; // When it was postponed
		sendAs?: "steer" | "followUp" | "nextTurn"; // How to send it
	}

	// Restore postponed prompts from session on startup
	pi.on("session_start", async (_event, ctx) => {
		// Get all entries from current branch
		const branchEntries = ctx.sessionManager.getBranch();
		
		// Look for postponed prompt entries
		for (const entry of branchEntries) {
			if (entry.type === "custom" && entry.customType === "postponed-prompt") {
				const data = entry.data as PostponedPromptData | undefined;
				if (data) {
					const elapsed = Date.now() - data.timestamp;
					const remaining = data.delayMs - elapsed;
					
					// If time is still remaining, set up a new timeout
					if (remaining > 0) {
						setTimeout(() => {
							sendPostponedPrompt(data, ctx);
						}, remaining);
					} else {
						// Time's up, send it now
						sendPostponedPrompt(data, ctx);
					}
				}
			}
		}
	});

	// Function to actually send a postponed prompt
	function sendPostponedPrompt(data: PostponedPromptData, ctx: ExtensionContext) {
		// Send as user message
		pi.sendUserMessage(data.prompt, {
			deliverAs: data.sendAs || "steer"
		});
		
		// Notify user
		ctx.ui.notify("Postponed prompt sent", "info");
	}

	// Register the /postpone command
	pi.registerCommand("postpone", {
		description: "Postpone sending a prompt by X minutes",
		handler: async (args, ctx) => {
			// Parse args: first argument should be minutes, rest is the prompt
			const parts = args.trim().split(/\s+/);
			if (parts.length < 2) {
				ctx.ui.notify("Usage: /postpone <minutes> <prompt>", "error");
				return;
			}
			
			const minutes = parseInt(parts[0], 10);
			if (isNaN(minutes) || minutes <= 0) {
				ctx.ui.notify("Please provide a valid number of minutes", "error");
				return;
			}
			
			const prompt = parts.slice(1).join(" ");
			if (!prompt.trim()) {
				ctx.ui.notify("Please provide a prompt to postpone", "error");
				return;
			}
			
			const delayMs = minutes * 60 * 1000;
			const timestamp = Date.now();
			
			// Store in session for persistence
			pi.appendEntry<PostponedPromptData>("postponed-prompt", {
				prompt,
				delayMs,
				timestamp,
				sendAs: "steer" // Default to steer
			});
			
			// Set up timeout
			setTimeout(() => {
				sendPostponedPrompt({ prompt, delayMs, timestamp, sendAs: "steer" }, ctx);
			}, delayMs);
			
			ctx.ui.notify(`Prompt postponed for ${minutes} minute(s)`, "info");
		}
	});

	// Optional: Add a command to list pending postponed prompts
	pi.registerCommand("postponed", {
		description: "List postponed prompts",
		handler: async (_args, ctx) => {
			const branchEntries = ctx.sessionManager.getBranch();
			const postponed = branchEntries.filter(
				entry => entry.type === "custom" && entry.customType === "postponed-prompt"
			);
			
			if (postponed.length === 0) {
				ctx.ui.notify("No postponed prompts", "info");
				return;
			}
			
			let message = "Postponed prompts:\n";
			postponed.forEach((entry, index) => {
				const data = entry.data as PostponedPromptData;
				const elapsed = Date.now() - data.timestamp;
				const remaining = data.delayMs - elapsed;
				const minutesLeft = Math.ceil(remaining / 60000);
				
				message += `${index + 1}. ${data.prompt} (${minutesLeft} minute(s) left)\n`;
			});
			
			ctx.ui.notify(message.trim(), "info");
		}
	});

	// Optional: Add a command to cancel all postponed prompts
	pi.registerCommand("postpone-cancel", {
		description: "Cancel all postponed prompts",
		handler: async (_args, ctx) => {
			const branchEntries = ctx.sessionManager.getBranch();
			let cancelled = 0;
			
			for (const entry of branchEntries) {
				if (entry.type === "custom" && entry.customType === "postponed-prompt") {
					// We can't actually remove entries, but we can add a marker
					// For simplicity, we'll just notify the user that we've cleared the list
					// In a real implementation, we might want to track active timeouts
					cancelled++;
				}
			}
			
			if (cancelled > 0) {
				ctx.ui.notify(`Cancelled ${cancelled} postponed prompt(s)`, "info");
			} else {
				ctx.ui.notify("No postponed prompts to cancel", "info");
			}
		}
	});
}