import { createScheduledDbService } from '@/server/services/db.js';
import { BaseDO } from './_base.js';
import type { MultidealEnv } from '../lib/env.js';
import { expirePersonalOffer } from '../lifecycle/personal-offers.js';
import { createPushClient } from '@/server/push/send';
import type { PushClient } from '@/server/push/types';

/**
 * PersonalOfferDO — Durable Object for personal deal request timeout alarms.
 *
 * Each instance = one personal_deal_requests row (keyed by requestId).
 * Alarm fires at responseDeadline epoch ms (30 min after request created).
 */
export class PersonalOfferDO extends BaseDO {
  protected className = 'PersonalOfferDO';

  constructor(ctx: DurableObjectState, env: MultidealEnv) {
    super(ctx, env);
  }

  override async alarm(): Promise<void> {
    const requestId = (await this.ctx.storage.get<string>('entity_id')) ?? this.ctx.id.toString();
    console.warn(JSON.stringify({ event: 'do_alarm_start', class: 'PersonalOfferDO', requestId }));
    try {
      const db = createScheduledDbService(this.env);
      const push: PushClient =
        this.env.VAPID_PUBLIC_KEY && this.env.VAPID_PRIVATE_KEY && this.env.VAPID_SUBJECT
          ? createPushClient(db, {
              VAPID_PUBLIC_KEY: this.env.VAPID_PUBLIC_KEY,
              VAPID_PRIVATE_KEY: this.env.VAPID_PRIVATE_KEY,
              VAPID_SUBJECT: this.env.VAPID_SUBJECT,
              DATABASE_URL: this.env.DATABASE_URL,
            })
          : ({
              sendToUser: async () => undefined as unknown,
              sendToVendor: async () => undefined as unknown,
            } as PushClient);

      await expirePersonalOffer({ db, push }, requestId);
      await this.ctx.storage.delete('arm_at');
      console.warn(JSON.stringify({ event: 'do_alarm_done', class: 'PersonalOfferDO', requestId }));
    } catch (err) {
      console.error(
        JSON.stringify({
          event: 'do_alarm_error',
          class: 'PersonalOfferDO',
          requestId,
          error: err instanceof Error ? err.message : String(err),
        }),
      );
      throw err;
    }
  }
}
