import type { PilotDeckHookEvent } from "../protocol/events.js";
import { parseHookOutput } from "./parseHookOutput.js";
import type { PilotDeckHookOutput } from "../protocol/output.js";

export type PendingAsyncHook = {
  id: string;
  startedAt: Date;
  hookName: string;
  hookEvent: PilotDeckHookEvent;
  stdout: string;
  stderr: string;
  responseDelivered: boolean;
  asyncRewake?: boolean;
};

export type AsyncHookResponse = {
  id: string;
  hookName: string;
  hookEvent: PilotDeckHookEvent;
  stdout: string;
  stderr: string;
  output: PilotDeckHookOutput;
  rewake: boolean;
};

export class AsyncHookRegistry {
  private readonly hooks = new Map<string, PendingAsyncHook>();

  register(hook: PendingAsyncHook): void {
    this.hooks.set(hook.id, hook);
  }

  list(): PendingAsyncHook[] {
    return [...this.hooks.values()];
  }

  collectResponses(): AsyncHookResponse[] {
    const responses: AsyncHookResponse[] = [];
    for (const hook of this.hooks.values()) {
      if (hook.responseDelivered || !hook.stdout.trim()) {
        continue;
      }
      const output = parseHookOutput(hook.stdout);
      if (output.type === "async") {
        continue;
      }
      hook.responseDelivered = true;
      responses.push({
        id: hook.id,
        hookName: hook.hookName,
        hookEvent: hook.hookEvent,
        stdout: hook.stdout,
        stderr: hook.stderr,
        output,
        rewake: hook.asyncRewake === true && isBlockingOutput(output),
      });
    }
    return responses;
  }

  removeDelivered(): void {
    for (const hook of this.hooks.values()) {
      if (hook.responseDelivered) {
        this.hooks.delete(hook.id);
      }
    }
  }

  clear(): void {
    this.hooks.clear();
  }
}

function isBlockingOutput(output: PilotDeckHookOutput): boolean {
  return output.type === "sync" && (output.continue === false || output.decision === "block");
}