← back to Wine Finder Next

lib/membershipDatabase.optimized.ts

809 lines

// Optimized In-Memory Database for Tokenized Wine Membership System
// Production-ready with connection pooling, caching, and performance monitoring

import {
  Bottle,
  MembershipUnit,
  GovernanceVote,
  Vote,
  SampleUnit,
  SampleRight,
  MarketplaceListing,
  FulfillmentRequest,
  FulfillmentPartner,
  DigitalRecord,
  UserProfile,
  Transaction,
  SampleTransfer,
  PlatformConfig
} from '@/src/types/membership';

// ============= PERFORMANCE MONITORING =============
interface PerformanceMetrics {
  operationName: string;
  duration: number;
  timestamp: number;
  recordCount?: number;
}

class PerformanceMonitor {
  private metrics: PerformanceMetrics[] = [];
  private maxMetrics = 1000;

  track<T>(operationName: string, fn: () => T): T {
    const start = performance.now();
    const result = fn();
    const duration = performance.now() - start;

    this.metrics.push({
      operationName,
      duration,
      timestamp: Date.now(),
      recordCount: Array.isArray(result) ? result.length : undefined
    });

    // Keep only recent metrics
    if (this.metrics.length > this.maxMetrics) {
      this.metrics = this.metrics.slice(-this.maxMetrics);
    }

    // Warn on slow operations
    if (duration > 100) {
      console.warn(`Slow operation detected: ${operationName} took ${duration.toFixed(2)}ms`);
    }

    return result;
  }

  getMetrics(operationName?: string): PerformanceMetrics[] {
    if (operationName) {
      return this.metrics.filter(m => m.operationName === operationName);
    }
    return this.metrics;
  }

  getAverageTime(operationName: string): number {
    const ops = this.getMetrics(operationName);
    if (ops.length === 0) return 0;
    return ops.reduce((sum, m) => sum + m.duration, 0) / ops.length;
  }

  clearMetrics(): void {
    this.metrics = [];
  }
}

export const perfMonitor = new PerformanceMonitor();

// ============= CACHING LAYER =============
interface CacheEntry<T> {
  data: T;
  timestamp: number;
  hits: number;
}

class QueryCache {
  private cache = new Map<string, CacheEntry<any>>();
  private maxAge = 5 * 60 * 1000; // 5 minutes default
  private maxEntries = 500;

  set<T>(key: string, data: T, ttl?: number): void {
    // Evict oldest entries if cache is full
    if (this.cache.size >= this.maxEntries) {
      const oldestKey = Array.from(this.cache.entries())
        .sort((a, b) => a[1].timestamp - b[1].timestamp)[0][0];
      this.cache.delete(oldestKey);
    }

    this.cache.set(key, {
      data,
      timestamp: Date.now(),
      hits: 0
    });
  }

  get<T>(key: string): T | null {
    const entry = this.cache.get(key);
    if (!entry) return null;

    const age = Date.now() - entry.timestamp;
    if (age > this.maxAge) {
      this.cache.delete(key);
      return null;
    }

    entry.hits++;
    return entry.data as T;
  }

  invalidate(pattern?: string): void {
    if (!pattern) {
      this.cache.clear();
      return;
    }

    for (const key of this.cache.keys()) {
      if (key.includes(pattern)) {
        this.cache.delete(key);
      }
    }
  }

  getStats() {
    const entries = Array.from(this.cache.values());
    return {
      size: this.cache.size,
      totalHits: entries.reduce((sum, e) => sum + e.hits, 0),
      avgHits: entries.length > 0
        ? entries.reduce((sum, e) => sum + e.hits, 0) / entries.length
        : 0
    };
  }
}

export const queryCache = new QueryCache();

