import { useState } from 'react';

import { type FileCardType } from '@material-hu/components/design-system/FileCard/types';
import Uploader from '@material-hu/components/design-system/Uploader';

import { uploadOneFile } from 'src/services/attachments';
import { FileTypes } from 'src/types/attachments';
import { bytesFrom } from 'src/utils/bytes';

const MAX_FILE_ATTACHMENTS = 10;
const MAX_SIZE_PER_FILE = bytesFrom(100, 'MB');

type Props = {
  formValue: Record<string, unknown>[] | undefined;
  onChange: (value: Record<string, unknown>[] | undefined) => void;
  disabled: boolean;
  setUploadingFiles: React.Dispatch<
    React.SetStateAction<Record<string, boolean>>
  >;
  fieldName: string;
};

const FileUploader = ({
  formValue,
  onChange,
  disabled,
  setUploadingFiles,
  fieldName,
}: Props) => {
  const [loadingCards, setLoadingCards] = useState<FileCardType[]>([]);

  const existingFiles = Array.isArray(formValue) ? formValue : [];
  const fileByUrl = new Map(existingFiles.map(f => [f.url, f]));

  const settledCards = existingFiles.map(f => ({
    status: 'success' as const,
    attachment: {
      url: f.url,
      name: f.name,
      type: f.type || FileTypes.FILE,
      size: f.size || '0 B',
      bytes: 0,
    },
  }));

  const handleChange = (cards: FileCardType[]) => {
    const uploading = cards.filter(c => c.status === 'uploading');
    setLoadingCards(uploading);

    const files: Record<string, unknown>[] = [];
    for (const c of cards) {
      const att = c.attachment;
      if (c.status !== 'success' || !att) continue;

      const existing = fileByUrl.get(att.url);
      files.push(
        existing || {
          name: att.name,
          size: att.size,
          mime: c.file?.type || '',
          fileObject: c.file || {},
          type: FileTypes.FILE,
          toUpload: true,
          url: att.url,
        },
      );
    }

    onChange(files.length > 0 ? files : undefined);
  };

  const handleUpload = async (file: File) => {
    setUploadingFiles(prev => ({ ...prev, [fieldName]: true }));
    try {
      const result = await uploadOneFile({
        name: file.name,
        fileObject: file,
        contentType: file.type,
        size: file.size,
        type: FileTypes.FILE,
      });
      return {
        status: 'success' as const,
        file,
        attachment: {
          url: result.url ?? '',
          name: result.name ?? '',
          type: result.type || FileTypes.FILE,
          size: result.size || '0 B',
          bytes: file.size,
        },
      };
    } catch {
      return { status: 'error' as const, file };
    } finally {
      setUploadingFiles(prev => {
        const next = { ...prev };
        delete next[fieldName];
        return next;
      });
    }
  };

  return (
    <Uploader
      // biome-ignore lint/suspicious/noExplicitAny: bridging form value to FileCardType
      value={[...settledCards, ...loadingCards] as any}
      onChange={handleChange}
      // biome-ignore lint/suspicious/noExplicitAny: bridging upload result to FileCardType
      uploadFunction={handleUpload as any}
      triggerOnChangeWhenUploading
      acceptedTypes={['pdf', 'msword', 'compressed', 'xml']}
      maxFiles={MAX_FILE_ATTACHMENTS}
      fileSizeLimit={MAX_SIZE_PER_FILE}
      disabled={disabled}
      readOnly={disabled}
    />
  );
};

export default FileUploader;
