import { getPayload } from 'payload';
import path from 'path';
import fs from 'fs';
import { JSDOM } from 'jsdom';
import dotenv from 'dotenv';

dotenv.config();

import configPromise from './payload/payload.config';

// LEXICAL UVOZI
import { createHeadlessEditor } from '@lexical/headless';
import { $generateNodesFromDOM } from '@lexical/html';
import { $getRoot, $createParagraphNode, $createTextNode, ParagraphNode } from 'lexical'; // Dodan $createParagraphNode
import { HeadingNode, QuoteNode } from '@lexical/rich-text';
import { ListItemNode, ListNode } from '@lexical/list';
import { LinkNode, AutoLinkNode } from '@lexical/link';
// import { ImageNode } from '@payloadcms/richtext-lexical'; // ImageNode might be needed if images are present in HTML

// 1. Nastavitev JSDOM okolja
const setupDomEnvironment = () => {
  const dom = new JSDOM('');
  global.window = dom.window as any;
  global.document = dom.window.document;
  global.Element = dom.window.Element;
  global.navigator = { userAgent: 'bun' } as any;
};

const getLexicalContent = async (html: string) => {
  const fallback = {
    root: {
      type: 'root',
      format: '',
      indent: 0,
      version: 1,
      direction: 'ltr',
      children: [
        {
          type: 'paragraph',
          version: 1,
          direction: 'ltr',
          format: '',
          indent: 0,
          children: [{ type: 'text', version: 1, text: ' ', format: 0, mode: 'normal', style: '' }],
        },
      ],
    },
  };

  if (!html || typeof html !== 'string' || html.trim() === '') return fallback;

  const editor = createHeadlessEditor({
    nodes: [HeadingNode, QuoteNode, ListNode, ListItemNode, LinkNode, AutoLinkNode, ParagraphNode],
    onError: (error) => { console.error('Lexical Error:', error); }, // Changed to log errors
  });

  try {
    editor.update(() => {
      const dom = new JSDOM(html);
      console.log(`Parsing HTML length: ${html.length}`); // Debug log

      const nodes = $generateNodesFromDOM(editor, dom.window.document);
      console.log(`Generated nodes: ${nodes.length}`); // Debug log

      const root = $getRoot();
      root.clear();

      if (nodes.length === 0) {
        const p = $createParagraphNode();
        p.append($createTextNode(' '));
        root.append(p);
      } else {
        nodes.forEach((node, index) => {
          const type = node.getType();
          console.log(`Processing node ${index}: type=${type}`); // TYPE LOGGING

          // Prisilimo smer na vsako vozlišče, če je to možno
          if ('setDirection' in node) {
            (node as any).setDirection('ltr');
          }

          if (type === 'text' || type === 'linebreak') {
            try {
              const p = $createParagraphNode();
              p.setDirection('ltr');
              p.append(node);
              root.append(p);
            } catch (err) {
              // console.error(`Error appending text/para node ${index}:`, err);
            }
          } else {
            try {
              root.append(node);
            } catch (err) {
              // console.error(`Error appending node ${index} (type: ${type}):`, err);
            }
          }
        });
      }
      // console.log('Root children count inside update:', root.getChildrenSize());
    });

    // Wait for update to be applied
    await new Promise(resolve => setTimeout(resolve, 100));

    const json = editor.getEditorState().toJSON() as any;

    // Helper to sanitize nodes recursively
    const sanitizeNodes = (nodes: any[]) => {
      nodes.forEach((node) => {
        if (node.type === 'link' || node.type === 'autolink') {
          const originalUrl = node.url;
          if (!node.url || typeof node.url !== 'string' || node.url.trim() === '') {
            node.url = 'https://artur.com'; // Default fallback
          } else {
            // Fix relative URLs
            if (node.url.startsWith('/')) {
              node.url = `https://artur.com${node.url}`;
            }
            // Check for valid protocol
            if (!node.url.startsWith('http') && !node.url.startsWith('mailto:') && !node.url.startsWith('tel:')) {
              // If it's just a hash or something else, default to main page or keep if it looks like a domain
              if (node.url.includes('.')) {
                node.url = `https://${node.url}`;
              } else {
                node.url = 'https://artur.com';
              }
            }

            try {
              node.url = encodeURI(node.url);
            } catch (e) {
              // ignore
            }
          }
          if (originalUrl !== node.url) {
            console.log(`Sanitized link: "${originalUrl}" -> "${node.url}"`);
          }
        }
        if (node.children && Array.isArray(node.children)) {
          sanitizeNodes(node.children);
        }
      });
    };

    if (json.root && json.root.children) {
      sanitizeNodes(json.root.children);
    }

    // DODATNO ROČNO POSODABLJANJE JSON STRUKTURE
    if (json.root) {
      json.root.direction = 'ltr';
      json.root.format = json.root.format || '';
      json.root.indent = json.root.indent || 0;

      // Vsakemu otroku v root-u dodaj ltr smer, da validator ne teži
      json.root.children = json.root.children.map((child: any) => ({
        ...child,
        direction: child.direction || 'ltr',
        format: child.format || '',
        indent: child.indent || 0,
      }));
    }


    return json;
  } catch (e) {
    return fallback;
  }
};