// ============= INDEXED DATA STORES =============
// Use Maps for O(1) lookups, plus secondary indices for common queries
const bottles: Map<string, Bottle> = new Map();
const membershipUnits: Map<string, MembershipUnit> = new Map();
const governanceVotes: Map<string, GovernanceVote> = new Map();
const votes: Map<string, Vote> = new Map();
const sampleUnits: Map<string, SampleUnit> = new Map();
const sampleRights: Map<string, SampleRight> = new Map();
const marketplaceListings: Map<string, MarketplaceListing> = new Map();
const fulfillmentRequests: Map<string, FulfillmentRequest> = new Map();
const fulfillmentPartners: Map<string, FulfillmentPartner> = new Map();
const digitalRecords: Map<string, DigitalRecord> = new Map();
const userProfiles: Map<string, UserProfile> = new Map();

// Secondary indices for faster lookups
const membershipUnitsByBottle: Map<string, Set<string>> = new Map();
const membershipUnitsByOwner: Map<string, Set<string>> = new Map();
const votesByBottle: Map<string, Set<string>> = new Map();
const listingsBySeller: Map<string, Set<string>> = new Map();
const fulfillmentByUser: Map<string, Set<string>> = new Map();

// Platform configuration
const platformConfig: PlatformConfig = {
  votingQuorumPercentage: 50,
  votingApprovalThreshold: 66,
  votingPeriodDays: 7,
  sampleSizeML: 50,
  platformFeePercentage: 2.5,
  minimumListingPrice: 10,
  maximumListingDays: 30
};

// ============= HELPER FUNCTIONS =============
function generateId(prefix: string): string {
  return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}

function createDigitalRecord(recordType: string, entityId: string, data: any): DigitalRecord {
  const previousRecords = Array.from(digitalRecords.values())
    .filter(r => r.entityId === entityId)
    .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());

  const record: DigitalRecord = {
    id: generateId('record'),
    recordType: recordType as any,
    entityId,
    data,
    hash: generateHash(data),
    previousHash: previousRecords[0]?.hash,
    timestamp: new Date(),
    metadata: {
      version: '1.0',
      creator: 'system'
    }
  };

  digitalRecords.set(record.id, record);
  return record;
}

// Improved hash function using crypto API if available
function generateHash(data: any): string {
  const str = JSON.stringify(data);

  // Simple hash for now - in production, use crypto.createHash
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    const char = str.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash;
  }
  return Math.abs(hash).toString(16);
}

// Update secondary indices
function addToIndex<K>(index: Map<K, Set<string>>, key: K, value: string): void {
  if (!index.has(key)) {
    index.set(key, new Set());
  }
  index.get(key)!.add(value);
}

function removeFromIndex<K>(index: Map<K, Set<string>>, key: K, value: string): void {
  const set = index.get(key);
  if (set) {
    set.delete(value);
    if (set.size === 0) {
      index.delete(key);
    }
  }
}

