import { handle } from '@astrojs/cloudflare/handler';
import { captureCaught } from '@/lib/observability';
import { DurableObject } from 'cloudflare:workers';

export class RenderDO extends DurableObject<Env> {
  #inflight: Promise<Response> | null = null;

  override async fetch(request: Request): Promise<Response> {
    const secret = (this.env as { RENDER_DO_SECRET?: string }).RENDER_DO_SECRET;
    const header = request.headers.get('x-md-render-do');

    if (!header || !secret || header !== secret) {
      return new Response('Forbidden', { status: 403 });
    }

    if (this.#inflight) {
      try {
        const shared = await this.#inflight;
        return shared.clone();
      } catch (coalesceErr) {
        captureCaught(coalesceErr, {
          scope: 'worker.render-do.coalesce',
          severity: 'info',
        });
      }
    }

    const renderPromise = this.#render(request);
    this.#inflight = renderPromise;
    try {
      const res = await renderPromise;
      return res.clone();
    } finally {
      this.#inflight = null;
    }
  }

  async #render(request: Request): Promise<Response> {
    const headers = new Headers(request.headers);
    headers.delete('x-md-render-do');
    headers.set('x-md-do-inner', '1');
    const cleanRequest = new Request(request.url, {
      method: request.method,
      headers,
      redirect: 'manual',
    });
    const ctx = {
      waitUntil: (promise: Promise<unknown>) => this.ctx.waitUntil(promise),
      passThroughOnException: () => {},
    } as ExecutionContext;

    const response = await handle(cleanRequest, this.env, ctx);
    const body = await response.arrayBuffer();
    return new Response(body, response);
  }
}
