import * as Outline24 from '@heroicons/react/24/outline';
import * as Solid24 from '@heroicons/react/24/solid';
import * as Solid20 from '@heroicons/react/20/solid';
import * as Solid16 from '@heroicons/react/16/solid';

const colorClasses = {
  black: 'color-black',
  white: 'color-white',
  'gray-900': 'color-gray-900',
  'gray-700': 'color-gray-700',
  'gray-600': 'color-gray-600',
  'gray-500': 'color-gray-500',
  'gray-400': 'color-gray-400',
  'red-600': 'color-red-600',
  'red-500': 'color-red-500',
  'blue-600': 'color-blue-600',
  'green-600': 'color-green-600',
  'green-100': 'color-green-100',
  'yellow-500': 'text-yellow-500',
  'orange-500': 'text-orange-500',
};

const colorHex = {
  black: '#111827',
  white: '#ffffff',
  'gray-900': '#111827',
  'gray-700': '#374151',
  'gray-600': '#4b5563',
  'gray-500': '#6b7280',
  'gray-400': '#9ca3af',
  'red-600': '#dc2626',
  'red-500': '#ef4444',
  'blue-600': '#2563eb',
  'green-600': '#16a34a',
  'green-100': '#dcfce7',
  'yellow-500': '#f59e0b',
  'orange-500': '#f97316',
};

const iconSections = {
  header: [
    { name: 'header-bell', component: 'BellIcon' },
    { name: 'header-dropdown', component: 'ChevronDownIcon' },
  ],
  subheader: [
    { name: 'subheader-calendar', component: 'CalendarDaysIcon' },
    { name: 'subheader-chevron-right', component: 'ChevronRightIcon' },
    { name: 'subheader-swap', component: 'ArrowsRightLeftIcon' },
    { name: 'subheader-refresh', component: 'ArrowPathIcon' },
    { name: 'subheader-settings', component: 'AdjustmentsHorizontalIcon' },
  ],
  'sidebar-core': [
    { name: 'sidebar-core-collapse', component: 'ChevronDoubleLeftIcon' },
    { name: 'sidebar-core-dashboard', component: 'RectangleGroupIcon' },
    { name: 'sidebar-core-directory', component: 'UserGroupIcon' },
    { name: 'sidebar-core-inbox', component: 'InboxStackIcon' },
    { name: 'sidebar-core-favorites', component: 'HeartIcon' },
    { name: 'sidebar-core-announcements', component: 'MegaphoneIcon' },
    { name: 'sidebar-core-files', component: 'DocumentTextIcon' },
    { name: 'sidebar-core-tasks', component: 'ClipboardDocumentCheckIcon' },
    { name: 'sidebar-core-reports', component: 'ChartBarSquareIcon' },
    { name: 'sidebar-core-team', component: 'UsersIcon' },
    { name: 'sidebar-core-support', component: 'LifebuoyIcon' },
    { name: 'sidebar-core-sync', component: 'ArrowPathIcon' },
    { name: 'sidebar-core-settings', component: 'Cog8ToothIcon' },
    { name: 'sidebar-core-security', component: 'ShieldCheckIcon' },
    { name: 'sidebar-core-analytics', component: 'ChartBarIcon' },
    { name: 'sidebar-core-terminal', component: 'CommandLineIcon' },
    { name: 'sidebar-core-expand', component: 'ChevronDoubleRightIcon' },
    { name: 'sidebar-core-gear', component: 'Cog6ToothIcon' },
  ],
  'sidebar-point': [
    { name: 'sidebar-point-collapse', component: 'ChevronDoubleLeftIcon' },
    { name: 'sidebar-point-dashboard', component: 'SquaresPlusIcon' },
    { name: 'sidebar-point-up', component: 'ChevronUpIcon' },
    { name: 'sidebar-point-messages', component: 'ChatBubbleLeftRightIcon' },
    { name: 'sidebar-point-docs', component: 'DocumentDuplicateIcon' },
  ],
  modules: [
    { name: 'modules-progress', component: 'ArrowPathRoundedSquareIcon' },
    { name: 'modules-success', component: 'CheckCircleIcon' },
    { name: 'modules-info', component: 'InformationCircleIcon' },
    { name: 'modules-time', component: 'ClockIcon' },
  ],
  nuevos: [{ name: 'nuevos-eye', component: 'EyeIcon' }],
};

