import type { CheckoutIntentData } from './types.js';

/** Checkout caller identity. Guest tokens are verified upstream (I/O); the machine only sees the pre-verified `guestAuthorized` boolean. */
export type CheckoutActor =
  | { kind: 'user'; userId: string }
  | { kind: 'guest'; guestAccessToken: string };

export interface CheckoutIntentStartInput {
  purchaseUserId: string | null;
  actor: CheckoutActor;
  guestAuthorized: boolean;
  paymentStatus: string;
  vendorReady: boolean;
  orderStatus: string;
}

export type CheckoutIntentStartDecision =
  | { ok: true; shouldClaimOrder: boolean }
  | {
      ok: false;
      code: 'FORBIDDEN' | 'INVALID_STATUS' | 'VENDOR_NOT_ONBOARDED';
      error: string;
    };

export function decideCheckoutIntentStart(
  input: CheckoutIntentStartInput,
): CheckoutIntentStartDecision {
  if (input.actor.kind === 'user') {
    if (input.purchaseUserId !== input.actor.userId) {
      return { ok: false, code: 'FORBIDDEN', error: 'Access denied' };
    }
  } else if (input.purchaseUserId !== null || !input.guestAuthorized) {
    return { ok: false, code: 'FORBIDDEN', error: 'Access denied' };
  }

  if (input.paymentStatus !== 'pending' && input.paymentStatus !== 'charging') {
    return {
      ok: false,
      code: 'INVALID_STATUS',
      error: `State: ${input.paymentStatus}`,
    };
  }

  if (input.orderStatus !== 'pending' && input.orderStatus !== 'charging') {
    return {
      ok: false,
      code: 'INVALID_STATUS',
      error: `State: ${input.orderStatus}`,
    };
  }

  if (!input.vendorReady) {
    return {
      ok: false,
      code: 'VENDOR_NOT_ONBOARDED',
      error: 'Vendor inactive',
    };
  }

  return { ok: true, shouldClaimOrder: input.orderStatus === 'pending' };
}

export interface PostChargeReserveInput {
  chargeStatus: 'requires_client_confirmation' | 'succeeded';
  providerPaymentId: string;
  clientSecret?: string;
  reservationExists: boolean;
}

export type PostChargeReserveDecision = {
  ok: true;
  replayed: boolean;
  data: CheckoutIntentData;
};

export function decidePostChargeReserve(input: PostChargeReserveInput): PostChargeReserveDecision {
  if (!input.providerPaymentId.trim()) {
    throw new Error('provider payment id is required');
  }

  if (input.chargeStatus === 'succeeded') {
    return {
      ok: true,
      replayed: input.reservationExists,
      data: { providerPaymentId: input.providerPaymentId, finalized: true },
    };
  }

  if (!input.clientSecret?.trim()) {
    throw new Error('client secret is required for interactive confirmation');
  }

  return {
    ok: true,
    replayed: input.reservationExists,
    data: {
      clientSecret: input.clientSecret,
      providerPaymentId: input.providerPaymentId,
    },
  };
}
