import { RouteDto } from '@/proxy/routes/models'
import { lazy } from 'react'
import { useComponents } from '@/contexts/ComponentContext'

// Tüm view bileşenlerini import et (vite özel)
// shared klasörü hariç, çünkü bu bileşenler genellikle başka yerlerde statik import ediliyor
const modules = import.meta.glob(['../views/**/*.tsx', '!../views/shared/**/*.tsx'])

const lazyComponentCache = new Map<string, React.LazyExoticComponent<React.ComponentType<any>>>()

// ComponentPath'in fiziksel mi yoksa dinamik mi olduğunu belirle
function isPhysicalComponent(componentPath: string): boolean {
  // @ ile başlayan path'ler fiziksel dosya yolu
  // Başka bir kural: dynamic: ile başlayan path'ler dinamik
  return componentPath.startsWith('@/') || componentPath.startsWith('../')
}

function isDynamicComponent(componentPath: string): boolean {
  // dynamic: ile başlayan path'ler dinamik komponent
  return componentPath.startsWith('dynamic:')
}

// Fiziksel komponent yükleme (mevcut mantık)
function loadPhysicalComponent(componentPath: string) {
  const cleanedPath = componentPath.replace(/^@\//, '')
  const fullPath = `../${cleanedPath}.tsx`

  if (lazyComponentCache.has(fullPath)) {
    // console.log(`Physical component loaded from cache: ${fullPath}`)
    return lazyComponentCache.get(fullPath)!
  }

  const loader = modules[fullPath]
  if (!loader) {
    console.error(`Physical component not found for path: ${fullPath}`)
    throw new Error(`Physical component not found for path: ${fullPath}`)
  }

  const LazyComponent = lazy(loader as () => Promise<{ default: React.ComponentType<any> }>)
  lazyComponentCache.set(fullPath, LazyComponent)
  return LazyComponent
}

// Dinamik komponent yükleme (yeni mantık)
function loadDynamicComponent(
  componentPath: string, 
  registeredComponents: Record<string, React.ComponentType<unknown>>,
  renderComponent?: (name: string, props?: any) => React.ReactNode,
  isComponentRegistered?: (name: string) => boolean
) {
  const componentName = componentPath.replace('dynamic:', '')
  
  if (lazyComponentCache.has(componentPath)) {
    // console.log(`Dynamic component loaded from cache: ${componentName}`)
    return lazyComponentCache.get(componentPath)!
  }

  // Önce manuel registered komponentleri kontrol et
  let DynamicComponent = registeredComponents[componentName]
  
  // Eğer manuel registered'da yoksa, database compiled komponentleri kontrol et
  if (!DynamicComponent && isComponentRegistered && renderComponent && isComponentRegistered(componentName)) {
    DynamicComponent = (props: any) => renderComponent(componentName, props) as React.ReactElement
  }

  if (!DynamicComponent) {
    if (isComponentRegistered) {
      console.log('Database component registry available - checking...')
    }
    throw new Error(`Dynamic component not found: ${componentName}`)
  }

  // console.log(`Dynamic component loaded: ${componentName}`)
  // Dinamik komponent için lazy wrapper oluştur
  const LazyComponent = lazy(() => Promise.resolve({ default: DynamicComponent as React.ComponentType<any> }))
  lazyComponentCache.set(componentPath, LazyComponent)
  return LazyComponent
}

export function loadComponent(
  componentPath: string, 
  registeredComponents?: Record<string, React.ComponentType<unknown>>,
  renderComponent?: (name: string, props?: any) => React.ReactNode,
  isComponentRegistered?: (name: string) => boolean
) {
  if (isPhysicalComponent(componentPath)) {
    return loadPhysicalComponent(componentPath)
  } else if (isDynamicComponent(componentPath)) {
    if (!registeredComponents) {
      throw new Error('Registered components required for dynamic component loading')
    }
    return loadDynamicComponent(componentPath, registeredComponents, renderComponent, isComponentRegistered)
  } else {
    // Backward compatibility: varsayılan olarak fiziksel komponent kabul et
    return loadPhysicalComponent(componentPath)
  }
}

// React Router için uygun bir route tipi
export interface DynamicReactRoute {
  key: string
  path: string
  getComponent: (
    registeredComponents?: Record<string, React.ComponentType<unknown>>,
    renderComponent?: (name: string, props?: any) => React.ReactNode,
    isComponentRegistered?: (name: string) => boolean
  ) => React.LazyExoticComponent<React.ComponentType<any>>
  routeType: string
  authority?: string[]
  componentPath: string
  isPhysical: boolean
  isDynamic: boolean
}

// API'den gelen route objesini, React Router için uygun hale getirir
export function mapDynamicRoutes(routes: RouteDto[]): DynamicReactRoute[] {
  return routes.map((route) => ({
    key: route.path,
    path: route.path,
    getComponent: (registeredComponents, renderComponent, isComponentRegistered) => 
      loadComponent(route.componentPath, registeredComponents, renderComponent, isComponentRegistered),
    routeType: route.routeType,
    authority: route.authority,
    componentPath: route.componentPath,
    isPhysical: isPhysicalComponent(route.componentPath),
    isDynamic: isDynamicComponent(route.componentPath),
  }))
}
