/**
 * OpenCode Notification Plugin - TypeScript Version
 * Uses session.idle event to detect when AI completes and extracts session title
 */

import type { Plugin } from "@opencode-ai/plugin";

export const NotificationPlugin: Plugin = async ({
  project,
  client,
  $,
  directory,
}) => {
  const config = {
    enabled: true,
    sound: true,
    minInterval: 10000,
    maxSummaryLength: 200,
  };

  // Early exit if disabled
  if (!config.enabled) {
    client.app
      .log({
        body: {
          service: "notification-plugin",
          level: "info",
          message: `🔕 Notification Plugin disabled`,
        },
      })
      .catch(() => {});
    return {};
  }

  // Log plugin initialization (non-blocking - don't await during init)
  client.app
    .log({
      body: {
        service: "notification-plugin",
        level: "info",
        message: `🔔 Notification Plugin loaded for: ${project?.id || directory}`,
      },
    })
    .catch(() => {}); // Non-blocking with error handling

  const notify = async (summary: string): Promise<void> => {
    if (!summary || summary.length < 3) return;

    try {
      // Use OpenCode toast notification (proper SDK way)
      client.tui
        .showToast({
          body: { message: summary, variant: "success" },
        })
        .catch(() => {});

      // Also use native notification as backup
      if (process.platform === "darwin") {
        // Escape special characters for AppleScript
        const escapedSummary = summary
          .replace(/\\/g, "\\\\")
          .replace(/"/g, '\\"')
          .replace(/'/g, "'\\''");

         $`osascript -e 'display notification "${escapedSummary}" with title "OpenCode"'`.catch(() => {});
        // Play sound asynchronously to avoid blocking
        $`afplay /System/Library/Sounds/Glass.aiff`.catch(() => {});
      } else {
        // Linux notification
        $`notify-send "OpenCode" "${summary}"`.catch(() => {});
        // $`paplay /usr/share/sounds/alsa/Front_Right.wav`.catch(() => {});
      }

      // Log success (non-blocking)
      client.app
        .log({
          body: {
            service: "notification-plugin",
            level: "info",
            message: `✅ Notification sent: ${summary.slice(0, 50)}...`,
          },
        })
        .catch(() => {});
    } catch (error) {
      // Log error (non-blocking)
      client.app
        .log({
          body: {
            service: "notification-plugin",
            level: "warn",
            message: `⚠️ Notification failed: ${(error as Error).message}`,
          },
        })
        .catch(() => {});
    }
  };

  // Event throttling + deduplication with proper types
  let processedEvents = new Set<string>();
  let lastNotificationTime = 0;

  return {
    event: async ({ event }) => {
      try {
        const now = Date.now();

        // Handle session completion via session.idle event
        // This fires when the AI agent finishes and session summary is generated
        if (event.type === "session.idle") {
          const sessionId = event.properties?.sessionID;
          const eventId = `session-idle-${sessionId}-${now}`;

          // Prevent duplicate notifications (10 second minimum)
          if (now - lastNotificationTime < 10000) return;
          if (processedEvents.has(eventId)) return;
          processedEvents.add(eventId);
          lastNotificationTime = now;

          // Try to get session summary via SDK with detailed logging
          setTimeout(async () => {
            try {
              let summary = "Session completed";

              // Log debug info
              client.app
                .log({
                  body: {
                    service: "notification-plugin",
                    level: "info",
                    message: `🔍 Attempting to get summary for session: ${sessionId}`,
                  },
                })
                .catch(() => {});

              // Method 1: Get message.summary.body from last user message
              // Retry up to 3 times with delays to wait for summary generation
              let retries = 3;
              let retryDelay = 1000; // Start with 1 second

              while (retries > 0 && summary === "Session completed") {
                try {
                  const messagesResponse = await client.session.messages({
                    path: { id: sessionId },
                  });

                  if (
                    messagesResponse.data &&
                    Array.isArray(messagesResponse.data)
                  ) {
                    // Get the last user message
                    const lastUserMessage = messagesResponse.data
                      .filter((m) => m.info.role === "user")
                      .pop();

                    if (
                      lastUserMessage?.info?.summary &&
                      typeof lastUserMessage.info.summary === "object" &&
                      lastUserMessage.info.summary.body
                    ) {
                      summary = lastUserMessage.info.summary.body
                        .trim()
                        .slice(0, 200);

                      client.app
                        .log({
                          body: {
                            service: "notification-plugin",
                            level: "info",
                            message: `✅ Using message.summary.body: ${summary}`,
                          },
                        })
                        .catch(() => {});
                      break; // Found summary, exit retry loop
                    } else if (
                      retries === 1 &&
                      lastUserMessage?.info?.summary &&
                      typeof lastUserMessage.info.summary === "object" &&
                      lastUserMessage.info.summary.title
                    ) {
                      // Use title only on last retry if body not available
                      summary = lastUserMessage.info.summary.title
                        .trim()
                        .slice(0, 200);

                      client.app
                        .log({
                          body: {
                            service: "notification-plugin",
                            level: "info",
                            message: `📋 Using message.summary.title: ${summary}`,
                          },
                        })
                        .catch(() => {});
                      break;
                    }
                  }

                  // Wait before retry
                  if (retries > 1) {
                    await new Promise((resolve) =>
                      setTimeout(resolve, retryDelay),
                    );
                    retryDelay *= 1.5; // Exponential backoff
                  }
                } catch (messagesError) {
                  client.app
                    .log({
                      body: {
                        service: "notification-plugin",
                        level: "warn",
                        message: `⚠️ Messages fetch failed (retry ${4 - retries}): ${(messagesError as Error).message}`,
                      },
                    })
                    .catch(() => {});
                }

                retries--;
              }

              await notify(summary);
            } catch (error) {
              client.app
                .log({
                  body: {
                    service: "notification-plugin",
                    level: "error",
                    message: `❌ Notification error: ${(error as Error).message}`,
                  },
                })
                .catch(() => {});
              await notify("Session completed");
            }
          }, 3000); // Initial delay before first retry attempt

          // Cleanup processed events to prevent memory leak
          if (processedEvents.size > 10) {
            processedEvents.clear();
          }
          return;
        }
      } catch (error) {
        // Log event handling errors (non-blocking)
        client.app
          .log({
            body: {
              service: "notification-plugin",
              level: "error",
              message: `❌ Event handling failed: ${(error as Error).message}`,
            },
          })
          .catch(() => {});
      }
    },
  };
};
