import {
  createProductionReceiptStore,
  hasValidReceiptAuditIntegrity,
  matchesCanonicalV3RouteResource,
  type StoredX402Receipt,
} from './receipt-store';
import { isValidV3RequestId } from '../../_lib/validation';
import { V3_API_ROUTES } from '../../_lib/inventory';

export type ReceiptEnvironment = Readonly<Record<string, string | undefined>>;

export function assertV3ReceiptStatusRelationships(receipt: StoredX402Receipt): void {
  const route = V3_API_ROUTES.find((candidate) => candidate.id === receipt.binding.routeId);
  if (
    !route ||
    route.method !== receipt.binding.method ||
    route.path !== receipt.binding.route ||
    !matchesCanonicalV3RouteResource(route.path, receipt.binding.resource)
  ) throw new Error('receipt route binding is not canonical');
  if (receipt.binding.network !== `eip155:${receipt.binding.chainId}`) {
    throw new Error('receipt payment network and chain do not match');
  }
  if (
    receipt.observation &&
    (receipt.observation.network !== receipt.binding.network ||
      receipt.observation.chainId !== receipt.binding.chainId ||
      receipt.observation.network !== `eip155:${receipt.observation.chainId}`)
  ) throw new Error('receipt transaction evidence does not match payment requirement');
}

function publicReceipt(receipt: StoredX402Receipt) {
  if (!hasValidReceiptAuditIntegrity(receipt)) throw new Error('receipt audit integrity verification failed');
  assertV3ReceiptStatusRelationships(receipt);
  return {
    schema: 'vaultfire.v3.x402.receipt-status.v1',
    schemaVersion: '1.0.0',
    protocolVersion: '3.0.0',
    receiptId: receipt.receiptId,
    requestId: receipt.binding.requestId,
    state: receipt.state,
    routeId: receipt.binding.routeId,
    route: receipt.binding.route,
    resource: receipt.binding.resource,
    method: receipt.binding.method,
    paymentRequirement: {
      network: receipt.binding.network,
      chainId: receipt.binding.chainId,
      asset: receipt.binding.asset,
      amount: receipt.binding.amount,
      scheme: receipt.binding.scheme,
      payee: receipt.binding.payee,
      requiredFinality: receipt.binding.requiredFinality,
      minConfirmations: receipt.binding.minConfirmations,
    },
    bindingDigest: receipt.bindingDigest,
    createdAt: receipt.createdAt,
    updatedAt: receipt.updatedAt,
    version: receipt.version,
    auditIntegrity: {
      ...receipt.auditIntegrity,
      verified: true,
      historyVerifiedFromGenesis: true,
      eventCount: receipt.auditHistory.length,
    },
    transactionEvidence: receipt.observation
      ? {
          network: receipt.observation.network,
          chainId: receipt.observation.chainId,
          txHash: receipt.observation.txHash,
          blockNumber: receipt.observation.blockNumber,
          blockHash: receipt.observation.blockHash,
          headBlockNumber: receipt.observation.headBlockNumber,
          observedFinality: receipt.observation.observedFinality,
          observedAt: receipt.observation.observedAt,
          canonicalBlock: receipt.observation.canonicalBlock,
        }
      : null,
    evidenceLabels: {
      receiptPersisted: true,
      transactionObserved: Boolean(receipt.observation),
      settlementVerified: ['confirmed', 'finalized'].includes(receipt.state),
      bazaarIndexingVerified: false,
    },
  };
}

export async function createReceiptStatusResponse(
  requestId: string,
  environment: ReceiptEnvironment = process.env,
  fetchImpl: typeof fetch = fetch,
): Promise<Response> {
  if (!isValidV3RequestId(requestId)) {
    return Response.json(
      { schema: 'vaultfire.v3.input-error.v1', schemaVersion: '1.0.0', protocolVersion: '3.0.0', error: { code: 'invalid_request_id', message: 'Invalid request ID', retryable: false } },
      { status: 400, headers: { 'Cache-Control': 'no-store' } },
    );
  }
  const store = createProductionReceiptStore({ ...environment }, fetchImpl);
  if (!store.available) {
    return Response.json(
      { schema: 'vaultfire.v3.x402.receipt-error.v1', schemaVersion: '1.0.0', protocolVersion: '3.0.0', error: 'V3 receipt store is not configured', code: 'v3_receipt_store_unconfigured', retryable: false },
      { status: 503, headers: { 'Cache-Control': 'no-store', 'X-Robots-Tag': 'noindex' } },
    );
  }
  try {
    const receipt = await store.get(requestId);
    if (!receipt) {
      return Response.json(
        { schema: 'vaultfire.v3.x402.receipt-error.v1', schemaVersion: '1.0.0', protocolVersion: '3.0.0', error: 'Receipt not found', code: 'v3_receipt_not_found', requestId, retryable: false },
        { status: 404, headers: { 'Cache-Control': 'no-store' } },
      );
    }
    return Response.json(publicReceipt(receipt), {
      headers: { 'Cache-Control': 'no-store', 'X-Robots-Tag': 'noindex' },
    });
  } catch {
    return Response.json(
      { schema: 'vaultfire.v3.x402.receipt-error.v1', schemaVersion: '1.0.0', protocolVersion: '3.0.0', error: 'V3 receipt evidence is unavailable', code: 'v3_receipt_store_unavailable', retryable: true },
      { status: 503, headers: { 'Cache-Control': 'no-store', 'X-Robots-Tag': 'noindex' } },
    );
  }
}
