import { base64UrlDecodeBytes, base64UrlDecodeStr } from '@/lib/encoding.js';
import { captureCaught } from '@/lib/observability';
import { sha256Hex, signE2eProof } from '@/server/security/e2e-proof';
import type {
  CarrierAdapter,
  BuyLabelArgs,
  CarrierTrackResult,
  CarrierWebhookResult,
  ShipmentStatus,
} from './types';

const BASE_URLS = {
  test: 'https://daas-public-api.development.dev.woltapi.com',
  production: 'https://daas-public-api.wolt.com',
} as const;

interface WoltDriveEnv {
  WOLT_DRIVE_MERCHANT_KEY?: string;
  WOLT_DRIVE_MERCHANT_ID?: string;
  WOLT_DRIVE_MOCK_URL?: string;
  WOLT_DRIVE_ENV?: 'test' | 'production';
  WOLT_DRIVE_WEBHOOK_SECRET?: string;
  SUPPORT_EMAIL?: string;
  SUPPORT_PHONE?: string;
  E2E_SECRET?: string;
}

/** Max age for Wolt webhook dispatched_at (and optional JWT exp) before reject. */
const DISPATCHED_AT_MAX_SKEW_MS = 15 * 60 * 1000;

function parseDispatchedAtMs(dispatchedAt: unknown): number | null {
  if (typeof dispatchedAt !== 'string' || !dispatchedAt) return null;
  const ms = Date.parse(dispatchedAt);
  return Number.isNaN(ms) ? null : ms;
}

function isWebhookTimestampFresh(payload: Record<string, unknown>): boolean {
  const dispatchedMs = parseDispatchedAtMs(payload.dispatched_at);
  if (dispatchedMs == null) return false;
  if (Math.abs(Date.now() - dispatchedMs) > DISPATCHED_AT_MAX_SKEW_MS) return false;

  const exp = payload.exp;
  if (typeof exp === 'number' && exp * 1000 < Date.now() - 60_000) return false;

  return true;
}

function woltWebhookEventId(
  payload: Record<string, unknown>,
  eventType: string,
  woltOrderId: string,
): string {
  const jti = payload.jti;
  if (typeof jti === 'string' && jti) return jti;
  return `${eventType}:${woltOrderId}:${String(payload.dispatched_at ?? '')}`;
}

// Wolt event type → internal ShipmentStatus (null = ETA update / informational, ignore)
const EVENT_STATUS_MAP: Record<string, ShipmentStatus | null> = {
  'order.received': 'shipped',
  'order.rejected': 'cancelled',
  'order.pickup_eta_updated': null,
  'order.pickup_arrival': null,
  'order.pickup_started': 'in_transit',
  'order.picked_up': 'in_transit',
  'order.dropoff_started': 'out_for_delivery',
  'order.dropoff_arrival': 'out_for_delivery',
  'order.dropoff_completed': 'delivered',
  'order.delivered': 'delivered',
  'order.dropoff_eta_updated': null,
  'order.customer_no_show': 'failed_delivery',
  'order.handshake_delivery': null,
  'order.location_updated': null, // high-frequency GPS — skip
};

async function verifyJwtHs256(
  token: string,
  secret: string,
): Promise<Record<string, unknown> | null> {
  try {
    const parts = token.split('.');
    if (parts.length !== 3) return null;
    const [headerB64, payloadB64, sigB64] = parts as [string, string, string];

    const enc = new TextEncoder();
    const key = await crypto.subtle.importKey(
      'raw',
      enc.encode(secret),
      { name: 'HMAC', hash: 'SHA-256' },
      false,
      ['verify'],
    );

    const sigBytes = base64UrlDecodeBytes(sigB64);
    const data = enc.encode(`${headerB64}.${payloadB64}`);
    const valid = await crypto.subtle.verify('HMAC', key, sigBytes as BufferSource, data);
    if (!valid) return null;

    return JSON.parse(base64UrlDecodeStr(payloadB64)) as Record<string, unknown>;
  } catch (err) {
    captureCaught(err, { scope: 'carriers.wolt-drive.verifyJwtHs256', severity: 'info' });
    return null;
  }
}

function toE164IL(phone: string): string {
  const digits = phone.replace(/\D/g, '');
  if (digits.startsWith('972')) return '+' + digits;
  if (digits.startsWith('0')) return '+972' + digits.slice(1);
  return '+972' + digits;
}

export class WoltDriveAdapter implements CarrierAdapter {
  kind = 'wolt_drive' as const;
  capabilities = {
    canBuyLabel: true,
    hasTrackingApi: false,
    hasWebhook: true,
    supportsInsurance: false,
  };

  constructor(private env: WoltDriveEnv) {}

  private get baseUrl(): string {
    return BASE_URLS[this.env.WOLT_DRIVE_ENV ?? 'test'];
  }

