
import { useCallback } from 'preact/hooks';

import { useT } from '../../hooks/useT';
import { registerModule, type AsukaModuleComponent } from '../../core/modules';

import { useAsukaStore, type UploadedAsset } from '../../store/asukaStore';
import { DEFAULT_PERMISSIONS } from '../../core/permissions';
import { hasConfiguredUploadPicker, openConfiguredUploadPicker, registerUploadSelection, resolveUploadedFileUrl, resolveUploadStrategy, type ResolvedUploadSelectionItem } from '../../core/images';
import { DEFAULT_ASUKA_UPLOAD_STRATEGY } from '../../types/options';

import { Card, CardHeader, CardTitle, CardContent } from '../core/Card';
import { FileDropzone } from '../core/FileDropzone';
import { Button } from '../core/Button';
import { IconButton } from '../core/IconButton';
import { AsukaIcon } from '../core/AsukaIcon';
import { List } from '../core/List';

function getAssetPreviewUrl(asset: UploadedAsset): string {
  return String(asset.previewUrl || asset.url || '').trim();
}

/**
 * Reusable upload panel used both stand-alone and inside the Images module.
 *
 * The list is backed by the shared uploadedAssets store so files uploaded through
 * the Upload module, canvas upload API, media inputs and custom upload handlers all
 * appear in the same place.
 */
