'use client';

import { useEffect, useState } from 'react';
import { File as FileFallback } from 'lucide-react';
import { cn } from '@djangocfg/ui-core/lib';

import { getMaterialIconsSync, loadMaterialIcons } from './loader';
import { resolveFolderIcon, type FolderIconOverrides } from './specialFolders';

export type FileIconSize = 12 | 14 | 16 | 18 | 20 | 24 | 28 | 32 | 40 | 48 | 64;

export interface FileIconProps {
  /** File name (with extension) or folder name. */
  name: string;
  /** Render a folder icon instead of a file icon. */
  isFolder?: boolean;
  /** Folder open / closed state. Ignored when `isFolder` is false. */
  isExpanded?: boolean;
  /** Pixel size of the icon. */
  size?: FileIconSize;
  /**
   * Override or extend the built-in special-folder mapping. Keys are
   * matched case-insensitively. Only used when `isFolder` is true.
   */
  folderOverrides?: FolderIconOverrides;
  className?: string;
}

/**
 * VSCode-style file icon.
 *
 * - Folders render Lucide `Folder` / `FolderOpen` (amber tint).
 * - Files use `material-file-icons` if it's installed in the consumer; otherwise
 *   fall back to a neutral Lucide `File` icon.
 *
 * The optional dependency is loaded lazily on first render — there is zero
 * bundle cost for consumers who never mount this component.
 */
export function FileIcon({
  name,
  isFolder = false,
  isExpanded = false,
  size = 16,
  folderOverrides,
  className,
}: FileIconProps) {
  const [svg, setSvg] = useState<string | null>(() => {
    if (isFolder) return null;
    const fn = getMaterialIconsSync();
    return fn ? (fn(name)?.svg ?? null) : null;
  });

  useEffect(() => {
    if (isFolder) {
      setSvg(null);
      return;
    }
    let cancelled = false;
    void loadMaterialIcons().then((fn) => {
      if (cancelled) return;
      setSvg(fn ? (fn(name)?.svg ?? null) : null);
    });
    return () => {
      cancelled = true;
    };
  }, [isFolder, name]);

  if (isFolder) {
    const Icon = resolveFolderIcon({
      name,
      isExpanded,
      overrides: folderOverrides,
    });
    return (
      <Icon
        className={cn('shrink-0 text-amber-500', className)}
        style={{ width: size, height: size }}
      />
    );
  }

  if (!svg) {
    return (
      <FileFallback
        className={cn('shrink-0 text-muted-foreground/80', className)}
        style={{ width: size, height: size }}
      />
    );
  }

  return (
    <span
      role="img"
      aria-hidden
      className={cn('inline-block shrink-0', className)}
      style={{ width: size, height: size }}
      dangerouslySetInnerHTML={{ __html: svg }}
    />
  );
}

export default FileIcon;