  async buyLabel(
    args: BuyLabelArgs,
  ): Promise<{ trackingNumber: string; labelR2Key: string; trackingUrl: string }> {
    const { WOLT_DRIVE_MERCHANT_KEY, WOLT_DRIVE_MERCHANT_ID } = this.env;
    if (!WOLT_DRIVE_MERCHANT_KEY || !WOLT_DRIVE_MERCHANT_ID) {
      throw new Error('wolt_drive_no_credentials');
    }
    if (!args.resolvedPickup || !args.resolvedDropoff) {
      throw new Error('wolt_drive_missing_resolved_addresses');
    }

    const { resolvedPickup: pickup, resolvedDropoff: dropoff } = args;

    const body = {
      pickup: {
        location: {
          formatted_address: pickup.formattedAddress,
          coordinates: { lat: pickup.lat, lon: pickup.lon },
        },
        contact_details: {
          name: pickup.contactName,
          phone_number: toE164IL(pickup.contactPhone),
        },
        comment: 'Multideal vendor pickup',
      },
      dropoff: {
        location: {
          formatted_address: dropoff.formattedAddress,
          coordinates: { lat: dropoff.lat, lon: dropoff.lon },
        },
        contact_details: {
          name: dropoff.contactName,
          phone_number: toE164IL(dropoff.contactPhone),
        },
        comment: dropoff.deliveryNote ?? '',
      },
      customer_support: {
        email: this.env.SUPPORT_EMAIL ?? 'support@multi.deal',
        phone_number: this.env.SUPPORT_PHONE ?? '+972000000000',
      },
      merchant_order_reference_id: args.shipmentId,
      is_no_contact: false,
      contents: [{ count: 1, description: 'Multideal order' }],
      tips: [],
      min_preparation_time_minutes: 30,
    };

    // Inline mock: avoids CF loopback subrequest timeout (522) when mock URL is same worker domain
    if (this.env.WOLT_DRIVE_MOCK_URL === 'INLINE') {
      return {
        trackingNumber: `mock-wolt-${args.shipmentId}`,
        trackingUrl: 'https://wolt.com/track/mock',
        labelR2Key: '',
      };
    }

    const woltUrl =
      this.env.WOLT_DRIVE_MOCK_URL ??
      `${this.baseUrl}/merchants/${WOLT_DRIVE_MERCHANT_ID}/delivery-order`;

    const bodyStr = JSON.stringify(body);
    const headers: Record<string, string> = {
      Authorization: `Bearer ${WOLT_DRIVE_MERCHANT_KEY}`,
      'Content-Type': 'application/json',
    };
    if (this.env.WOLT_DRIVE_MOCK_URL && this.env.E2E_SECRET) {
      const ts = Math.floor(Date.now() / 1000);
      const pathname = new URL(woltUrl).pathname;
      const sig = await signE2eProof(
        this.env.E2E_SECRET,
        'POST',
        pathname,
        ts,
        await sha256Hex(bodyStr),
        new URL(woltUrl).origin,
      );
      headers['x-e2e-ts'] = String(ts);
      headers['x-e2e-sig'] = sig;
    }

    const res = await fetch(woltUrl, {
      method: 'POST',
      headers,
      body: bodyStr,
    });

    if (!res.ok) {
      throw new Error(`wolt_drive_api_error:${res.status}`);
    }

    const data = (await res.json()) as {
      wolt_order_reference_id: string;
      tracking?: { url?: string };
    };

    return {
      trackingNumber: data.wolt_order_reference_id,
      trackingUrl: data.tracking?.url ?? '',
      labelR2Key: '',
    };
  }

  async track(_trackingNumber: string): Promise<CarrierTrackResult> {
    throw new Error('wolt_drive_no_tracking_api');
  }

  async verifyWebhook(req: Request): Promise<CarrierWebhookResult | null> {
    if (!this.env.WOLT_DRIVE_WEBHOOK_SECRET) return null;

    let body: string;
    try {
      body = await req.text();
    } catch (err) {
      captureCaught(err, { scope: 'carriers.wolt-drive.verifyWebhook.read', severity: 'info' });
      return null;
    }

    let token: string;
    try {
      const parsed = JSON.parse(body) as { token?: string };
      token = parsed.token ?? '';
      if (!token) return null;
    } catch (err) {
      captureCaught(err, { scope: 'carriers.wolt-drive.verifyWebhook.parse', severity: 'info' });
      return null;
    }

    const payload = await verifyJwtHs256(token, this.env.WOLT_DRIVE_WEBHOOK_SECRET);
    if (!payload) return null;
    if (!isWebhookTimestampFresh(payload)) return null;

    // Confirmed payload structure: { type, dispatched_at, details: { wolt_order_reference_id, ... } }
    const details = payload.details as Record<string, unknown> | undefined;
    const woltOrderId = details?.wolt_order_reference_id as string | undefined;
    const eventType = payload.type as string | undefined;
    if (!woltOrderId || !eventType) return null;

    if (!(eventType in EVENT_STATUS_MAP)) return null;
    const status = EVENT_STATUS_MAP[eventType];
    if (!status) return null; // informational event — no status change

    return {
      trackingNumber: woltOrderId,
      status,
      eventId: woltWebhookEventId(payload, eventType, woltOrderId),
      raw: payload,
    };
  }
}
