import { useEffect, useMemo, useState } from 'preact/hooks';
import { useT } from '../../hooks/useT';
import type { AsukaModuleComponent } from '../../core/modules';
import type { AsukaCanvas2DTextPatch, AsukaCanvas2DTextSelection } from '../../core/renderEngine';
import {
  getPaletteForActiveMethodOrFallback,
  getActivePrintingMethodId,
  setActivePrintingMethodId,
  getPrintingMethods,
  subscribePrintingConfig,
} from '../../core/printing';

import { Card, CardContent } from '../core/Card';
import { Field } from '../core/Field';
import { Select } from '../core/Select';
import { Input } from '../core/Input';
import { SegmentedControl } from '../core/SegmentedControl';
import { ToggleButton } from '../core/ToggleButton';
import { ColorSwatchGrid } from '../core/ColorSwatchGrid';
import { ColorInput } from '../forms';
import { useAsukaStore } from '../../store/asukaStore';
import { getSelectedRendererText, updateSelectedRendererText } from '../../core/rendererTextSelection';

const TYPO_PRESETS = [
  {
    value: 'body',
    label: 'Body',
    patch: { fontSize: 16, fontWeight: 'normal', lineHeight: 1.2, charSpacing: 0 },
  },
  {
    value: 'subtitle',
    label: 'Subtitle',
    patch: { fontSize: 20, fontWeight: 600, lineHeight: 1.2, charSpacing: 0 },
  },
  {
    value: 'title',
    label: 'Title',
    patch: { fontSize: 28, fontWeight: 700, lineHeight: 1.1, charSpacing: 0 },
  },
] as const;