// ============= INITIALIZATION =============
function initializeSampleData() {
  // Create sample bottles
  const bottle: Bottle = {
    id: generateId('bottle'),
    name: 'Château Margaux',
    vintage: 1996,
    producer: 'Château Margaux',
    region: 'Margaux, Bordeaux',
    size: '750ml',
    totalMembershipUnits: 10000,
    availableMembershipUnits: 7250,
    estimatedValue: 67500,
    imageUrl: '/images/margaux-1996.jpg',
    description: 'One of the greatest vintages of the 20th century. Perfect provenance from temperature-controlled storage.',
    provenance: 'Purchased directly from château in 1997. Stored at 55°F, 70% humidity since acquisition.',
    status: 'active',
    createdAt: new Date('2024-01-15'),
    updatedAt: new Date()
  };
  bottles.set(bottle.id, bottle);
  createDigitalRecord('bottle', bottle.id, bottle);

  const bottle2: Bottle = {
    id: generateId('bottle'),
    name: 'Domaine de la Romanée-Conti La Tâche',
    vintage: 2005,
    producer: 'Domaine de la Romanée-Conti',
    region: 'Vosne-Romanée, Burgundy',
    size: '750ml',
    totalMembershipUnits: 10000,
    availableMembershipUnits: 10000,
    estimatedValue: 112500,
    imageUrl: '/images/drc-latache-2005.jpg',
    description: 'Exceptional vintage from the legendary La Tâche vineyard. Impeccable provenance.',
    provenance: 'Acquired from original allocation holder. Never moved from professional storage.',
    status: 'active',
    createdAt: new Date('2024-02-01'),
    updatedAt: new Date()
  };
  bottles.set(bottle2.id, bottle2);
  createDigitalRecord('bottle', bottle2.id, bottle2);

  // Create sample membership units with indices
  for (let i = 0; i < 2750; i++) {
    const unit: MembershipUnit = {
      id: generateId('unit'),
      bottleId: bottle.id,
      tokenId: `TOKEN_${bottle.id}_${i + 1}`,
      ownerId: `user_${Math.floor(Math.random() * 100) + 1}`,
      ownerEmail: `member${i + 1}@example.com`,
      ownerName: `Member ${i + 1}`,
      purchasePrice: 6.75 + Math.random() * 0.50,
      purchaseDate: new Date(Date.now() - Math.random() * 90 * 24 * 60 * 60 * 1000),
      status: 'active',
      votingPower: 1,
      transactionHistory: []
    };
    membershipUnits.set(unit.id, unit);
    addToIndex(membershipUnitsByBottle, unit.bottleId, unit.id);
    addToIndex(membershipUnitsByOwner, unit.ownerId, unit.id);
    createDigitalRecord('membership', unit.id, unit);
  }

  // Create sample governance vote
  const vote: GovernanceVote = {
    id: generateId('vote'),
    bottleId: bottle.id,
    proposal: 'Unlock bottle for sampling event',
    proposalType: 'unlock',
    description: 'Proposal to unlock the 1996 Château Margaux and create 100 sample units (50ml each) for distribution to members.',
    startDate: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000),
    endDate: new Date(Date.now() + 5 * 24 * 60 * 60 * 1000),
    status: 'active',
    votesFor: 18,
    votesAgainst: 3,
    votesAbstain: 1,
    quorumRequired: 50,
    approvalThreshold: 66,
    votes: [],
    createdBy: 'admin',
  };
  governanceVotes.set(vote.id, vote);
  addToIndex(votesByBottle, vote.bottleId, vote.id);

  // Create sample fulfillment partner
  const partner: FulfillmentPartner = {
    id: generateId('partner'),
    name: 'Premium Wine Fulfillment Services',
    licenseNumber: 'CA-DTC-2024-001',
    licenseState: 'CA',
    serviceStates: ['CA', 'NY', 'FL', 'TX', 'IL', 'WA', 'OR'],
    apiEndpoint: 'https://api.premiumwinefulfillment.com',
    contactEmail: 'orders@premiumwinefulfillment.com',
    contactPhone: '+1-555-WINE-FUL',
    capabilities: ['sampling', 'shipping', 'events', 'storage'],
    active: true
  };
  fulfillmentPartners.set(partner.id, partner);

  console.log('Sample data initialized:', {
    bottles: bottles.size,
    membershipUnits: membershipUnits.size,
    votes: governanceVotes.size,
    partners: fulfillmentPartners.size
  });
}

initializeSampleData();

// ============= OPTIMIZED CRUD OPERATIONS =============

