import { useState, useCallback, useRef, useEffect } from 'react';
import type { ExtendedFile } from '@ablogcms/read-files';
import { DropZone } from '@ablogcms/components/drop-zone';
import MediaInsert from '@ablogcms/media/components/media-insert/media-insert';
import MediaUpdate from '@ablogcms/media/components/media-update/media-update';
import type { MediaItem, MediaViewFileType } from '@ablogcms/media/types';

interface DropAreaProps {
  mid?: number;
  thumbnail?: string;
  caption?: string;
  className?: string;
  mediaType?: 'image' | 'file' | 'all' | 'svg';
  onChange?: (items: MediaItem[]) => void;
  onError?: () => void;
}

function DropArea({
  mid: midProp = undefined,
  thumbnail: thumbnailProp = '',
  caption = '',
  className = '',
  mediaType = 'image',
  onChange = () => {},
  onError = () => {},
}: DropAreaProps) {
  const [mid, setMid] = useState(midProp);
  const [tab, setTab] = useState<'upload' | 'select'>('upload');
  const [insertModalOpened, setInsertModalOpened] = useState(false);
  const [updateModalOpened, setUpdateModalOpened] = useState(false);
  const [files, setFiles] = useState<File[]>([]);
  const [thumbnail, setThumbnail] = useState(thumbnailProp);
  const inputFileRef = useRef<HTMLInputElement>(null);

  const handleUpdateButtonClick = useCallback(() => {
    inputFileRef.current?.click();
  }, []);

  const handleComplete = useCallback((files: ExtendedFile[]) => {
    setFiles(files.map((item) => item.file));
    setInsertModalOpened(true);
  }, []);

  const uploadFile = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    if (!(event.target instanceof HTMLInputElement)) {
      return;
    }
    if (!event.target.files) {
      return;
    }
    setFiles(Array.from(event.target.files));
    setInsertModalOpened(true);
  }, []);

  const handleInsert = useCallback(
    (items: MediaItem[]) => {
      const [item] = items;
      const fileOrImage = item.media_type === 'image' || item.media_type === 'svg' ? 'image' : 'file';
      if (mediaType !== 'all' && mediaType !== fileOrImage) {
        onError();
        setInsertModalOpened(false);
        return;
      }
      setInsertModalOpened(false);
      setMid(item.media_id);
      setThumbnail(item.media_edited);
      onChange(items);
    },
    [mediaType, onError, onChange]
  );

  const onClose = useCallback(() => {
    setInsertModalOpened(false);
  }, []);

  const handleUpdateModalClose = useCallback(() => {
    setUpdateModalOpened(false);
  }, []);

  const selectMedia = useCallback(() => {
    setInsertModalOpened(true);
    setTab('select');
  }, []);

  const handleMediaUpdate = useCallback(
    (item: MediaItem) => {
      setUpdateModalOpened(false);
      setMid(item.media_id);
      setThumbnail(item.media_edited);
      onChange([item]);
    },
    [onChange]
  );

  const remove = useCallback(() => {
    setMid(undefined);
    onChange([]);
  }, [onChange]);

  const openEditModal = useCallback(() => {
    setUpdateModalOpened(true);
  }, []);

  useEffect(() => {
    const listener = (event: Event) => {
      if (!(event instanceof CustomEvent)) {
        return;
      }
      const media = event.detail.data as MediaItem;
      if (mid === media.media_id) {
        handleMediaUpdate(media);
      }
    };
    document.addEventListener('acms.media-updated', listener);
    return () => {
      document.removeEventListener('acms.media-updated', listener);
    };
  }, [mid, handleMediaUpdate]);

  return (
    <>
      <DropZone onComplete={handleComplete}>
        <div>
          {!mid && (
            <div className={`acms-admin-editor-media-box ${className}`}>
              <div className="acms-admin-editor-media-icon-wrap">
                <i className="acms-admin-icon acms-admin-icon-unit-image" />
              </div>
              <p className="acms-admin-media-unit-droparea-text">新規メディアを追加 または ファイルをドロップ</p>
              <div style={{ marginTop: '5px' }}>
                <button type="button" className="acms-admin-editor-media-btn" onClick={handleUpdateButtonClick}>
                  アップロード
                </button>
                <input
                  ref={inputFileRef}
                  id="input-file"
                  type="file"
                  onChange={uploadFile}
                  style={{ display: 'none' }}
                  multiple
                />
                <button type="button" className="acms-admin-editor-media-btn" onClick={selectMedia}>
                  メディアを選択
                </button>
              </div>
            </div>
          )}
          {mid && (
            <div className="acms-admin-media-unit-preview-wrap">
              <div className="acms-admin-media-unit-preview-overlay" />
              <button
                type="button"
                className="acms-admin-media-unit-preview-remove-btn"
                onClick={remove}
                aria-label={ACMS.i18n('media.clear_button_label')}
              />
              {(mediaType === 'image' || mediaType === 'svg') && (
                <img className="acms-admin-media-field-preview" src={`${thumbnail}`} alt="" />
              )}
              {mediaType === 'file' && (
                <div className="acms-admin-media-unit-file-icon-wrap">
                  <img className="acms-admin-media-unit-file-icon" src={`${thumbnail}`} alt="" />
                  <p className="acms-admin-media-unit-file-caption">{caption}</p>
                </div>
              )}
              <button
                type="button"
                className="acms-admin-media-edit-btn acms-admin-media-unit-preview-edit-btn"
                onClick={openEditModal}
              >
                編集
              </button>
            </div>
          )}
        </div>
      </DropZone>
      <MediaInsert
        isOpen={insertModalOpened}
        onInsert={handleInsert}
        files={files}
        onClose={onClose}
        tab={tab}
        filetype={['image', 'svg'].includes(mediaType) ? 'image' : (mediaType as MediaViewFileType)}
      />
      {mid != null && mid > 0 && (
        <MediaUpdate
          isOpen={updateModalOpened}
          mid={mid}
          onClose={handleUpdateModalClose}
          onUpdate={handleMediaUpdate}
        />
      )}
    </>
  );
}

export default DropArea;