export const TextFormattingFabricModule: AsukaModuleComponent = ({ context }) => {
  const t = useT();
  const [activeText, setActiveText] = useState<AsukaCanvas2DTextSelection | null>(null);
  const [printingTick, setPrintingTick] = useState(0);
  const fontsCatalog = useAsukaStore((state: any) => state.fontsCatalog ?? []);
  const engine = context.getEngine?.() ?? null;
  const textTools = engine?.canvas2d ?? null;

  useEffect(() => {
    const unsub = subscribePrintingConfig(() => setPrintingTick((t) => t + 1));
    return () => unsub?.();
  }, []);

  useEffect(() => {
    const sync = () => setActiveText(getSelectedRendererText(engine));
    sync();
    return engine?.events.subscribe(() => sync()) ?? (() => {});
  }, [engine]);

  const methods = useMemo(() => {
    void printingTick;
    return getPrintingMethods();
  }, [printingTick]);
  const activeMethodId = useMemo(() => {
    void printingTick;
    return getActivePrintingMethodId();
  }, [printingTick]);
  const palette = useMemo<any>(() => {
    void printingTick;
    return getPaletteForActiveMethodOrFallback() as any;
  }, [printingTick]);

  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 fontSize = Number(activeText?.fontSize ?? 16);
  const lineHeight = Number(activeText?.lineHeight ?? 1.2);
  const charSpacing = Number(activeText?.charSpacing ?? 0);
  const fill = activeText?.fill ?? '#111827';
  const textAlign = activeText?.textAlign ?? 'left';

  const fontWeight = String(activeText?.fontWeight ?? 'normal');
  const isBold = fontWeight === 'bold' || Number(fontWeight) >= 600;
  const isItalic = activeText?.fontStyle === 'italic';
  const isUnderline = Boolean(activeText?.underline);

  const applyPatch = (patch: AsukaCanvas2DTextPatch) => {
    if (!activeText || !engine) return;
    void updateSelectedRendererText(engine, patch, { source: 'text-formatting' }).catch(() => {});
  };

  const applyTextTransform = (mode: 'upper' | 'lower') => {
    if (!activeText) return;

    const next = mode === 'upper' ? activeText.text.toUpperCase() : activeText.text.toLowerCase();
    if (activeText.curved && textTools) {
      void textTools.updateSelectedTextCurve({ text: next }, { commit: true, source: 'text-case' }).catch(() => {});
      return;
    }
    applyPatch({ text: next });
  };

  if (!activeText) {
    return (
      <Card>
        <CardContent>
          <p className="ask-text-[12px] ask-leading-5 ask-text-textMuted">{t('ui.select_a_text_object_to_edit_formatting', 'Select a text layer to edit formatting.')}</p>
        </CardContent>
      </Card>
    );
  }

  return (
    <Card>
      <CardContent className="ask-flex ask-flex-col ask-gap-3">
        <div className="ask-rounded-2xl ask-border ask-border-borderSubtle ask-bg-surfaceAlt ask-p-3">
          <div className="ask-grid ask-grid-cols-[1fr_1.25fr] ask-gap-2">
            <Field label={t('ui.preset')}>
              <Select
                value=""
                options={TYPO_PRESETS.map((p) => ({ value: p.value, label: p.label }))}
                onChange={(e) => {
                  const v = (e.currentTarget as HTMLSelectElement).value;
                  const preset = TYPO_PRESETS.find((p) => p.value === v);
                  if (!preset) return;
                  applyPatch(preset.patch);
                }}
              />
            </Field>

            <Field label={t('ui.font')}>
              <Select
                value={fontFamily}
                options={fontOptions}
                onChange={(e) => {
                  const v = (e.currentTarget as HTMLSelectElement).value;
                  applyPatch({ fontFamily: v });
                }}
              />
            </Field>
          </div>
        </div>

        <div className="ask-rounded-2xl ask-border ask-border-borderSubtle ask-bg-surfaceAlt ask-p-3">
          <div className="ask-mb-2 ask-text-[12px] ask-font-semibold ask-text-text">{t('ui.typography', 'Typography')}</div>
          <div className="ask-grid ask-grid-cols-3 ask-gap-2">
            <label className="ask-flex ask-flex-col ask-gap-1">
              <span className="ask-text-[10px] ask-font-medium ask-text-textMuted">{t('ui.size')}</span>
              <Input
                type="number"
                value={String(fontSize)}
                onInput={(e) => applyPatch({ fontSize: Number((e.target as HTMLInputElement).value || 0) })}
                className="ask-h-9 ask-w-full"
              />
            </label>

            <label className="ask-flex ask-flex-col ask-gap-1">
              <span className="ask-text-[10px] ask-font-medium ask-text-textMuted">{t('ui.line_height')}</span>
              <Input
                type="number"
                step="0.05"
                value={String(lineHeight)}
                onInput={(e) => applyPatch({ lineHeight: Number((e.target as HTMLInputElement).value || 0) })}
                className="ask-h-9 ask-w-full"
              />
            </label>

            <label className="ask-flex ask-flex-col ask-gap-1">
              <span className="ask-text-[10px] ask-font-medium ask-text-textMuted">{t('ui.spacing', 'Spacing')}</span>
              <Input
                type="number"
                step="1"
                value={String(charSpacing)}
                onInput={(e) => applyPatch({ charSpacing: Number((e.target as HTMLInputElement).value || 0) })}
                className="ask-h-9 ask-w-full"
              />
            </label>
          </div>
        </div>

        <div className="ask-rounded-2xl ask-border ask-border-borderSubtle ask-bg-surfaceAlt ask-p-3">
          <div className="ask-grid ask-grid-cols-2 ask-gap-3">
            <div>
              <div className="ask-mb-2 ask-text-[12px] ask-font-semibold ask-text-text">{t('ui.style')}</div>
              <div className="ask-flex ask-flex-wrap ask-gap-2">
                <ToggleButton pressed={isBold} onClick={() => applyPatch({ fontWeight: isBold ? 'normal' : 'bold' })} title={t('ui.bold')}>
                  <span className="ask-font-semibold">B</span>
                </ToggleButton>

                <ToggleButton pressed={isItalic} onClick={() => applyPatch({ fontStyle: isItalic ? 'normal' : 'italic' })} title={t('ui.italic')}>
                  <span className="ask-italic">I</span>
                </ToggleButton>

                <ToggleButton pressed={isUnderline} onClick={() => applyPatch({ underline: !isUnderline })} title={t('ui.underline')}>
                  <span className="ask-underline">U</span>
                </ToggleButton>
              </div>
            </div>

            <div>
              <div className="ask-mb-2 ask-text-[12px] ask-font-semibold ask-text-text">{t('ui.case', 'Case')}</div>
              <div className="ask-flex ask-flex-wrap ask-gap-2">
                <ToggleButton onClick={() => applyTextTransform('upper')} title={t('ui.uppercase')}>{t('ui.upper','UPPER')}</ToggleButton>
                <ToggleButton onClick={() => applyTextTransform('lower')} title={t('ui.lowercase')}>{t('ui.lower','lower')}</ToggleButton>
              </div>
            </div>
          </div>

          <div className="ask-mt-3">
            <div className="ask-mb-2 ask-text-[12px] ask-font-semibold ask-text-text">{t('ui.align')}</div>
            <SegmentedControl
              value={textAlign}
              options={[
                { value: 'left', label: 'Left' },
                { value: 'center', label: 'Center' },
                { value: 'right', label: 'Right' },
                { value: 'justify', label: 'Justify' },
              ]}
              onChange={(v) => applyPatch({ textAlign: v })}
            />
          </div>
        </div>

        <div className="ask-rounded-2xl ask-border ask-border-borderSubtle ask-bg-surfaceAlt ask-p-3">
          <div className="ask-mb-2 ask-flex ask-items-center ask-justify-between ask-gap-2">
            <span className="ask-text-[12px] ask-font-semibold ask-text-text">{t('ui.text_color')}</span>
            <span className="ask-text-[10px] ask-text-textMuted">{fill}</span>
          </div>

          <div className="ask-flex ask-items-center ask-gap-2">
            <ColorInput
              value={fill}
              colorLabel={t('ui.text_color', 'Text color')}
              onValueChange={(value) => applyPatch({ fill: value })}
              wrapperClassName="ask-max-w-48"
            />
            {(palette as any)?.colors?.length ? (
              <div className="ask-min-w-0 ask-flex-1">
                <ColorSwatchGrid
                  colors={(palette as any).colors.map((c: any) => ({ id: c.id, label: c.name ?? c.label, value: c.value }))}
                  activeId={(palette as any).colors.find((c: any) => String(c?.value ?? '').toLowerCase() === String(fill ?? '').toLowerCase())?.id}
                  onChange={(c) => applyPatch({ fill: c.value })}
                />
              </div>
            ) : (
              <div className="ask-text-[11px] ask-text-textMuted">{t('ui.choose_custom_color', 'Choose a custom color.')}</div>
            )}
          </div>
        </div>

        <div className="ask-rounded-2xl ask-border ask-border-borderSubtle ask-bg-surfaceAlt ask-p-3">
          <Field label={t('ui.printing_method')}>
            <Select
              value={activeMethodId ?? 'all'}
              options={[
                { value: 'all', label: t('printing.allMethods', 'All methods') },
                ...(methods as any[]).map((m: any) => ({ value: m.id, label: m.name ?? m.label ?? m.id })),
              ]}
              onChange={(e) => {
                const v = (e.currentTarget as HTMLSelectElement).value;
                setActivePrintingMethodId(v === 'all' ? null : v);
              }}
            />
          </Field>
        </div>
      </CardContent>
    </Card>
  );
};

export default TextFormattingFabricModule;