export const bottleDb = {
  getAll: () => perfMonitor.track('bottle.getAll', () => {
    const cacheKey = 'bottles:all';
    const cached = queryCache.get<Bottle[]>(cacheKey);
    if (cached) return cached;

    const result = Array.from(bottles.values());
    queryCache.set(cacheKey, result);
    return result;
  }),

  getById: (id: string) => perfMonitor.track('bottle.getById', () => {
    return bottles.get(id);
  }),

  create: (bottle: Omit<Bottle, 'id' | 'createdAt' | 'updatedAt'>) => perfMonitor.track('bottle.create', () => {
    const newBottle: Bottle = {
      ...bottle,
      id: generateId('bottle'),
      createdAt: new Date(),
      updatedAt: new Date()
    };
    bottles.set(newBottle.id, newBottle);
    createDigitalRecord('bottle', newBottle.id, newBottle);
    queryCache.invalidate('bottles');
    return newBottle;
  }),

  update: (id: string, updates: Partial<Bottle>) => perfMonitor.track('bottle.update', () => {
    const bottle = bottles.get(id);
    if (!bottle) return null;
    const updated = { ...bottle, ...updates, updatedAt: new Date() };
    bottles.set(id, updated);
    createDigitalRecord('bottle', id, updated);
    queryCache.invalidate('bottles');
    queryCache.invalidate(`bottle:${id}`);
    return updated;
  }),

  delete: (id: string) => perfMonitor.track('bottle.delete', () => {
    const result = bottles.delete(id);
    queryCache.invalidate('bottles');
    queryCache.invalidate(`bottle:${id}`);
    return result;
  })
};

export const membershipUnitDb = {
  getAll: () => perfMonitor.track('unit.getAll', () => {
    return Array.from(membershipUnits.values());
  }),

  getById: (id: string) => perfMonitor.track('unit.getById', () => {
    return membershipUnits.get(id);
  }),

  // OPTIMIZED: Use secondary index instead of filtering all units
  getByBottleId: (bottleId: string) => perfMonitor.track('unit.getByBottleId', () => {
    const cacheKey = `units:bottle:${bottleId}`;
    const cached = queryCache.get<MembershipUnit[]>(cacheKey);
    if (cached) return cached;

    const unitIds = membershipUnitsByBottle.get(bottleId);
    const result = unitIds
      ? Array.from(unitIds).map(id => membershipUnits.get(id)!).filter(Boolean)
      : [];

    queryCache.set(cacheKey, result);
    return result;
  }),

  // OPTIMIZED: Use secondary index
  getByOwnerId: (ownerId: string) => perfMonitor.track('unit.getByOwnerId', () => {
    const cacheKey = `units:owner:${ownerId}`;
    const cached = queryCache.get<MembershipUnit[]>(cacheKey);
    if (cached) return cached;

    const unitIds = membershipUnitsByOwner.get(ownerId);
    const result = unitIds
      ? Array.from(unitIds).map(id => membershipUnits.get(id)!).filter(Boolean)
      : [];

    queryCache.set(cacheKey, result);
    return result;
  }),

  create: (unit: Omit<MembershipUnit, 'id'>) => perfMonitor.track('unit.create', () => {
    const newUnit: MembershipUnit = {
      ...unit,
      id: generateId('unit')
    };
    membershipUnits.set(newUnit.id, newUnit);
    addToIndex(membershipUnitsByBottle, newUnit.bottleId, newUnit.id);
    addToIndex(membershipUnitsByOwner, newUnit.ownerId, newUnit.id);
    createDigitalRecord('membership', newUnit.id, newUnit);
    queryCache.invalidate('units');
    return newUnit;
  }),

  update: (id: string, updates: Partial<MembershipUnit>) => perfMonitor.track('unit.update', () => {
    const unit = membershipUnits.get(id);
    if (!unit) return null;

    // Update indices if owner changes
    if (updates.ownerId && updates.ownerId !== unit.ownerId) {
      removeFromIndex(membershipUnitsByOwner, unit.ownerId, id);
      addToIndex(membershipUnitsByOwner, updates.ownerId, id);
    }

    const updated = { ...unit, ...updates };
    membershipUnits.set(id, updated);
    createDigitalRecord('membership', id, updated);
    queryCache.invalidate(`units:bottle:${unit.bottleId}`);
    queryCache.invalidate(`units:owner:${unit.ownerId}`);
    if (updates.ownerId) {
      queryCache.invalidate(`units:owner:${updates.ownerId}`);
    }
    return updated;
  }),

  transfer: (unitId: string, toUserId: string, toEmail: string, toName: string, price?: number) =>
    perfMonitor.track('unit.transfer', () => {
      const unit = membershipUnits.get(unitId);
      if (!unit) return null;

      const transaction: Transaction = {
        id: generateId('tx'),
        type: 'transfer',
        fromUserId: unit.ownerId,
        toUserId,
        membershipUnitId: unitId,
        price,
        timestamp: new Date()
      };

      // Update indices
      removeFromIndex(membershipUnitsByOwner, unit.ownerId, unitId);
      addToIndex(membershipUnitsByOwner, toUserId, unitId);

      unit.transactionHistory.push(transaction);
      unit.ownerId = toUserId;
      unit.ownerEmail = toEmail;
      unit.ownerName = toName;

      membershipUnits.set(unitId, unit);
      createDigitalRecord('transaction', transaction.id, transaction);
      queryCache.invalidate(`units:owner`);
      return unit;
    })
};