export const UploadImagePanel: AsukaModuleComponent = ({ context }) => {
  const t = useT();
  const engine = context.getEngine?.() ?? null;
  const permissions = useAsukaStore((s: any) => s.permissions ?? DEFAULT_PERMISSIONS);
  const items = useAsukaStore((s: any): UploadedAsset[] => (Array.isArray(s.uploadedAssets) ? s.uploadedAssets : []));
  const registerUploadedAsset = useAsukaStore((s: any) => s.registerUploadedAsset);
  const removeUploadedAsset = useAsukaStore((s: any) => s.removeUploadedAsset);
  const clearUploadedAssets = useAsukaStore((s: any) => s.clearUploadedAssets);

  // Read upload config from init options (no in-module toggle).
  const uploadCfg = useAsukaStore((s: any) => s.moduleConfig?.upload);
  const multiple = Boolean(uploadCfg?.multiple);
  const autoAddOnSingle = uploadCfg?.autoAddOnSingle !== false;

  const canAddUploadToCanvas = Boolean((permissions as any)?.canUploadImage ?? true) && Boolean((permissions as any)?.canAddImage ?? true);

  const addImageToActiveEngine = useCallback(async (input: { file?: File; url?: string; src?: string; name?: string; source?: string; mode?: string; previewUrl?: string; metadata?: unknown }) => {
    if (!canAddUploadToCanvas || !engine) return;
    const resolvedUrl = input.file
      ? await resolveUploadedFileUrl(input.file, {
          upload: uploadCfg,
          defaultStrategy: DEFAULT_ASUKA_UPLOAD_STRATEGY,
          source: input.source ?? 'upload-module',
          mode: input.mode,
        })
      : (input.url || input.previewUrl || input.src);
    if (!resolvedUrl) return;
    await engine.objects.addImage({
      url: resolvedUrl,
      src: input.src,
      name: input.name,
      center: true,
      upload: uploadCfg,
      registerUploadedAsset: false,
      __skipRemoteImagePermissionCheck: true,
      metadata: { ...(input.metadata && typeof input.metadata === 'object' ? input.metadata as Record<string, unknown> : {}), source: input.source ?? 'upload-module', mode: input.mode, previewUrl: input.previewUrl },
    } as any);
  }, [canAddUploadToCanvas, engine, uploadCfg]);

  const addFilesToList = useCallback((files: File[]) => {
    if (!files?.length) return;

    for (const file of files) {
      registerUploadedAsset?.({
        file,
        source: 'upload-module',
        strategy: resolveUploadStrategy(uploadCfg),
        status: 'ready',
      });
    }

    // Workflow:
    // - single: optionally auto-add to canvas
    // - multiple: do NOT auto-add to avoid surprises/spam
    if (!multiple && autoAddOnSingle && canAddUploadToCanvas) {
      void addImageToActiveEngine({ file: files[0], source: 'upload-module' }).catch(() => {});
    }
  }, [addImageToActiveEngine, autoAddOnSingle, canAddUploadToCanvas, multiple, registerUploadedAsset, uploadCfg]);

  const addSelectedUploadToCanvas = useCallback((selection: ResolvedUploadSelectionItem) => {
    if (!canAddUploadToCanvas) return;
    void addImageToActiveEngine({
      file: selection.file,
      url: selection.url,
      src: selection.previewUrl,
      source: selection.source ?? 'upload-module',
      mode: selection.mode,
      name: selection.name,
      previewUrl: selection.previewUrl,
      metadata: selection.metadata,
    }).catch(() => {});
  }, [addImageToActiveEngine, canAddUploadToCanvas]);

  const hasUploadPicker = hasConfiguredUploadPicker(uploadCfg);
  const browseWithConfiguredPicker = useCallback(async () => {
    if (!hasConfiguredUploadPicker(uploadCfg)) return false;
    const selections = await openConfiguredUploadPicker(uploadCfg, {
      accept: 'image/*',
      multiple,
      source: 'upload-module',
      mode: 'image',
      kind: 'canvas-upload',
    });
    if (!selections) return false;
    if (!selections.length) return true;

    for (const selection of selections) {
      if (selection.file) {
        registerUploadedAsset?.({
          file: selection.file,
          source: selection.source ?? 'upload-module',
          mode: selection.mode ?? 'image',
          strategy: selection.strategy ?? resolveUploadStrategy(uploadCfg),
          status: 'ready',
          metadata: selection.metadata,
        });
      } else {
        registerUploadSelection(selection, { source: selection.source ?? 'upload-module', mode: selection.mode ?? 'image', strategy: selection.strategy ?? 'selected-url' });
      }
    }

    if (!multiple && autoAddOnSingle) {
      addSelectedUploadToCanvas(selections[0]);
    }

    return true;
  }, [addSelectedUploadToCanvas, autoAddOnSingle, multiple, registerUploadedAsset, uploadCfg]);

  const addToCanvas = (asset: UploadedAsset) => {
    if (!canAddUploadToCanvas) return;
    const url = String(asset.url || asset.previewUrl || '').trim();
    if (asset.file && (!url || /^blob:/i.test(url))) {
      void addImageToActiveEngine({ file: asset.file, source: asset.source ?? 'upload-module', mode: asset.mode, name: asset.name, metadata: asset.metadata }).catch(() => {});
      return;
    }
    if (url) {
      void addImageToActiveEngine({ url, source: asset.source, name: asset.name, previewUrl: asset.previewUrl, metadata: asset.metadata }).catch(() => {});
      return;
    }
    if (asset.file) void addImageToActiveEngine({ file: asset.file, source: 'upload-module', name: asset.name, metadata: asset.metadata }).catch(() => {});
  };

  return (
    <Card>
      <CardHeader>
        <CardTitle>{t('ui.upload')}</CardTitle>
      </CardHeader>

      <CardContent className="ask-flex ask-flex-col ask-gap-4">
        <FileDropzone
          accept="image/*"
          multiple={multiple}
          label={multiple ? 'Click or drop images here' : 'Click or drop an image here'}
          hint={multiple ? 'Multiple files allowed' : 'Single image'}
          uploadContext="canvas-upload"
          onBrowse={hasUploadPicker ? browseWithConfiguredPicker : undefined}
          onFiles={addFilesToList}
        />

        <List<UploadedAsset>
          header={
            <div className="ask-flex ask-items-center ask-justify-between">
              <div className="ask-text-[11px] ask-font-medium">{t('ui.uploaded_images')}</div>
              {items.length ? (
                <Button
                  size="sm"
                  variant="ghost"
                  onClick={() => {
                    clearUploadedAssets?.();
                  }}
                >
                  {t('common.clear', 'Clear')}
                </Button>
              ) : null}
            </div>
          }
          items={items}
          columns={2}
          getKey={(it) => it.id}
          empty={<div className="ask-text-[10px] ask-text-textMuted">{t('ui.no_uploads_yet')}</div>}
          renderItem={(it) => {
            const previewUrl = getAssetPreviewUrl(it);
            return (
              <div className="ask-overflow-hidden ask-rounded-[14px] ask-border ask-border-borderSubtle ask-bg-surfaceAlt">
                <button
                  type="button"
                  className="ask-block ask-w-full"
                  onClick={() => addToCanvas(it)}
                  title={t('ui.add_to_canvas')}
                >
                  {previewUrl ? (
                    <img src={previewUrl} alt={it.name} className="ask-h-24 ask-w-full ask-object-cover" loading="lazy" decoding="async" draggable={false} />
                  ) : (
                    <div className="ask-flex ask-h-24 ask-items-center ask-justify-center ask-text-[10px] ask-text-textMuted">{it.name}</div>
                  )}
                </button>

                <div className="ask-grid ask-grid-cols-[minmax(0,1fr)_auto] ask-items-center ask-gap-1 ask-p-2">
                  <Button size="sm" onClick={() => addToCanvas(it)}>{t('common.add', 'Add')}</Button>
                  <IconButton
                    variant="plain"
                    className="ask-text-textMuted hover:ask-text-danger"
                    title={t('common.remove', 'Remove')}
                    aria-label={t('common.remove', 'Remove')}
                    onClick={() => removeUploadedAsset?.(it.id)}
                  >
                    <AsukaIcon name="trash" size={15} />
                  </IconButton>
                </div>
              </div>
            );
          }}
        />
      </CardContent>
    </Card>
  );
};

registerModule({
  id: 'image-upload',
  label: 'Upload',
  icon: 'upload',
  displayMode: 'floating',
  keepMounted: true,
  supportedEngines: ['fabric', '3d'],
  requiredCapabilities: ['addImage'],
  render: UploadImagePanel,
});

export default UploadImagePanel;