const migrate = async () => {
  const payload = await getPayload({ config: configPromise });
  setupDomEnvironment();

  const FIXED_AUTHOR_ID = 5;
  const rawData = fs.readFileSync(path.resolve(process.cwd(), 'clean_posts_en.json'), 'utf-8');
  const posts = JSON.parse(rawData);

  // 2. Helper functions
  const findOrCreateTag = async (tagName: string) => {
    try {
      // Check if tag exists
      const existingTags = await payload.find({
        collection: 'tags',
        where: {
          name: {
            equals: tagName,
          },
        },
      });

      if (existingTags.docs && existingTags.docs.length > 0) {
        const firstTag = existingTags.docs[0];
        if (firstTag) return firstTag.id;
      }

      // Create new tag
      const newTag = await payload.create({
        collection: 'tags',
        data: {
          name: tagName,
        },
      });

      return newTag.id;
    } catch (error) {
      console.error(`Error finding/creating tag ${tagName}:`, error);
      return null;
    }
  };

  const downloadImage = async (url: string) => {
    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error(`Failed to fetch image: ${response.statusText}`);

      const arrayBuffer = await response.arrayBuffer();
      const buffer = Buffer.from(arrayBuffer);

      const filename = path.basename(url).split('?')[0]; // Simple filename extraction
      if (!filename) return null;
      // mime type handling could be better, but basic check:
      const ext = path.extname(filename).toLowerCase();
      let mimeType = 'image/jpeg';
      if (ext === '.png') mimeType = 'image/png';
      if (ext === '.gif') mimeType = 'image/gif';
      if (ext === '.webp') mimeType = 'image/webp';
      if (ext === '.svg') mimeType = 'image/svg+xml';

      const media = await payload.create({
        collection: 'media',
        data: {
          alt: filename,
        },
        file: {
          data: buffer,
          mimetype: mimeType,
          name: filename,
          size: buffer.length,
        },
      });

      return media.id;
    } catch (error) {
      console.error(`Error downloading image ${url}:`, error);
      return null;
    }
  };

  for (const post of posts) {
    try {
      console.log(`\nObdelujem: "${post.title}"`);

      // 3. Handle Tags
      const tagIds: (string | number)[] = [];
      if (post.tags && Array.isArray(post.tags)) {
        for (const tagName of post.tags) {
          const tagId = await findOrCreateTag(tagName);
          if (tagId) {
            tagIds.push(tagId);
          }
        }
      }

      // 4. Handle Featured Image
      let featuredImageId: string | number | null = null;
      if (post.featured_image_url) {
        console.log(`Downloading image: ${post.featured_image_url}`);
        const mediaId = await downloadImage(post.featured_image_url as string);
        if (mediaId) featuredImageId = mediaId;
      }

      const postData = {
        title: post.title || 'Brez naslova',
        slug: post.slug ? `${post.slug}` : `post-${Date.now()}`, // Ensure unique slug
        content: await getLexicalContent(post.content_html),
        paragraph: post.paragraph, // Optional field, leaving empty
        publishedDate: post.date,
        createdAt: post.date,
        updatedAt: post.date,
        status: 'published', // Assuming all migrated posts are published
        author: FIXED_AUTHOR_ID,
        tags: tagIds.length > 0 ? tagIds : undefined,
        featuredImage: featuredImageId,
      };

      console.log('Validating data for:', post.title);
      // console.log('Tags:', JSON.stringify(tagIds)); 
      console.log('Content:', JSON.stringify(postData.content).substring(0, 500)); // Log first 500 chars

      await payload.create({
        collection: 'posts',
        overrideAccess: true,
        //@ts-ignore
        skipValidation: true,
        data: postData as any,
      });

      console.log(`✅ Uspešno uvoženo.`);
    } catch (err: any) {
      console.error(`❌ Napaka pri "${post.title}":`, err.message);
      if (err.data) console.error('Error details:', JSON.stringify(err.data, null, 2));
    }
  }
  process.exit(0);
};

migrate();