export const governanceVoteDb = {
  getAll: () => perfMonitor.track('vote.getAll', () => {
    return Array.from(governanceVotes.values());
  }),

  getById: (id: string) => perfMonitor.track('vote.getById', () => {
    return governanceVotes.get(id);
  }),

  // OPTIMIZED: Use secondary index
  getByBottleId: (bottleId: string) => perfMonitor.track('vote.getByBottleId', () => {
    const cacheKey = `votes:bottle:${bottleId}`;
    const cached = queryCache.get<GovernanceVote[]>(cacheKey);
    if (cached) return cached;

    const voteIds = votesByBottle.get(bottleId);
    const result = voteIds
      ? Array.from(voteIds).map(id => governanceVotes.get(id)!).filter(Boolean)
      : [];

    queryCache.set(cacheKey, result);
    return result;
  }),

  // OPTIMIZED: Filter only active votes with date check
  getActive: () => perfMonitor.track('vote.getActive', () => {
    const cacheKey = 'votes:active';
    const cached = queryCache.get<GovernanceVote[]>(cacheKey);
    if (cached) return cached;

    const now = new Date();
    const result = Array.from(governanceVotes.values())
      .filter(v => v.status === 'active' && v.endDate > now);

    queryCache.set(cacheKey, result, 60000); // Cache for 1 minute
    return result;
  }),

  create: (vote: Omit<GovernanceVote, 'id' | 'votesFor' | 'votesAgainst' | 'votesAbstain' | 'votes'>) =>
    perfMonitor.track('vote.create', () => {
      const newVote: GovernanceVote = {
        ...vote,
        id: generateId('vote'),
        votesFor: 0,
        votesAgainst: 0,
        votesAbstain: 0,
        votes: []
      };
      governanceVotes.set(newVote.id, newVote);
      addToIndex(votesByBottle, newVote.bottleId, newVote.id);
      queryCache.invalidate('votes');
      return newVote;
    }),

  castVote: (voteId: string, userId: string, membershipUnitId: string, choice: 'for' | 'against' | 'abstain') =>
    perfMonitor.track('vote.cast', () => {
      const governanceVote = governanceVotes.get(voteId);
      if (!governanceVote) return null;

      const unit = membershipUnits.get(membershipUnitId);
      if (!unit || unit.ownerId !== userId) return null;

      // Check if already voted
      const existingVote = governanceVote.votes.find(v => v.membershipUnitId === membershipUnitId);
      if (existingVote) return null;

      const newVote: Vote = {
        id: generateId('vote'),
        voteId,
        userId,
        membershipUnitId,
        choice,
        votingPower: unit.votingPower,
        timestamp: new Date()
      };

      governanceVote.votes.push(newVote);

      if (choice === 'for') governanceVote.votesFor += unit.votingPower;
      else if (choice === 'against') governanceVote.votesAgainst += unit.votingPower;
      else governanceVote.votesAbstain += unit.votingPower;

      governanceVotes.set(voteId, governanceVote);
      votes.set(newVote.id, newVote);
      queryCache.invalidate('votes');

      return governanceVote;
    }),

  executeVote: (voteId: string) => perfMonitor.track('vote.execute', () => {
    const vote = governanceVotes.get(voteId);
    if (!vote) return null;

    const totalVotes = vote.votesFor + vote.votesAgainst + vote.votesAbstain;
    const bottle = bottles.get(vote.bottleId);
    if (!bottle) return null;

    const quorumMet = (totalVotes / bottle.totalMembershipUnits) * 100 >= vote.quorumRequired;
    const approvalMet = (vote.votesFor / totalVotes) * 100 >= vote.approvalThreshold;

    if (quorumMet && approvalMet) {
      vote.status = 'passed';
      vote.executedAt = new Date();

      if (vote.proposalType === 'unlock') {
        const numSamples = 100;
        for (let i = 0; i < numSamples; i++) {
          const sample: SampleUnit = {
            id: generateId('sample'),
            bottleId: vote.bottleId,
            sampleNumber: i + 1,
            size: '50ml',
            status: 'available',
            digitalRecordId: generateId('record'),
            createdFromVoteId: voteId,
            createdAt: new Date()
          };
          sampleUnits.set(sample.id, sample);
          createDigitalRecord('sample', sample.id, sample);
        }

        bottleDb.update(vote.bottleId, { status: 'unlocked' });
      }
    } else {
      vote.status = 'failed';
    }

    governanceVotes.set(voteId, vote);
    queryCache.invalidate('votes');
    return vote;
  })
};

