import { bytesToHex } from '@/lib/encoding.js';
import type { CarrierAdapter } from './types';

export class PickupPseudoAdapter implements CarrierAdapter {
  kind = 'pickup' as const;
  capabilities = {
    canBuyLabel: false,
    hasTrackingApi: false,
    hasWebhook: false,
    supportsInsurance: false,
  };
  async buyLabel(): Promise<never> {
    throw new Error('pickup_no_label');
  }
  async track(): Promise<never> {
    throw new Error('pickup_no_tracking');
  }
  async verifyWebhook(): Promise<null> {
    return null;
  }
  // Signed-token helpers used by /api/shipments/[id]/pickup-confirm:
  static async signPickupToken(shipmentId: string, secret: string): Promise<string> {
    const enc = new TextEncoder();
    const key = await crypto.subtle.importKey(
      'raw',
      enc.encode(secret),
      { name: 'HMAC', hash: 'SHA-256' },
      false,
      ['sign'],
    );
    const exp = Math.floor(Date.now() / 1000) + 86400;
    const nonce = crypto.randomUUID();
    const payload = `${shipmentId}.${exp}.${nonce}`;
    const sig = await crypto.subtle.sign('HMAC', key, enc.encode(payload));
    const sigHex = bytesToHex(sig);
    return `${payload}.${sigHex}`;
  }
  static async verifyPickupToken(
    token: string,
    secret: string,
  ): Promise<{ shipmentId: string; nonce: string } | null> {
    const enc = new TextEncoder();
    const parts = token.split('.');
    if (parts.length !== 4) return null;
    const shipmentId = parts[0] as string;
    const expStr = parts[1] as string;
    const nonce = parts[2] as string;
    const sigHex = parts[3] as string;
    if (Number(expStr) < Math.floor(Date.now() / 1000)) return null;
    const key = await crypto.subtle.importKey(
      'raw',
      enc.encode(secret),
      { name: 'HMAC', hash: 'SHA-256' },
      false,
      ['verify'],
    );
    const sig = Uint8Array.from(sigHex.match(/.{2}/g)!.map((h) => parseInt(h, 16)));
    const ok = await crypto.subtle.verify(
      'HMAC',
      key,
      sig,
      enc.encode(`${shipmentId}.${expStr}.${nonce}`),
    );
    return ok ? { shipmentId, nonce } : null;
  }
}
