
import { useT } from '../../hooks/useT';
import { useEffect, useMemo, useState } from 'preact/hooks';
import { loadQrCodeGenerator } from '../../core/qrcodeRuntime';
import { registerModule, type AsukaModuleComponent } from '../../core/modules';
import { getI18n } from '../../core/i18n';

import { Card, CardHeader, CardTitle, CardContent } from '../core/Card';
import { Button } from '../core/Button';
import { Input } from '../core/Input';
import { Field } from '../core/Field';
import { Select } from '../core/Select';
import { ColorInput } from '../forms';

type ECLevel = 'L' | 'M' | 'Q' | 'H';

function clampInt(v: number, min: number, max: number) {

if (Number.isNaN(v)) return min;
  return Math.min(max, Math.max(min, Math.round(v)));
}

async function buildQrSvg(opts: {
  value: string;
  size: number; // px
  margin: number; // cells
  ecLevel: ECLevel;
  fg: string;
  bg: string;
}) {
  const value = opts.value.trim();
  const size = clampInt(opts.size, 64, 2048);
  const margin = clampInt(opts.margin, 0, 16);
  const ecLevel = opts.ecLevel;

  const qrcode = await loadQrCodeGenerator();
  const qr: any = (qrcode as any)(0, ecLevel);
  qr.addData(value);
  qr.make();

  const n = qr.getModuleCount();
  const vb = n + margin * 2;

  // Vector QR: 1 unit per cell, scaled via width/height.
  // Background
  const bgRect =
    opts.bg && opts.bg !== 'transparent'
      ? `<rect x="0" y="0" width="${vb}" height="${vb}" fill="${opts.bg}"/>`
      : '';

  const fg = opts.fg || '#000000';

  let rects = '';
  for (let r = 0; r < n; r++) {
    for (let c = 0; c < n; c++) {
      if (qr.isDark(r, c)) {
        rects += `<rect x="${c + margin}" y="${r + margin}" width="1" height="1" fill="${fg}"/>`;
      }
    }
  }

  const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${vb} ${vb}" shape-rendering="crispEdges">${bgRect}${rects}</svg>`;
  return { svg, size, n, vb };
}

/**
 * QR Code panel (offline).
 *
 * Generates a lightweight vector (SVG) QR code locally and adds it to the canvas via Fabric.
 */
export const QRCodePanel: AsukaModuleComponent = ({ context }) => {
  const t = useT();
  const [value, setValue] = useState('https://example.com');
  const [size, setSize] = useState(512);
  const [margin, setMargin] = useState(4);
  const [ecLevel, setEcLevel] = useState<ECLevel>('M');
  const [fg, setFg] = useState('#000000');
  const [bg, setBg] = useState('#ffffff');

  const canGenerate = useMemo(() => value.trim().length > 0, [value]);

  const [preview, setPreview] = useState<string | null>(null);

  useEffect(() => {
    let alive = true;
    if (!canGenerate) {
      setPreview(null);
      return () => { alive = false; };
    }
    buildQrSvg({ value, size, margin, ecLevel, fg, bg })
      .then((result) => { if (alive) setPreview(result.svg); })
      .catch(() => { if (alive) setPreview(null); });
    return () => { alive = false; };
  }, [value, size, margin, ecLevel, fg, bg, canGenerate]);

  const addToCanvas = async () => {
    if (!canGenerate) return;

    const { svg } = await buildQrSvg({ value, size, margin, ecLevel, fg, bg });
    const engine = context.getEngine?.() ?? null;
    if (!engine) return;

    await engine.objects.addDesign({
      svgText: svg,
      svg,
      url: `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`,
      name: 'QR Code',
      itemGroup: 'Images',
      center: true,
      metadata: {
        sourceModule: 'qrcode',
        itemGroup: 'Images',
        svg,
        qrCode: true,
        qrSvg: svg,
      },
      itemType: 'qr-code',
      sourceModule: 'qrcode',
      qrCode: true,
      qrSvg: svg,
    } as any);
  };

  return (
    <Card>
      <CardHeader className="ask-flex ask-items-center ask-justify-between ask-gap-2">
        <CardTitle>{t('ui.qr_code')}</CardTitle>
        <Button size="sm" onClick={addToCanvas} disabled={!canGenerate}>{t('ui.add_to_canvas')}</Button>
      </CardHeader>

      <CardContent className="ask-flex ask-flex-col ask-gap-4">
        <Field label={t('ui.value')} required>
          <Input required aria-required="true" value={value} onInput={(e) => setValue((e.target as HTMLInputElement).value)} placeholder={t('ui.text_or_url')} />
        </Field>

        <div className="ask-grid ask-grid-cols-2 ask-gap-3">
          <Field label={t('ui.size_px')} required>
            <Input
              required
              aria-required="true"
              type="number"
              value={String(size)}
              min={64}
              max={2048}
              step={16}
              onInput={(e) => setSize(Number((e.target as HTMLInputElement).value))}
            />
          </Field>

          <Field label={t('ui.margin_cells')} required>
            <Input
              required
              aria-required="true"
              type="number"
              value={String(margin)}
              min={0}
              max={16}
              step={1}
              onInput={(e) => setMargin(Number((e.target as HTMLInputElement).value))}
            />
          </Field>

          <Field label={t('ui.error_correction')} required>
            <Select
              required
              aria-required="true"
              value={ecLevel}
              onChange={(e) => setEcLevel((e.target as HTMLSelectElement).value as ECLevel)}
              options={[
                { label: t('qrcode.ecLevelLow', 'L (7%)'), value: 'L' },
                { label: t('qrcode.ecLevelMedium', 'M (15%)'), value: 'M' },
                { label: t('qrcode.ecLevelQuartile', 'Q (25%)'), value: 'Q' },
                { label: t('qrcode.ecLevelHigh', 'H (30%)'), value: 'H' },
              ]}
            />
          </Field>

          <div className="ask-grid ask-grid-cols-2 ask-gap-3">
            <Field label={t('ui.foreground')} required>
              <ColorInput required value={fg} colorLabel={t('ui.foreground')} onValueChange={setFg} />
            </Field>
            <Field label={t('ui.background')} required>
              <ColorInput required value={bg} colorLabel={t('ui.background')} onValueChange={setBg} />
            </Field>
          </div>
        </div>

        <div className="ask-mt-1 ask-rounded-xl ask-border ask-border-border ask-bg-surfaceAlt/50 ask-p-3">
          {preview ? (
            <>
              <div
                className="ask-flex ask-items-center ask-justify-center"
                dangerouslySetInnerHTML={{ __html: preview }}
              />
              <div className="ask-text-[12px] ask-text-textMuted"></div>
              <div className="ask-text-[12px] ask-text-textMuted">{t('ui.enter_a_value_to_preview')}</div>
            </>
          ) : null}
        </div>

        <div className="ask-text-[10px] ask-text-textMuted">{t('ui.generated_locally_offline_as_svg_for_crisp_scaling')}</div>
      </CardContent>
    </Card>
  );
};

registerModule({
  id: 'image-qrcode',
  label: getI18n().t('modules.qrcode-image'),
  icon: 'qr-code',
  displayMode: 'floating',
  supportedEngines: ['fabric', '3d'],
  requiredCapabilities: ['addImage'],
  render: QRCodePanel,
});

export default QRCodePanel;