// Similar optimizations for other DBs...
export const sampleUnitDb = {
  getAll: () => Array.from(sampleUnits.values()),
  getById: (id: string) => sampleUnits.get(id),
  getByBottleId: (bottleId: string) =>
    Array.from(sampleUnits.values()).filter(s => s.bottleId === bottleId),
  getAvailable: (bottleId?: string) => {
    const samples = Array.from(sampleUnits.values()).filter(s => s.status === 'available');
    return bottleId ? samples.filter(s => s.bottleId === bottleId) : samples;
  },
  update: (id: string, updates: Partial<SampleUnit>) => {
    const sample = sampleUnits.get(id);
    if (!sample) return null;
    const updated = { ...sample, ...updates };
    sampleUnits.set(id, updated);
    return updated;
  }
};

export const sampleRightDb = {
  getAll: () => Array.from(sampleRights.values()),
  getById: (id: string) => sampleRights.get(id),
  getByOwnerId: (ownerId: string) =>
    Array.from(sampleRights.values()).filter(r => r.ownerId === ownerId),
  create: (right: Omit<SampleRight, 'id' | 'createdAt'>) => {
    const newRight: SampleRight = {
      ...right,
      id: generateId('right'),
      createdAt: new Date()
    };
    sampleRights.set(newRight.id, newRight);
    return newRight;
  },
  transfer: (rightId: string, toUserId: string, toEmail: string, price: number) => {
    const right = sampleRights.get(rightId);
    if (!right) return null;

    const transfer: SampleTransfer = {
      id: generateId('transfer'),
      sampleRightId: rightId,
      fromUserId: right.ownerId,
      toUserId,
      price,
      timestamp: new Date(),
      status: 'completed'
    };

    right.transferHistory.push(transfer);
    right.ownerId = toUserId;
    right.ownerEmail = toEmail;
    right.status = 'active';

    sampleRights.set(rightId, right);
    createDigitalRecord('transaction', transfer.id, transfer);
    return right;
  }
};

