import { useRef, useState } from 'react';
import { uploadFileToOss, type OssMediaType } from '../lib/upload';
import { enqueueUpload } from '../lib/upload-lock';
import { toastError } from '../lib/toast';

type OssUploadFieldProps = {
  value?: string;
  onChange?: (url: string) => void;
  bizType: string;
  mediaType?: OssMediaType;
  accept?: string;
  wide?: boolean;
  compact?: boolean;
  label?: string;
};

const DEFAULT_MAX_MB = 10;

export default function OssUploadField({
  value,
  onChange,
  bizType,
  mediaType = 'IMAGE',
  accept,
  wide,
  compact,
  label,
}: OssUploadFieldProps) {
  const inputRef = useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState('');

  function showUploadError(text: string) {
    setError(text);
    toastError(text);
  }

  const resolvedAccept =
    accept ?? (mediaType === 'VIDEO' ? 'video/*' : mediaType === 'FILE' ? 'image/*,.pdf' : 'image/*');

  async function persistUpload(file: File) {
    if (!file.size) {
      showUploadError('图片读取失败，请重新选择');
      return;
    }
    if (file.size > DEFAULT_MAX_MB * 1024 * 1024) {
      showUploadError(`文件不能超过 ${DEFAULT_MAX_MB}MB`);
      return;
    }
    const result = await uploadFileToOss(file, { bizType, mediaType });
    onChange?.(result.url);
  }

  async function uploadSelectedFile(file: File) {
    setUploading(true);
    setError('');
    try {
      await enqueueUpload(() => persistUpload(file));
    } catch (e) {
      showUploadError(e instanceof Error ? e.message : '上传失败');
    } finally {
      setUploading(false);
      if (inputRef.current) inputRef.current.value = '';
    }
  }

  function pickFile() {
    if (uploading) return;
    setError('');
    inputRef.current?.click();
  }

  const isImage = mediaType === 'IMAGE' && value;
  const isFile = mediaType === 'FILE' && value;
  const busy = uploading;
  const pickerLabel = label ?? (mediaType === 'IMAGE' ? '从系统相册选择' : '点击上传');

  const triggerProps = {
    type: 'button' as const,
    disabled: busy,
    onClick: pickFile,
  };

  return (
    <div className="partner-oss-upload">
      <input
        ref={inputRef}
        type="file"
        accept={resolvedAccept}
        className="partner-oss-upload-input"
        disabled={busy}
        onChange={(e) => {
          const file = e.target.files?.[0];
          if (file) {
            void uploadSelectedFile(file);
          }
        }}
      />
      {isImage ? (
        <button {...triggerProps} className={`partner-upload-preview${wide ? ' partner-upload-preview--wide' : ''}`}>
          <img src={value} alt={label ?? '已上传'} />
          <span className="partner-upload-preview-mask">
            <span className="material-symbols-outlined">{busy ? 'hourglass_top' : 'edit'}</span>
            <span>{uploading ? '上传中…' : '更换'}</span>
          </span>
        </button>
      ) : isFile ? (
        <button {...triggerProps} className="partner-upload-file">
          <div className="partner-bills-icon" style={{ background: '#ffb3ae' }}>
            <span className="material-symbols-outlined text-primary">description</span>
          </div>
          <div style={{ textAlign: 'left', flex: 1 }}>
            <span className="text-primary" style={{ fontWeight: 700, display: 'block' }}>已上传合同</span>
            <span className="label-md text-muted">{uploading ? '上传中…' : '点击更换'}</span>
          </div>
        </button>
      ) : (
        <button
          {...triggerProps}
          className={`partner-upload-dashed${wide ? ' partner-upload-dashed--wide' : ''}${compact ? ' partner-upload-dashed--compact' : ''}`}
        >
          <span className="material-symbols-outlined text-primary" style={{ fontSize: compact ? 28 : 36 }}>
            {busy ? 'hourglass_top' : 'photo_library'}
          </span>
          <span className="text-primary" style={{ fontWeight: 500 }}>
            {uploading ? '上传中…' : pickerLabel}
          </span>
        </button>
      )}
      {error && <p className="partner-form-error" role="alert">{error}</p>}
    </div>
  );
}
