/**
 * Built-in Hypen Components
 * Framework-provided components like Router and Route
 */

import { app } from "../app.js";
import { frameworkLoggers } from "../logger.js";

const log = frameworkLoggers.router;

/**
 * Router Component
 * Automatically matches routes and renders the appropriate child Route
 *
 * Usage in Hypen DSL:
 * Router {
 *   Route(path: "/") { HomePage }
 *   Route(path: "/products") { ProductList }
 *   Route(path: "/users/:id") { UserProfile }
 * }
 */
export const Router = app
  .defineState(
    {
      currentPath: "/",
      matchedRoute: null as any,
      routeParams: {} as Record<string, string>,
    },
    { name: "__Router" }
  )
  .onCreated((state, context) => {
    if (!context) {
      log.error("Requires global context");
      return;
    }

    // Subscribe to router changes
    const router = context.router;
    if (!router) {
      log.error("Router not found in context");
      return;
    }

    // Get access to the Hypen engine for lazy rendering
    const hypenEngine = (context as any).__hypenEngine;

    // Function to render only the matching route
    const updateRouteVisibility = async (currentPath: string) => {
      // Find all Route elements in the DOM
      const routeElements = document.querySelectorAll(
        '[data-hypen-type="route"]'
      );

      let matchFound = false;

      for (let index = 0; index < routeElements.length; index++) {
        const routeEl = routeElements[index];
        const htmlEl = routeEl as HTMLElement;
        const routePath = htmlEl.dataset.routePath || "/";

        // Simple path matching (exact match for now)
        const isMatch = routePath === currentPath;

        // Only show the matching route, hide all others
        htmlEl.style.display = isMatch ? "flex" : "none";

        if (isMatch) {
          matchFound = true;

          // Check if this route needs to be rendered
          const componentName = htmlEl.dataset.routeComponent;
          const isLazy = htmlEl.dataset.routeLazy === "true";
          const hasContent = htmlEl.children.length > 0;

          // Render if route has no content and has a component name
          if (componentName && !hasContent && hypenEngine) {
            try {
              await hypenEngine.renderLazyRoute(
                routePath,
                componentName,
                htmlEl
              );
            } catch (err) {
              log.error(`Failed to render route ${routePath}:`, err);
            }
          }
        }
      }

      if (!matchFound) {
        log.warn(
          `No route matched path: ${currentPath}. Available routes:`,
          Array.from(routeElements).map(
            (el: Element) => (el as HTMLElement).dataset.routePath
          )
        );
      }
    };

    // Initial route visibility (after DOM is ready)
    setTimeout(() => {
      updateRouteVisibility(state.currentPath);
    }, 100);

    router.onNavigate((routeState) => {
      state.currentPath = routeState.currentPath;
      state.routeParams = routeState.params;

      // Update route visibility when path changes
      updateRouteVisibility(routeState.currentPath);
    });
  })
  .build();

/**
 * Route Component
 * Defines a route pattern and its content
 * This is just a marker component - Router processes it
 *
 * Props:
 * - path: string - Route pattern (e.g., "/", "/users/:id", "/dashboard/*")
 *
 * Usage:
 * Route(path: "/products") {
 *   ProductList
 * }
 */
export const Route = app.defineState({}, { name: "__Route" }).build();

/**
 * Navigation Link Component
 * Navigates to a route when clicked
 *
 * Props:
 * - to: string - Target path
 *
 * Usage:
 * Link(to: "/products") {
 *   Text("View Products")
 * }
 */
export const Link = app
  .defineState(
    {
      to: "/",
      isActive: false,
    },
    { name: "__Link" }
  )
  .onAction("navigate", ({ state, context }) => {
    const router = context?.router;
    if (!router) {
      log.error("Link requires router context");
      return;
    }

    const targetPath = state.to;
    router.push(targetPath);
  })
  .onCreated((state, context) => {
    if (!context) return;

    // Check if current path matches this link's target
    const router = context.router;
    if (router) {
      router.onNavigate((routeState) => {
        state.isActive = routeState.currentPath === state.to;
      });
    }
  })
  .build();