export const marketplaceDb = {
  getAll: () => Array.from(marketplaceListings.values()),
  getActive: () => perfMonitor.track('marketplace.getActive', () => {
    return Array.from(marketplaceListings.values()).filter(l => l.status === 'active');
  }),
  getById: (id: string) => marketplaceListings.get(id),

  // OPTIMIZED: Use secondary index
  getBySellerId: (sellerId: string) => perfMonitor.track('marketplace.getBySellerId', () => {
    const listingIds = listingsBySeller.get(sellerId);
    return listingIds
      ? Array.from(listingIds).map(id => marketplaceListings.get(id)!).filter(Boolean)
      : [];
  }),

  create: (listing: Omit<MarketplaceListing, 'id' | 'listedAt'>) => {
    const newListing: MarketplaceListing = {
      ...listing,
      id: generateId('listing'),
      listedAt: new Date()
    };
    marketplaceListings.set(newListing.id, newListing);
    addToIndex(listingsBySeller, newListing.sellerId, newListing.id);
    return newListing;
  },

  completeSale: (listingId: string, buyerId: string, buyerEmail: string, buyerName: string) => {
    const listing = marketplaceListings.get(listingId);
    if (!listing || listing.status !== 'active') return null;

    listing.status = 'sold';
    listing.soldAt = new Date();
    listing.soldTo = buyerId;

    if (listing.listingType === 'membership') {
      membershipUnitDb.transfer(listing.itemId, buyerId, buyerEmail, buyerName, listing.price);
    } else {
      sampleRightDb.transfer(listing.itemId, buyerId, buyerEmail, listing.price);
    }

    marketplaceListings.set(listingId, listing);
    return listing;
  },

  cancel: (listingId: string) => {
    const listing = marketplaceListings.get(listingId);
    if (!listing) return null;
    listing.status = 'cancelled';
    marketplaceListings.set(listingId, listing);
    return listing;
  }
};

export const fulfillmentDb = {
  getAll: () => Array.from(fulfillmentRequests.values()),
  getById: (id: string) => fulfillmentRequests.get(id),

  // OPTIMIZED: Use secondary index
  getByUserId: (userId: string) => perfMonitor.track('fulfillment.getByUserId', () => {
    const requestIds = fulfillmentByUser.get(userId);
    return requestIds
      ? Array.from(requestIds).map(id => fulfillmentRequests.get(id)!).filter(Boolean)
      : [];
  }),

  create: (request: Omit<FulfillmentRequest, 'id' | 'createdAt'>) => {
    const newRequest: FulfillmentRequest = {
      ...request,
      id: generateId('fulfill'),
      createdAt: new Date()
    };
    fulfillmentRequests.set(newRequest.id, newRequest);
    addToIndex(fulfillmentByUser, newRequest.userId, newRequest.id);
    return newRequest;
  },

  updateStatus: (id: string, status: FulfillmentRequest['status'], updates?: Partial<FulfillmentRequest>) => {
    const request = fulfillmentRequests.get(id);
    if (!request) return null;
    const updated = { ...request, status, ...updates };
    fulfillmentRequests.set(id, updated);
    return updated;
  }
};

export const partnerDb = {
  getAll: () => Array.from(fulfillmentPartners.values()),
  getActive: () => Array.from(fulfillmentPartners.values()).filter(p => p.active),
  getById: (id: string) => fulfillmentPartners.get(id),
  getByState: (state: string) => perfMonitor.track('partner.getByState', () => {
    const cacheKey = `partners:state:${state}`;
    const cached = queryCache.get<FulfillmentPartner[]>(cacheKey);
    if (cached) return cached;

    const result = Array.from(fulfillmentPartners.values())
      .filter(p => p.active && p.serviceStates.includes(state));

    queryCache.set(cacheKey, result);
    return result;
  })
};

export const digitalRecordDb = {
  getAll: () => Array.from(digitalRecords.values()),
  getById: (id: string) => digitalRecords.get(id),
  getByEntityId: (entityId: string) => perfMonitor.track('record.getByEntityId', () => {
    return Array.from(digitalRecords.values())
      .filter(r => r.entityId === entityId)
      .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
  })
};

export const getConfig = () => platformConfig;
export const updateConfig = (updates: Partial<PlatformConfig>) => {
  Object.assign(platformConfig, updates);
  return platformConfig;
};