const curatedIcons = Object.values(iconSections)
  .flat()
  .reduce((acc, item) => {
    acc[item.name] = item.component;
    return acc;
  }, {});

const curatedIconNames = Object.keys(curatedIcons);
const iconLibraries = [
  { key: '24-outline', weight: 24, style: 'outline', lib: Outline24, defaultSize: 24 },
  { key: '24-solid', weight: 24, style: 'solid', lib: Solid24, defaultSize: 24 },
  { key: '20-solid', weight: 20, style: 'solid', lib: Solid20, defaultSize: 20 },
  { key: '16-solid', weight: 16, style: 'solid', lib: Solid16, defaultSize: 16 },
];
const heroiconComponentNames = Array.from(
  new Set(iconLibraries.flatMap(({ lib }) => Object.keys(lib)))
).sort();
const VARIANT_KEYS = iconLibraries.map(({ key }) => key);

const statusPalette = [
  { key: 'critical', fill: '#EF4444', subtle: '#FEE2E2' },
  { key: 'high', fill: '#F97316', subtle: '#FFEDD5' },
  { key: 'medium', fill: '#FACC15', subtle: '#FEF9C3' },
  { key: 'low', fill: '#22C55E', subtle: '#DCFCE7' },
  { key: 'info', fill: '#2563EB', subtle: '#DBEAFE' },
  { key: 'neutral', fill: '#94A3B8', subtle: '#E2E8F0' },
];

const statusIndicators = statusPalette.flatMap((status) => {
  const base = [
    {
      id: `status-${status.key}`,
      shape: 'circle',
      fill: status.fill,
      stroke: status.fill,
      variant: 'solid',
      group: 'circle',
      tone: status.key,
    },
    {
      id: `status-${status.key}-outline`,
      shape: 'circle',
      fill: status.subtle,
      stroke: status.fill,
      variant: 'outline',
      group: 'circle',
      tone: status.key,
    },
    {
      id: `status-${status.key}-triangle`,
      shape: 'triangle',
      fill: status.fill,
      stroke: status.fill,
      variant: 'solid',
      group: 'triangle',
      tone: status.key,
    },
    {
      id: `status-${status.key}-triangle-outline`,
      shape: 'triangle',
      fill: status.subtle,
      stroke: status.fill,
      variant: 'outline',
      group: 'triangle',
      tone: status.key,
    },
    {
      id: `status-${status.key}-square`,
      shape: 'square',
      fill: status.fill,
      stroke: status.fill,
      variant: 'solid',
      group: 'square',
      tone: status.key,
    },
    {
      id: `status-${status.key}-square-outline`,
      shape: 'square',
      fill: status.subtle,
      stroke: status.fill,
      variant: 'outline',
      group: 'square',
      tone: status.key,
    },
  ];

  return base;
});

const statusIndicatorMap = statusIndicators.reduce((acc, item) => {
  acc[item.id] = item;
  return acc;
}, {});

const capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);

const toPascalIconName = (value) => {
  if (!value) return value;
  const trimmed = value.replace(/icon$/i, '').trim();
  if (!trimmed) return value;

  const parts = trimmed
    .split(/[\s-_]+/)
    .filter(Boolean)
    .map((part) => capitalize(part.toLowerCase()));

  if (!parts.length) return value;
  return `${parts.join('')}Icon`;
};

const getHeroiconName = (name) => {
  if (curatedIcons[name]) return curatedIcons[name];
  if (HEROICON_COMPONENT_NAMES.includes(name)) return name;

  const candidate = toPascalIconName(name);
  return HEROICON_COMPONENT_NAMES.includes(candidate) ? candidate : name;
};

const resolveHexColor = (desiredColor, fallback) => {
  if (!desiredColor) return fallback;
  return colorHex[desiredColor] || desiredColor;
};

