import { type FileUploadOptions } from '@material-hu/hooks/FileAssetUploader/useFileAssetUploader';
import { type FileAsset } from '@material-hu/types/attachments';

import api, { filesApi } from 'src/config/api';
import { DEFAULT_FILE_CARD_WIDTH } from 'src/pages/dashboard/serviceManagement/constants';
import {
  addFileType,
  compressFile,
  fileToAttachment,
  getArrayBuffer,
  getContentType,
  getFileNameExtension,
  isImage,
  isVideo,
  sanitizeFileName,
} from 'src/utils/files';

export const getImgDimensions = (numberOfImages: number) => {
  switch (numberOfImages) {
    case 1:
      return '280px';
    case 2:
      return '160px';
    case 3:
      return '125px';
    case 4:
      return '112px';
    default:
      return '104px';
  }
};

export const calculateFileCardWidth = (
  imageDimensions: string,
  numberOfImages: number,
  maxContainerWidth: number,
  gapBetweenImages: number,
) => {
  if (numberOfImages === 0) {
    return DEFAULT_FILE_CARD_WIDTH;
  }

  const imgWidth = parseInt(imageDimensions.replace('px', ''), 10); // Convert image dimensions to a number

  // Calculate the total width of each image including the gap (except after the last image in the row)
  const totalImageWidthWithGap = imgWidth + gapBetweenImages;

  // Calculate how many images fit in one row, considering the gap between images
  const imagesPerRow = Math.floor(
    (maxContainerWidth + gapBetweenImages) / totalImageWidthWithGap,
  );

  // If the number of images fits in one row, calculate the total width based on number of images and gaps
  if (numberOfImages <= imagesPerRow) {
    const totalWidth =
      imgWidth * numberOfImages + gapBetweenImages * (numberOfImages - 1);
    return `${totalWidth}px`;
  }

  // If images wrap, return the max container width
  return `${maxContainerWidth}px`;
};

export const signedUploadFile = async (
  file: File,
  isPublic = false,
  shouldCompress = true,
  signal?: any,
) => {
  const compressedFile = shouldCompress ? await compressFile(file) : file;
  const extension = getFileNameExtension(compressedFile.name);
  const arrayBuffer = await getArrayBuffer(compressedFile);
  const attachment = await fileToAttachment(compressedFile);
  const contentType = compressedFile.type || getContentType(extension || '');

  // For the time being, VIDEO types are not supported so it will be sent as a FILE instead
  const { data } = await api.post<FileAsset>('file-assets', {
    type: isVideo(compressedFile) ? 'FILE' : attachment.type,
    name: sanitizeFileName(attachment.name ?? compressedFile.name),
    contentType,
    width: attachment.width,
    height: attachment.height,
    size: attachment.size,
    public: isPublic,
  });

  // Use filesApi instead of api.put to avoid the transformRequest interceptor
  await filesApi.put(data.uploadUrl || '', arrayBuffer, {
    headers: {
      'Content-Type': contentType,
      'Content-Encoding': 'base64',
    },
    signal,
  });

  return data;
};

export const signedUploadWithOptions = (
  file: File,
  options?: FileUploadOptions,
) => {
  return signedUploadFile(
    addFileType(file),
    options?.isPublic ?? false,
    options?.shouldCompress ?? true,
    options?.signal,
  );
};

const getFiletype = (file: File) => {
  switch (true) {
    case isImage(file):
      return 'image';
    case isVideo(file):
      return 'video';
    default:
      return 'file';
  }
};

export const signedUpload = async (
  file: File,
  isPublic = false,
  shouldCompress = true,
  signal?: any,
) => {
  const compressedFile = shouldCompress ? await compressFile(file) : file;
  const extension = getFileNameExtension(compressedFile.name);

  const arrayBuffer = await getArrayBuffer(compressedFile);

  const fileType = getFiletype(compressedFile);
  const contentType = compressedFile.type || getContentType(extension || '');

  const signedURLResponse = await api.get<{ url: string }>('signed-url', {
    params: {
      fileName: `${file.type}.${extension}`.replace('/', '%2F'),
      contentType: contentType,
      type: fileType.toUpperCase(),
      public: isPublic,
    },
  });
  const {
    data: { url },
  } = signedURLResponse;

  // Use filesApi instead of api.put to avoid the transformRequest interceptor
  await filesApi.put(url, arrayBuffer, {
    headers: {
      'Content-Type': contentType,
      'Content-Encoding': 'base64',
    },
    signal,
  });

  return url;
};
