/**
 * iTerm2 Terminal Adapter
 *
 * Implements the TerminalAdapter interface for iTerm2 terminal emulator.
 * Uses AppleScript for all operations.
 */

import { spawnSync } from "node:child_process";
import type { SpawnOptions, TerminalAdapter } from "../utils/terminal-adapter";

/**
 * Context needed for iTerm2 spawning (tracks last pane for layout)
 */
export interface Iterm2SpawnContext {
  /** ID of the last spawned session, used for layout decisions */
  lastSessionId?: string;
}

export class Iterm2Adapter implements TerminalAdapter {
  readonly name = "iTerm2";
  private spawnContext: Iterm2SpawnContext = {};

  detect(): boolean {
    return (
      process.env.TERM_PROGRAM === "iTerm.app" &&
      !process.env.TMUX &&
      !process.env.ZELLIJ
    );
  }

  /**
   * Helper to execute AppleScript via stdin to avoid escaping issues with -e
   */
  private runAppleScript(script: string): {
    stdout: string;
    stderr: string;
    status: number | null;
  } {
    const result = spawnSync("osascript", ["-"], {
      input: script,
      encoding: "utf-8",
    });
    return {
      stdout: result.stdout?.toString() ?? "",
      stderr: result.stderr?.toString() ?? "",
      status: result.status,
    };
  }