const renderStatus = (config, size, className, overrideColor, props) => {
  const viewBox = 24;
  const fillColor = resolveHexColor(overrideColor, config.fill);
  const strokeColor = resolveHexColor(overrideColor, config.stroke || config.fill);
  const strokeWidth = config.variant === 'outline' ? 2 : 0;

  if (config.shape === 'triangle') {
    return (
      <svg
        width={size}
        height={size}
        viewBox={`0 0 ${viewBox} ${viewBox}`}
        role="img"
        aria-hidden="true"
        className={className}
        {...props}
      >
        <polygon
          points="12,4 22,20 2,20"
          fill={fillColor}
          stroke={strokeWidth ? strokeColor : 'none'}
          strokeWidth={strokeWidth}
          strokeLinejoin="round"
        />
      </svg>
    );
  }

  if (config.shape === 'diamond') {
    return (
      <svg
        width={size}
        height={size}
        viewBox={`0 0 ${viewBox} ${viewBox}`}
        role="img"
        aria-hidden="true"
        className={className}
        {...props}
      >
        <polygon
          points="12,2 22,12 12,22 2,12"
          fill={fillColor}
          stroke={strokeWidth ? strokeColor : 'none'}
          strokeWidth={strokeWidth}
          strokeLinejoin="round"
        />
      </svg>
    );
  }

  if (config.shape === 'square') {
    return (
      <svg
        width={size}
        height={size}
        viewBox={`0 0 ${viewBox} ${viewBox}`}
        role="img"
        aria-hidden="true"
        className={className}
        {...props}
      >
        <rect
          x="5"
          y="5"
          width="14"
          height="14"
          rx={4}
          fill={fillColor}
          stroke={strokeWidth ? strokeColor : 'none'}
          strokeWidth={strokeWidth}
        />
      </svg>
    );
  }

  return (
    <svg
      width={size}
      height={size}
      viewBox={`0 0 ${viewBox} ${viewBox}`}
      role="img"
      aria-hidden="true"
      className={className}
      {...props}
    >
      <circle
        cx="12"
        cy="12"
        r="9"
        fill={fillColor}
        stroke={strokeWidth ? strokeColor : 'none'}
        strokeWidth={strokeWidth}
      />
    </svg>
  );
};

export const ICON_CATALOG = curatedIconNames;
export const ICON_SECTIONS = iconSections;
export const STATUS_INDICATORS = statusIndicators;
export const STATUS_CATALOG = statusIndicators.map(({ id }) => id);
export const ICON_COLOR_TOKENS = Object.keys(colorClasses);
export const HEROICON_COMPONENT_NAMES = heroiconComponentNames;
export const ICON_VARIANTS = VARIANT_KEYS;

export const Icon = ({
  name,
  variant = '24-outline',
  size,
  className = '',
  color,
  ...props
}) => {
  if (!name) {
    return null;
  }

  const statusConfig = statusIndicatorMap[name];
  if (statusConfig) {
    const statusSize = size ?? 18;
    return renderStatus(statusConfig, statusSize, className, color, props);
  }

  const iconName = getHeroiconName(name);
  const selectedLibrary = iconLibraries.find(({ key }) => key === variant) || iconLibraries[0];
  const fallbackLibrary = iconLibraries.find(
    ({ weight, style }) =>
      weight === selectedLibrary.weight && style !== selectedLibrary.style
  );
  const IconComponent =
    selectedLibrary.lib[iconName] ||
    (fallbackLibrary ? fallbackLibrary.lib[iconName] : null) ||
    Outline24[iconName] ||
    Solid24[iconName] ||
    Solid20[iconName] ||
    Solid16[iconName];

  if (!IconComponent) {
    console.warn(`Icon "${name}" not found in catalog`);
    return null;
  }

  const colorClass = color && colorClasses[color] ? colorClasses[color] : '';
  const classes = `${colorClass} ${className}`.trim();

  const finalSize = size ?? selectedLibrary.defaultSize;

  return <IconComponent className={classes} width={finalSize} height={finalSize} {...props} />;
};

export default Icon;
