import { sql } from 'drizzle-orm';
import type { TransactionalDatabase } from '@platform-modules/db';
import type { FulfillmentDbSchema, FulfillmentPorts, StorageAdapter } from '@platform-modules/commerce-fulfillment';

export function createR2StorageAdapter(bucket: R2Bucket): StorageAdapter {
  return {
    async put(key, body) {
      await bucket.put(key, body);
    },
    async signedUrl(key, ttlSeconds) {
      // CF Workers R2 does not issue cryptographically signed URLs from the binding.
      // Serve downloads via /api/download/[key] (session + access_grant gate).
      // expiresAt reflects the token TTL even though the route itself is session-gated.
      return {
        url: `/api/download/${encodeURIComponent(key)}`,
        expiresAt: new Date(Date.now() + ttlSeconds * 1000),
      };
    },
  };
}

export function createNoOpStorageAdapter(): StorageAdapter {
  return {
    async put() {
      throw new Error('StorageAdapter: no R2 bucket configured (MEDIA binding missing)');
    },
    async signedUrl() {
      throw new Error('StorageAdapter: no R2 bucket configured (MEDIA binding missing)');
    },
  };
}

/**
 * Build digital-only FulfillmentPorts for the storefront.
 *
 * resolveBlobKey reads variant.attributes.blobKey — set this on each variant
 * when uploading its digital asset. Physical shipping is not supported in v1.
 */
export function createStorefrontFulfillmentPorts(
  db: TransactionalDatabase<FulfillmentDbSchema>,
  storage: StorageAdapter,
): FulfillmentPorts {
  return {
    db,
    storage,

    async resolveBlobKey(line) {
      const rows = await db.execute(sql`
        SELECT attributes FROM variant WHERE id = ${line.variantId} LIMIT 1
      `);
      const raw = Array.isArray(rows) ? rows : (rows as { rows?: unknown[] }).rows ?? [];
      const row = raw[0] as { attributes?: unknown } | undefined;
      if (!row) throw new Error(`Variant ${line.variantId} not found`);
      const attrs = row.attributes as Record<string, unknown> | null;
      const blobKey = attrs?.blobKey;
      if (typeof blobKey !== 'string' || !blobKey) {
        throw new Error(
          `Variant ${line.variantId} has no blobKey in attributes — upload a digital asset first`,
        );
      }
      return blobKey;
    },

    async resolveShippingAddress() {
      throw new Error('Physical shipping is not supported in v1');
    },

    async notify() {
      // v1 no-op — wire to @platform-modules/mail in a later wave
    },
  };
}
