import * as React from 'react';
import {augmentImageFile, getMimeTypeDescription} from '@/utils/blob';
import {formatFileSize, formatNumeral} from '@/utils/numeral';
import clsx from 'clsx';
import {useFileMetadata, useFileUrl, useImageControls} from '@/categories/blob/react';
import {KeyValueTable} from '@/categories/information/react';
import {useEnhanced} from '@modal-soft/react-utils';
import {CommonPreviewProps} from '@/categories/blob/react/common';
import {Swatch} from '@tesseract-design/web-color-react';

export type ImageFilePreviewDerivedElement = HTMLImageElement;

export interface ImageFilePreviewProps<F extends Partial<File> = Partial<File>>
  extends Omit<React.HTMLProps<ImageFilePreviewDerivedElement>, 'src' | 'alt'>, CommonPreviewProps<F> {}

export const ImageFilePreview = React.forwardRef<ImageFilePreviewDerivedElement, ImageFilePreviewProps>(({
  file,
  className,
  style,
  disabled = false,
  enhanced: enhancedProp = false,
  ...etcProps
}, forwardedRef) => {
  const { fileWithUrl, loading: urlLoading } = useFileUrl({ file });
  const { fileWithMetadata, loading: metadataLoading, error } = useFileMetadata({
    file: fileWithUrl as File,
    augmentFunction: augmentImageFile,
  });

  const {
    fullScreen,
    handleAction,
    imageRef,
    filenameRef,
  } = useImageControls({
    forwardedRef,
  });

  const { enhanced } = useEnhanced({ enhanced: enhancedProp });

  if (!(fileWithMetadata)) {
    return null;
  }

  const cannotDisplayPicture = Boolean(
    typeof fileWithMetadata.url !== 'string'
    && error
  );

  return (
    <div
      className={clsx(
        'flex flex-col sm:grid sm:grid-cols-3 gap-8 w-full',
        className,
      )}
      style={style}
    >
      <div className="h-full relative">
        <div className="sm:absolute top-0 left-0 w-full sm:h-full z-[3]">
          {typeof fileWithMetadata.url === 'string' && (
            <img
              {...etcProps}
              ref={imageRef}
              className={clsx(
                'block h-full max-w-full object-center bg-[#000000]',
                {
                  'object-contain fixed w-full top-0 left-0 z-[3]': fullScreen,
                  'object-cover w-full': !fullScreen,
                },
              )}
              src={fileWithMetadata.url}
              alt=""
              data-testid="preview"
            />
          )}
          {cannotDisplayPicture && (
            <div className="w-full h-full flex items-center justify-center text-center px-4 bg-[#000000] select-none">
              {error!.message}
            </div>
          )}
        </div>
      </div>
      <div
        className="col-span-2 flex-shrink-0 m-0 flex flex-col gap-4 justify-between"
      >
        <KeyValueTable
          hiddenKeys
          data-testid="infoBox"
          properties={[
            Boolean(fileWithMetadata.name) && {
              key: 'Name',
              className: 'font-bold',
              valueProps: {
                ref: filenameRef,
                title: fileWithMetadata.name,
                children: fileWithMetadata.name,
              },
            },
            (enhanced && Boolean(getMimeTypeDescription(fileWithMetadata.type, fileWithMetadata.name) || '(Loading)') || Boolean(fileWithMetadata.type)) && {
              key: 'Type',
              valueProps: {
                className: clsx(
                  !getMimeTypeDescription(fileWithMetadata.type, fileWithMetadata.name) && 'opacity-50'
                ),
                children: getMimeTypeDescription(fileWithMetadata.type, fileWithMetadata.name) || '(Loading)',
              },
            },
            (enhanced && Boolean(formatFileSize(fileWithMetadata.size) || '(Loading)') || Boolean(fileWithMetadata.size)) && {
              key: 'Size',
              valueProps: {
                className: clsx(
                  !formatFileSize(fileWithMetadata.size) && 'opacity-50'
                ),
                title: `${formatNumeral(fileWithMetadata.size ?? 0)} byte(s)`,
                children: formatFileSize(fileWithMetadata.size) || '(Loading)',
              },
            },
            typeof fileWithMetadata.metadata?.width === 'number'
            && typeof fileWithMetadata.metadata?.height === 'number'
            && {
              key: 'Pixel Dimensions',
              valueProps: {
                children: `${formatNumeral(fileWithMetadata.metadata.width)} × ${formatNumeral(fileWithMetadata.metadata.height)} pixel(s)`,
              },
            },
            Array.isArray(fileWithMetadata.metadata?.palette)
            && {
              key: 'Palette',
              valueProps: {
                className: '-ml-4 pl-4 pt-4 ',
                children: (
                  <div className="flex flex-wrap gap-3">
                    {fileWithMetadata.metadata?.palette.map((rgb, i) => (
                      <React.Fragment
                        key={rgb.join(' ')}
                      >
                        {i > 0 && ' '}
                        <Swatch
                          color={rgb}
                          mode="rgb"
                        />
                      </React.Fragment>
                    ))}
                  </div>
                ),
              },
            },
          ]}
        />
        {enhanced && (
          <form
            onSubmit={handleAction}
            className="flex gap-4"
          >
            <fieldset
              disabled={disabled || cannotDisplayPicture}
              className="contents"
            >
              <legend className="sr-only">
                Controls
              </legend>
              <button
                type="submit"
                name="action"
                value="toggleFullScreen"
                className={clsx(
                  'h-12 flex text-primary disabled:text-primary focus:text-secondary active:text-tertiary items-center justify-center leading-none gap-4 select-none',
                  'focus:outline-0',
                  'disabled:opacity-50 disabled:cursor-not-allowed',
                  {
                    'fixed top-0 left-0 w-full h-full opacity-0 z-[3]': fullScreen,
                  }
                )}
              >
              <span
                className="block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded"
              >
                Preview
              </span>
              </button>
              {' '}
              <button
                type="submit"
                name="action"
                value="download"
                className={clsx(
                  'h-12 flex text-primary disabled:text-primary focus:text-secondary active:text-tertiary items-center justify-center leading-none gap-4 select-none',
                  'focus:outline-0',
                  'disabled:opacity-50 disabled:cursor-not-allowed',
                )}
              >
              <span
                className="block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded"
              >
                Download
              </span>
              </button>
            </fieldset>
          </form>
        )}
      </div>
    </div>
  );
});

ImageFilePreview.displayName = 'ImageFilePreview';
