import { chadsay } from "./src/core/lib/eggs/chadsay"
import type { Plugin } from "vite"

export const componentPathPlugin = (): Plugin => {
  const VIRTUAL_PLUGIN_MODULE = "virtual:plugin-key"
  const VIRTUAL_SETUP_MODULE = "virtual:plugin-setup"

  const resolvedPluginModuleId = "\0" + VIRTUAL_PLUGIN_MODULE
  const resolvedSetupModuleId = "\0" + VIRTUAL_SETUP_MODULE

  // Cache for path resolution
  let pluginPathMappingModule: string | null = null

  return {
    name: "vite-plugin-component-path",
    enforce: "pre", // Run before Vue compilation

    configResolved(config) {
      // We can use this hook to log debug info when Vite starts
      console.log("[componentPathPlugin] Plugin initialized")
      console.log("[componentPathPlugin] Vite mode:", config.mode)
      console.log("[componentPathPlugin] Vite root:", config.root)
      console.log(chadsay("Be aware of hot Cheese!"))
    },

    resolveId: (id) => {
      if (id === VIRTUAL_PLUGIN_MODULE) {
        return resolvedPluginModuleId
      }
      if (id === VIRTUAL_SETUP_MODULE) {
        return resolvedSetupModuleId
      }
    },

    load: (id) => {
      // Plugin key management module
      if (id === resolvedPluginModuleId) {
        return `
          const pluginKeyMap = new Map();
          
          export function definePluginKey(key, instanceId) {
            console.debug("[componentPathPlugin] Defining plugin key:", key, "for instance:", instanceId);
            pluginKeyMap.set(instanceId, key);
          }
          
          export function getCurrentPluginKey(instanceId) {
            const key = pluginKeyMap.get(instanceId);
            console.debug("[componentPathPlugin] Getting plugin key for instance:", instanceId, "result:", key);
            return key;
          }
          
          export function cleanupPluginKey(instanceId) {
            console.debug("[componentPathPlugin] Cleaning up plugin key for instance:", instanceId);
            pluginKeyMap.delete(instanceId);
          }
        `
      }

      // Setup module (pre-imports Vue dependencies)
      if (id === resolvedSetupModuleId) {
        return `
          import { getCurrentInstance, onUnmounted } from 'vue';
          import { definePluginKey, cleanupPluginKey } from 'virtual:plugin-key';
          import { pluginPathMapping } from '@racletteCore/setup/plugin-system';
          
          export function usePluginSetup(filePath, fallbackPluginKey) {
            const instance = getCurrentInstance();
            if (!instance) {
              console.error('Plugin setup must be called within component setup');
              return;
            }

            // Try to resolve plugin key from path mapping
            let pluginKey = null;
            
            // Find the matching path prefix in the mapping
            for (const [pathPrefix, identifier] of Object.entries(pluginPathMapping)) {
              if (filePath.includes(pathPrefix)) {
                pluginKey = identifier;
                break;
              }
            }
            
            // Use fallback if no match found
            if (!pluginKey && fallbackPluginKey) {
              pluginKey = fallbackPluginKey;
            }
            
            if (!pluginKey) {
              // this is expected for all widgets that are not coming from plugins
              // console.warn(\`[componentPathPlugin] Could not determine plugin key for \${filePath}\`);
              return;
            }

            definePluginKey(pluginKey, instance.uid);
            
            onUnmounted(() => {
              cleanupPluginKey(instance.uid);
            });
          }
        `
      }
    },

    transform: (code, id) => {
      // Only transform .vue files that might be in a plugin
      if (id.endsWith(".vue")) {
        // Use normalized path for consistent matching
        const normalizedPath = id.replace(/\\/g, "/")

        // Import for setup
        const setupImport = `import { usePluginSetup } from 'virtual:plugin-setup';`

        const scriptSetupMatch = code.match(
          /<script\b(?=[^>]*\bsetup\b)(?=[^>]*\blang=["']ts["'])?[^>]*>/,
        )

        // Check if we have <script setup>
        // Add to existing <script setup>
        if (scriptSetupMatch) {
          const insertIndex =
            scriptSetupMatch.index + scriptSetupMatch[0].length

          // TODO: support options api in the future
          return (
            code.slice(0, insertIndex) +
            `\n${setupImport}\nusePluginSetup('${normalizedPath}');\n` +
            code.slice(insertIndex)
          )
        }
        // Add new <script setup> block before any existing script

        const scriptSetup = `<script setup>\n${setupImport}\nusePluginSetup('${normalizedPath}');\n</script>\n\n`
        // Find existing script tag or insert at start
        const existingScript = code.match(/<script.*?>/)

        if (existingScript) {
          return (
            code.slice(0, existingScript.index) +
            scriptSetup +
            code.slice(existingScript.index)
          )
        }

        return scriptSetup + code
      }

      return code
    },

    // Add a custom handler for HMR to help with debugging
    handleHotUpdate({ file, modules }) {
      // This is helpful for debugging when components are updated
      // if (file.endsWith(".vue")) {
      //   console.log("[componentPathPlugin] File updated:", file)
      // }

      // Don't intercept the update - let Vite handle it normally
      return modules
    },
  }
}
