import { useCallback, useEffect, useMemo, useState } from 'preact/hooks';
import { registerModule, type AsukaModuleComponent } from '../../core/modules';
import type { AsukaCanvas2DTextSelection } from '../../core/renderEngine';
import { useAsukaStore } from '../../store/asukaStore';
import { useT } from '../../hooks/useT';
import { getI18n } from '../../core/i18n';
import { Card, CardHeader, CardTitle, CardContent } from '../core/Card';
import { Field } from '../core/Field';
import { Select } from '../core/Select';
import { getSelectedRendererText, updateSelectedRendererText } from '../../core/rendererTextSelection';

const FontFamilyModule: AsukaModuleComponent = ({ context }) => {
  const t = useT();
  const [activeText, setActiveText] = useState<AsukaCanvas2DTextSelection | null>(null);
  const fontsCatalog = useAsukaStore((state: any) => state.fontsCatalog ?? []);
  const activeModuleId = useAsukaStore((state: any) => state.activeModuleId ?? null);
  const moduleOverlayStack = useAsukaStore((state: any) => state.moduleOverlayStack ?? []);
  const selectionMenuOpen = useAsukaStore((state: any) => state.selectionMenuOpen === true);
  const selectionMenuStack = useAsukaStore((state: any) => state.selectionMenuStack ?? []);
  const engine = context.getEngine?.() ?? null;

  const syncActiveText = useCallback(() => {
    setActiveText(getSelectedRendererText(engine));
  }, [engine]);

  useEffect(() => {
    syncActiveText();
    return engine?.events.subscribe(syncActiveText) ?? (() => {});
  }, [engine, syncActiveText]);

  const activeOverlayModuleId = moduleOverlayStack[moduleOverlayStack.length - 1] ?? activeModuleId;
  const activeSelectionModuleId = selectionMenuOpen
    ? selectionMenuStack[selectionMenuStack.length - 1] ?? null
    : null;
  const isVisible = activeOverlayModuleId === 'font-family' || activeSelectionModuleId === 'font-family';

  useEffect(() => {
    if (!isVisible) return;

    syncActiveText();
    const frame = requestAnimationFrame(syncActiveText);
    return () => cancelAnimationFrame(frame);
  }, [isVisible, syncActiveText]);

  const fontFamily = activeText?.fontFamily ?? 'Arial';
  const allowedFonts = useMemo(() => {
    const raw = activeText?.allowedFonts;
    return Array.isArray(raw) ? raw.map((value: any) => String(value ?? '').trim()).filter(Boolean) : [];
  }, [activeText]);

  const fontOptions = useMemo(() => {
    const catalog = Array.isArray(fontsCatalog) ? fontsCatalog : [];
    const filtered = allowedFonts.length
      ? catalog.filter((font: any) => allowedFonts.includes(String(font?.family ?? '')))
      : catalog;
    const mapped = filtered.map((font: any) => ({
      label: String(font?.family ?? ''),
      value: String(font?.family ?? ''),
    }));
    const hasCurrent = mapped.some((option: any) => option.value === fontFamily);
    if (!hasCurrent && fontFamily) mapped.unshift({ label: fontFamily, value: fontFamily });
    const seen = new Set<string>();
    return mapped.filter((option: any) => {
      const key = String(option.value ?? '');
      if (!key || seen.has(key)) return false;
      seen.add(key);
      return true;
    });
  }, [allowedFonts, fontFamily, fontsCatalog]);

  const applyFontFamily = (nextFamily: string) => {
    if (!activeText || !nextFamily || !engine) return;
    void updateSelectedRendererText(engine, { fontFamily: nextFamily }, { source: 'font-family' }).catch(() => {});
  };

  if (!activeText) {
    return (
      <Card>
        <CardHeader>
          <CardTitle>{t('fontFamily.title', 'Font family')}</CardTitle>
        </CardHeader>
        <CardContent>
          <p className="ask-text-[11px] ask-text-textMuted">{t('ui.select_a_text_object_to_edit_formatting', 'Select a text layer to edit formatting.')}</p>
        </CardContent>
      </Card>
    );
  }

  return (
    <Card>
      <CardHeader>
        <CardTitle>{t('fontFamily.title', 'Font family')}</CardTitle>
      </CardHeader>
      <CardContent className="ask-flex ask-flex-col ask-gap-4">
        <Field label={t('ui.font')}>
          <Select
            value={fontFamily}
            options={fontOptions}
            onChange={(e) => applyFontFamily((e.currentTarget as HTMLSelectElement).value)}
          />
        </Field>
      </CardContent>
    </Card>
  );
};

registerModule({
  id: 'font-family',
  title: getI18n().t('fontFamily.title', 'Font family'),
  icon: 'font-case',
  displayMode: 'floating',
  keepMounted: true,
  supportedEngines: ['fabric', '3d'],
  requiredCapabilities: ['objects'],
  render: FontFamilyModule,
});

export default FontFamilyModule;