  spawn(options: SpawnOptions): string {
    const envStr = Object.entries(options.env)
      .filter(([k]) => k.startsWith("PI_"))
      .map(([k, v]) => `${k}=${v}`)
      .join(" ");

    const itermCmd = `cd '${options.cwd}' && ${envStr} ${options.command}`;
    const escapedCmd = itermCmd.replace(/"/g, '\\"');

    let script: string;

    if (!this.spawnContext.lastSessionId) {
      script = `tell application "iTerm2"
  tell current session of current window
    set newSession to split vertically with default profile
    tell newSession
      write text "${escapedCmd}"
      return id
    end tell
  end tell
end tell`;
    } else {
      script = `tell application "iTerm2"
  repeat with aWindow in windows
    repeat with aTab in tabs of aWindow
      repeat with aSession in sessions of aTab
        if id of aSession is "${this.spawnContext.lastSessionId}" then
          tell aSession
            set newSession to split horizontally with default profile
            tell newSession
              write text "${escapedCmd}"
              return id
            end tell
          end tell
        end if
      end repeat
    end repeat
  end repeat
end tell`;
    }

    const result = this.runAppleScript(script);

    if (result.status !== 0) {
      throw new Error(
        `osascript failed with status ${result.status}: ${result.stderr}`,
      );
    }

    const sessionId = result.stdout.toString().trim();
    this.spawnContext.lastSessionId = sessionId;

    return `iterm_${sessionId}`;
  }

  kill(paneId: string): void {
    if (
      !paneId ||
      !paneId.startsWith("iterm_") ||
      paneId.startsWith("iterm_win_")
    ) {
      return;
    }

    const itermId = paneId.replace("iterm_", "");
    const script = `tell application "iTerm2"
  repeat with aWindow in windows
    repeat with aTab in tabs of aWindow
      repeat with aSession in sessions of aTab
        if id of aSession is "${itermId}" then
          close aSession
          return "Closed"
        end if
      end repeat
    end repeat
  end repeat
end tell`;

    try {
      this.runAppleScript(script);
    } catch {
      // Ignore errors
    }
  }

  isAlive(paneId: string): boolean {
    if (
      !paneId ||
      !paneId.startsWith("iterm_") ||
      paneId.startsWith("iterm_win_")
    ) {
      return false;
    }

    const itermId = paneId.replace("iterm_", "");
    const script = `tell application "iTerm2"
  repeat with aWindow in windows
    repeat with aTab in tabs of aWindow
      repeat with aSession in sessions of aTab
        if id of aSession is "${itermId}" then
          return "Alive"
        end if
      end repeat
    end repeat
  end repeat
end tell`;

    try {
      const result = this.runAppleScript(script);
      return result.stdout.includes("Alive");
    } catch {
      return false;
    }
  }

  setTitle(title: string): void {
    const escapedTitle = title.replace(/"/g, '\\"');
    const script = `tell application "iTerm2" to tell current session of current window
      set name to "${escapedTitle}"
    end tell`;
    try {
      this.runAppleScript(script);
    } catch {
      // Ignore errors
    }
  }

  /**
   * iTerm2 supports spawning separate OS windows via AppleScript
   */
  supportsWindows(): boolean {
    return true;
  }

  /**
   * Spawn a new separate OS window with the given options.
   */
  spawnWindow(options: SpawnOptions): string {
    const envStr = Object.entries(options.env)
      .filter(([k]) => k.startsWith("PI_"))
      .map(([k, v]) => `${k}=${v}`)
      .join(" ");

    const itermCmd = `cd '${options.cwd}' && ${envStr} ${options.command}`;
    const escapedCmd = itermCmd.replace(/"/g, '\\"');

    const windowTitle = options.teamName
      ? `${options.teamName}: ${options.name}`
      : options.name;

    const escapedTitle = windowTitle.replace(/"/g, '\\"');

    const script = `tell application "iTerm2"
  set newWindow to (create window with default profile)
  tell current session of newWindow
    -- Set the session name (tab title)
    set name to "${escapedTitle}"
    -- Set window title via escape sequence (OSC 2)
    -- We use double backslashes for AppleScript to emit a single backslash to the shell
    write text "printf '\\\\033]2;${escapedTitle}\\\\007'"
    -- Execute the command
    write text "cd '${options.cwd}' && ${escapedCmd}"
    return id of newWindow
  end tell
end tell`;

    const result = this.runAppleScript(script);

    if (result.status !== 0) {
      throw new Error(
        `osascript failed with status ${result.status}: ${result.stderr}`,
      );
    }

    const windowId = result.stdout.toString().trim();
    return `iterm_win_${windowId}`;
  }

  /**
   * Set the title of a specific window.
   */
  setWindowTitle(windowId: string, title: string): void {
    if (!windowId || !windowId.startsWith("iterm_win_")) {
      return;
    }

    const itermId = windowId.replace("iterm_win_", "");
    const escapedTitle = title.replace(/"/g, '\\"');

    const script = `tell application "iTerm2"
  repeat with aWindow in windows
    if id of aWindow is "${itermId}" then
      tell current session of aWindow
        write text "printf '\\\\033]2;${escapedTitle}\\\\007'"
      end tell
      exit repeat
    end if
  end repeat
end tell`;

    try {
      this.runAppleScript(script);
    } catch {
      // Silently fail
    }
  }

  /**
   * Kill/terminate a window.
   */
  killWindow(windowId: string): void {
    if (!windowId || !windowId.startsWith("iterm_win_")) {
      return;
    }

    const itermId = windowId.replace("iterm_win_", "");
    const script = `tell application "iTerm2"
  repeat with aWindow in windows
    if id of aWindow is "${itermId}" then
      close aWindow
      return "Closed"
    end if
  end repeat
end tell`;

    try {
      this.runAppleScript(script);
    } catch {
      // Silently fail
    }
  }

  /**
   * Check if a window is still alive/active.
   */
  isWindowAlive(windowId: string): boolean {
    if (!windowId || !windowId.startsWith("iterm_win_")) {
      return false;
    }

    const itermId = windowId.replace("iterm_win_", "");
    const script = `tell application "iTerm2"
  repeat with aWindow in windows
    if id of aWindow is "${itermId}" then
      return "Alive"
    end if
  end repeat
end tell`;

    try {
      const result = this.runAppleScript(script);
      return result.stdout.includes("Alive");
    } catch {
      return false;
    }
  }

  /**
   * Set the spawn context (used to restore state when needed)
   */
  setSpawnContext(context: Iterm2SpawnContext): void {
    this.spawnContext = context;
  }

  /**
   * Get current spawn context (useful for persisting state)
   */
  getSpawnContext(): Iterm2SpawnContext {
    return { ...this.spawnContext };
  }
}
