/**
 * Page layout pointer queries.
 *
 * Entity-alarm law (§7): scheduling a page arms ScheduledPublishDO;
 * cancelling the schedule or publishing immediately disarms it.
 */

import { eq, and, isNotNull, lte } from 'drizzle-orm';
import type { DrizzleClient } from '../client.js';
import { pageLayoutPointers } from '../schema.js';
import type { ServiceBundle } from '@/server/services/types.js';
import { captureCaught } from '@/server/observability/capture.server.js';

export async function findByPage(db: DrizzleClient, page: string) {
  const [row] = await db
    .select()
    .from(pageLayoutPointers)
    .where(eq(pageLayoutPointers.page, page))
    .limit(1);
  return row ?? null;
}

export async function createLivePointer(
  db: DrizzleClient,
  page: string,
  liveVersionId: string,
): Promise<void> {
  await db.insert(pageLayoutPointers).values({ page, liveVersionId });
}

/**
 * Schedule a future publish: sets scheduledVersionId + scheduledAt and arms the DO alarm.
 */
export async function schedulePublish(
  db: DrizzleClient,
  services: Pick<ServiceBundle, 'doClient'>,
  page: string,
  scheduledVersionId: string,
  scheduledAt: Date,
) {
  const [row] = await db
    .update(pageLayoutPointers)
    .set({ scheduledVersionId, scheduledAt })
    .where(eq(pageLayoutPointers.page, page))
    .returning();
  if (row) {
    try {
      await services.doClient.armScheduledPublishAlarm(page, scheduledAt);
    } catch (err) {
      captureCaught(err, { scope: 'armScheduledPublishAlarm', extra: { page } });
    }
  }
  return row ?? null;
}

/**
 * Cancel a scheduled publish — clear fields and disarm.
 */
export async function cancelScheduledPublish(
  db: DrizzleClient,
  services: Pick<ServiceBundle, 'doClient'>,
  page: string,
) {
  const [row] = await db
    .update(pageLayoutPointers)
    .set({ scheduledVersionId: null, scheduledAt: null })
    .where(eq(pageLayoutPointers.page, page))
    .returning();
  if (row) {
    try {
      await services.doClient.disarmScheduledPublishAlarm(page);
    } catch (err) {
      captureCaught(err, { scope: 'disarmScheduledPublishAlarm', extra: { page } });
    }
  }
  return row ?? null;
}

/**
 * Flip liveVersionId to scheduledVersionId and clear scheduled fields (immediate publish).
 * Disarms the alarm since the scheduled version is now live.
 */
export async function flipToScheduledVersion(
  db: DrizzleClient,
  services: Pick<ServiceBundle, 'doClient'>,
  page: string,
) {
  const [ptr] = await db
    .select()
    .from(pageLayoutPointers)
    .where(
      and(
        eq(pageLayoutPointers.page, page),
        isNotNull(pageLayoutPointers.scheduledVersionId),
        lte(pageLayoutPointers.scheduledAt, new Date()),
      ),
    )
    .limit(1);

  if (!ptr || !ptr.scheduledVersionId) return null;

  const [row] = await db
    .update(pageLayoutPointers)
    .set({
      liveVersionId: ptr.scheduledVersionId,
      scheduledVersionId: null,
      scheduledAt: null,
    })
    .where(eq(pageLayoutPointers.page, page))
    .returning();
  if (row) {
    try {
      await services.doClient.disarmScheduledPublishAlarm(page);
    } catch (err) {
      captureCaught(err, { scope: 'disarmScheduledPublishAlarm', extra: { page } });
    }
  }
  return row ?? null;
}
