/**
 * Migration Script: Convert BrandAsset base64Data to Filesystem Storage
 *
 * Phase 1: For each BrandAsset with base64Data but no valid url,
 *   - Convert base64 data to a file in uploads/brand-assets/
 *   - Set url to the filesystem path
 *   - Keep base64Data intact for rollback safety
 *
 * Phase 2 (manual, after verification): Clear base64Data from migrated records.
 *
 * Usage:
 *   cd src/backend
 *   npx ts-node src/scripts/migrate-brand-assets.ts
 *
 * Or with environment variable:
 *   MONGODB_URI=mongodb://localhost:27017/mengo npx ts-node src/scripts/migrate-brand-assets.ts
 */

import mongoose from 'mongoose';
import fs from 'fs';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';

const BRAND_ASSETS_DIR = path.resolve(process.cwd(), 'uploads', 'brand-assets');

const MIME_TO_EXT: Record<string, string> = {
  'image/png': 'png',
  'image/jpeg': 'jpg',
  'image/webp': 'webp',
  'image/gif': 'gif',
  'image/svg+xml': 'svg',
  'image/x-icon': 'ico',
  'image/vnd.microsoft.icon': 'ico',
  'application/pdf': 'pdf',
};

function parseDataUri(dataUri: string): { buffer: Buffer; mimeType: string } | null {
  const match = dataUri.match(/^data:([^;]+);base64,(.+)$/s);
  if (!match) return null;
  return {
    buffer: Buffer.from(match[2], 'base64'),
    mimeType: match[1],
  };
}

function needsMigration(doc: any): boolean {
  // Has base64Data but url is empty, null, or a data: URI
  if (!doc.base64Data) return false;
  if (!doc.url) return true;
  if (doc.url.startsWith('data:')) return true;
  return false;
}

async function migrate() {
  const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/mengo';

  console.log('🔄 BrandAsset base64Data → Filesystem Migration');
  console.log(`📂 Upload directory: ${BRAND_ASSETS_DIR}`);
  console.log(`🗄️  MongoDB URI: ${MONGODB_URI.replace(/:([^@]{4})[^@]+@/, ':****@')}`);
  console.log('');

  // Ensure upload directory exists
  if (!fs.existsSync(BRAND_ASSETS_DIR)) {
    fs.mkdirSync(BRAND_ASSETS_DIR, { recursive: true });
    console.log('📁 Created uploads/brand-assets/ directory');
  }

  // Connect to MongoDB
  console.log('⏳ Connecting to MongoDB...');
  await mongoose.connect(MONGODB_URI, {
    serverSelectionTimeoutMS: 30000,
    socketTimeoutMS: 120000,
  });
  console.log('✅ Connected to MongoDB');

  const db = mongoose.connection.db!;
  const collection = db.collection('brandassets');

  // Find documents needing migration
  const docs = await collection.find({
    base64Data: { $exists: true, $ne: null },
    $or: [
      { url: { $exists: false } },
      { url: null },
      { url: '' },
      { url: /^data:/ },
    ],
  }).toArray();

  console.log(`📊 Found ${docs.length} documents to migrate`);
  console.log('');

  if (docs.length === 0) {
    console.log('✨ No documents need migration. All done!');
    await mongoose.disconnect();
    return;
  }

  let migrated = 0;
  let skipped = 0;
  let errors = 0;

  for (const doc of docs) {
    try {
      const base64Str: string = doc.base64Data;

      // Parse data URI: "data:image/png;base64,ABC123..."
      const parsed = parseDataUri(base64Str);
      if (!parsed) {
        // Try treating as raw base64 (no data: prefix)
        console.log(`⚠️  Doc ${doc._id}: Could not parse data URI, trying raw base64...`);
        const ext = 'png';
        const buffer = Buffer.from(base64Str, 'base64');
        const filename = `${uuidv4()}.${ext}`;
        const filePath = path.join(BRAND_ASSETS_DIR, filename);

        fs.writeFileSync(filePath, buffer);
        const url = `/uploads/brand-assets/${filename}`;

        await collection.updateOne(
          { _id: doc._id },
          { $set: { url } }
          // Phase 2: also { $unset: { base64Data: "" } }
        );

        console.log(`✅ Migrated ${doc._id} -> ${url} (raw base64, ${buffer.length} bytes)`);
        migrated++;
        continue;
      }

      const { buffer, mimeType } = parsed;
      const ext = MIME_TO_EXT[mimeType] || 'png';
      const filename = `${uuidv4()}.${ext}`;
      const filePath = path.join(BRAND_ASSETS_DIR, filename);

      fs.writeFileSync(filePath, buffer);
      const url = `/uploads/brand-assets/${filename}`;

      // Phase 1: Set url, keep base64Data for rollback safety
      await collection.updateOne(
        { _id: doc._id },
        { $set: { url } }
        // Phase 2: also { $unset: { base64Data: "" } }
      );

      console.log(`✅ Migrated ${doc._id} -> ${url} (${mimeType}, ${buffer.length} bytes)`);
      migrated++;
    } catch (err: any) {
      console.error(`❌ Error migrating ${doc._id}:`, err.message);
      errors++;
    }
  }

  console.log('');
  console.log('═══════════════════════════════════════');
  console.log(`📊 Migration Summary:`);
  console.log(`   ✅ Migrated: ${migrated}`);
  console.log(`   ⏭️  Skipped:  ${skipped}`);
  console.log(`   ❌ Errors:    ${errors}`);
  console.log(`   📄 Total:     ${docs.length}`);
  console.log('═══════════════════════════════════════');
  console.log('');
  console.log('💡 Phase 1 complete: url fields set, base64Data preserved.');
  console.log('   After verifying images load correctly, run Phase 2:');
  console.log('   db.brandassets.updateMany({ url: /^\\/uploads\\/brand-assets/ }, { $unset: { base64Data: "" } })');

  await mongoose.disconnect();
  console.log('👋 Disconnected from MongoDB');
}

migrate().catch((err) => {
  console.error('Fatal error:', err);
  mongoose.disconnect();
  process.exit(1);
});