import { getPayload } from 'payload';
import configPromise from '../payload.config';
import * as dotenv from 'dotenv';
dotenv.config();

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { parseMarkdownToLexical } from '../src/payload/utils/lexicalParser';

async function mapImageToMediaId(payload: any, imagePath: string): Promise<string | null> {
  if (!imagePath) return null;
  const filename = path.basename(imagePath);

  // Exact match instead of substring to avoid matching "cable-black.jpg" with "cable.jpg"
  const media = await payload.find({
    collection: 'media',
    where: {
      filename: {
        equals: filename,
      },
    },
    limit: 1,
  });

  if (media.docs.length > 0) {
    return media.docs[0].id;
  }

  const cleanPath = imagePath.startsWith('/') ? imagePath.slice(1) : imagePath;
  const fullPath = path.join(process.cwd(), 'public', cleanPath);

  if (fs.existsSync(fullPath)) {
    try {
      console.log(`[Products Migration] 📤 Ingesting missing Media into Payload: ${filename}`);
      const newMedia = await payload.create({
        collection: 'media',
        data: {
          alt: filename.replace(/[-_]/g, ' ').replace(/\.[^/.]+$/, ''),
        },
        filePath: fullPath,
      });
      return newMedia.id;
    } catch (err: any) {
      console.error(`[Products Migration] ❌ Failed to ingest ${filename}:`, err);
    }
  } else {
    console.warn(`[Products Migration] ⚠️ Missing image entirely from disk: ${fullPath}`);
  }
  return null;
}

export async function migrateProducts() {
  const payload = await getPayload({ config: configPromise });
  const productLocales = ['en', 'de'];

  for (const locale of productLocales) {
    const productsDir = path.join(process.cwd(), 'data', 'products', locale);
    if (!fs.existsSync(productsDir)) continue;

    // Recursive file finder
    const mdFiles: string[] = [];
    const walk = (dir: string) => {
      const files = fs.readdirSync(dir);
      for (const file of files) {
        const fullPath = path.join(dir, file);
        const stat = fs.statSync(fullPath);
        if (stat.isDirectory()) {
          walk(fullPath);
        } else if (file.endsWith('.mdx')) {
          mdFiles.push(fullPath);
        }
      }
    };
    walk(productsDir);

    for (const filePath of mdFiles) {
      const fileContent = fs.readFileSync(filePath, 'utf8');
      const { data, content } = matter(fileContent);

      console.log(`Processing Product: [${locale.toUpperCase()}] ${data.title}`);

      // 1. Process Images
      const mediaIds = [];
      if (data.images && Array.isArray(data.images)) {
        for (const imgPath of data.images) {
          const id = await mapImageToMediaId(payload, imgPath);
          if (id) mediaIds.push(id);
        }
      }

      // 2. Map Lexical AST for deeply nested components (like ProductTabs + Technical data)
      const lexicalContent = parseMarkdownToLexical(content);

      const wrapLexical = (blocks: any[]) => ({
        root: {
          type: 'root',
          format: '',
          indent: 0,
          version: 1,
          children: blocks,
          direction: 'ltr',
        },
      });

      // Payload expects category objects via the 'category' key
      const formattedCategories = Array.isArray(data.categories)
        ? data.categories.map((c: string) => ({ category: c }))
        : [];

      const productData = {
        title: data.title,
        sku: data.sku || path.basename(filePath, '.mdx'),
        slug: path.basename(filePath, '.mdx'),
        locale: locale as 'en' | 'de',
        categories: formattedCategories,
        description: data.description || '',
        featuredImage: mediaIds.length > 0 ? mediaIds[0] : undefined,
        images: mediaIds.length > 0 ? mediaIds : undefined,
        content: wrapLexical(lexicalContent) as any,
        application: data.application
          ? (wrapLexical(parseMarkdownToLexical(data.application)) as any)
          : undefined,
        _status: 'published' as any,
      };

      // Check if product exists (by sku combined with locale, since slug may differ by language)
      const existing = await payload.find({
        collection: 'products',
        where: {
          and: [{ slug: { equals: productData.slug } }, { locale: { equals: locale } }],
        },
      });

      if (existing.docs.length > 0) {
        console.log(`Updating existing product ${productData.slug} (${locale})`);
        await payload.update({
          collection: 'products',
          id: existing.docs[0].id,
          data: productData,
        });
      } else {
        console.log(`Creating new product ${productData.slug} (${locale})`);
        await payload.create({
          collection: 'products',
          data: productData,
        });
      }
    }
  }

  console.log(`\n✅ Products Migration Complete!`);
  process.exit(0);
}

migrateProducts().catch(console.error);
