import path from 'path'
import { getFileByPath } from 'payload'
import { fileURLToPath } from 'url'

import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
import { devUser } from '../credentials.js'
import removeFiles from '../helpers/removeFiles.js'
import { AdminThumbnailFunction } from './collections/AdminThumbnailFunction/index.js'
import { AdminThumbnailSize } from './collections/AdminThumbnailSize/index.js'
import { AdminThumbnailWithSearchQueries } from './collections/AdminThumbnailWithSearchQueries/index.js'
import { CustomUploadFieldCollection } from './collections/CustomUploadField/index.js'
import { Uploads1 } from './collections/Upload1/index.js'
import { Uploads2 } from './collections/Upload2/index.js'
import {
  animatedTypeMedia,
  audioSlug,
  customFileNameMediaSlug,
  enlargeSlug,
  focalNoSizesSlug,
  hideFileInputOnCreateSlug,
  mediaSlug,
  mediaWithoutCacheTagsSlug,
  mediaWithoutRelationPreviewSlug,
  mediaWithRelationPreviewSlug,
  reduceSlug,
  relationPreviewSlug,
  relationSlug,
  unstoredMediaSlug,
  versionSlug,
} from './shared.js'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)

export default buildConfigWithDefaults({
  admin: {
    importMap: {
      baseDir: path.resolve(dirname),
    },
  },
  collections: [
    {
      slug: relationSlug,
      fields: [
        {
          name: 'image',
          type: 'upload',
          relationTo: 'media',
        },
        {
          name: 'versionedImage',
          type: 'upload',
          relationTo: versionSlug,
        },
        {
          name: 'hideFileInputOnCreate',
          type: 'upload',
          relationTo: hideFileInputOnCreateSlug,
        },
      ],
    },
    {
      slug: audioSlug,
      fields: [
        {
          name: 'audio',
          type: 'upload',
          filterOptions: {
            mimeType: {
              in: ['audio/mpeg'],
            },
          },
          relationTo: 'media',
        },
      ],
    },
    {
      slug: 'gif-resize',
      fields: [],
      upload: {
        formatOptions: {
          format: 'gif',
        },
        imageSizes: [
          {
            name: 'small',
            formatOptions: { format: 'gif', options: { quality: 90 } },
            height: 100,
            width: 100,
          },
          {
            name: 'large',
            formatOptions: { format: 'gif', options: { quality: 90 } },
            height: 1000,
            width: 1000,
          },
        ],
        mimeTypes: ['image/gif'],
        resizeOptions: {
          height: 200,
          position: 'center',
          width: 200,
        },
        staticDir: path.resolve(dirname, './media-gif'),
      },
    },
    {
      slug: 'filename-compound-index',
      fields: [
        {
          name: 'alt',
          type: 'text',
          admin: {
            description: 'Alt text to be used for compound index',
          },
        },
      ],
      upload: {
        filenameCompoundIndex: ['filename', 'alt'],
        imageSizes: [
          {
            name: 'small',
            formatOptions: { format: 'gif', options: { quality: 90 } },
            height: 100,
            width: 100,
          },
          {
            name: 'large',
            formatOptions: { format: 'gif', options: { quality: 90 } },
            height: 1000,
            width: 1000,
          },
        ],
        mimeTypes: ['image/*'],
      },
    },
    {
      slug: 'no-image-sizes',
      fields: [],
      upload: {
        mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'],
        resizeOptions: {
          height: 200,
          position: 'center',
          width: 200,
        },
        staticDir: path.resolve(dirname, './no-image-sizes'),
      },
    },
    {
      slug: 'object-fit',
      fields: [],
      upload: {
        imageSizes: [
          {
            name: 'fitContain',
            fit: 'contain',
            height: 300,
            width: 400,
          },
          {
            name: 'fitInside',
            fit: 'inside',
            height: 400,
            width: 300,
          },
          {
            name: 'fitCover',
            fit: 'cover',
            height: 300,
            width: 900,
          },
          {
            name: 'fitOutside',
            fit: 'outside',
            height: 200,
            width: 900,
          },
        ],
        mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'],
        staticDir: path.resolve(dirname, './object-fit'),
      },
    },
    {
      slug: 'with-meta-data',
      fields: [],
      upload: {
        imageSizes: [
          {
            name: 'sizeOne',
            height: 300,
            width: 400,
          },
        ],
        mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'],
        staticDir: path.resolve(dirname, './with-meta-data'),
        withMetadata: true,
      },
    },
    {
      slug: 'without-meta-data',
      fields: [],
      upload: {
        imageSizes: [
          {
            name: 'sizeTwo',
            height: 400,
            width: 300,
          },
        ],
        mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'],
        staticDir: path.resolve(dirname, './without-meta-data'),
        withMetadata: false,
      },
    },
    {
      slug: 'with-only-jpeg-meta-data',
      fields: [],
      upload: {
        imageSizes: [
          {
            name: 'sizeThree',
            height: 400,
            width: 300,
            withoutEnlargement: false,
          },
        ],
        staticDir: path.resolve(dirname, './with-only-jpeg-meta-data'),
        // eslint-disable-next-line @typescript-eslint/require-await
        withMetadata: async ({ metadata }) => {
          if (metadata.format === 'jpeg') {
            return true
          }
          return false
        },
      },
    },
    {
      slug: 'crop-only',
      fields: [],
      upload: {
        focalPoint: false,
        imageSizes: [
          {
            name: 'focalTest',
            height: 300,
            width: 400,
          },
          {
            name: 'focalTest2',
            height: 300,
            width: 600,
          },
          {
            name: 'focalTest3',
            height: 300,
            width: 900,
          },
        ],
        mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'],
        staticDir: path.resolve(dirname, './crop-only'),
      },
    },
    {
      slug: 'focal-only',
      fields: [],
      upload: {
        crop: false,
        imageSizes: [
          {
            name: 'focalTest',
            height: 300,
            width: 400,
          },
          {
            name: 'focalTest2',
            height: 300,
            width: 600,
          },
          {
            name: 'focalTest3',
            height: 300,
            width: 900,
          },
        ],
        mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'],
        staticDir: path.resolve(dirname, './focal-only'),
      },
    },
    {
      slug: focalNoSizesSlug,
      fields: [],
      upload: {
        crop: false,
        focalPoint: true,
        mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'],
        staticDir: path.resolve(dirname, './focal-no-sizes'),
      },
    },
    {
      slug: mediaSlug,
      fields: [],
      upload: {
        staticDir: path.resolve(dirname, './media'),
        // crop: false,
        // focalPoint: false,
        formatOptions: {
          format: 'png',
          options: { quality: 90 },
        },
        imageSizes: [
          {
            name: 'maintainedAspectRatio',
            crop: 'center',
            formatOptions: { format: 'png', options: { quality: 90 } },
            height: undefined,
            position: 'center',
            width: 1024,
          },
          {
            name: 'differentFormatFromMainImage',
            formatOptions: { format: 'jpg', options: { quality: 90 } },
            height: undefined,
            width: 200,
          },
          {
            name: 'maintainedImageSize',
            height: undefined,
            width: undefined,
          },
          {
            name: 'maintainedImageSizeWithNewFormat',
            formatOptions: { format: 'jpg', options: { quality: 90 } },
            height: undefined,
            width: undefined,
          },
          {
            name: 'accidentalSameSize',
            height: 80,
            position: 'top',
            width: 320,
          },
          {
            name: 'tablet',
            height: 480,
            width: 640,
          },
          {
            name: 'mobile',
            crop: 'left top',
            height: 240,
            width: 320,
          },
          {
            name: 'icon',
            height: 16,
            width: 16,
          },
          {
            name: 'focalTest',
            height: 300,
            width: 400,
          },
          {
            name: 'focalTest2',
            height: 300,
            width: 600,
          },
          {
            name: 'focalTest3',
            height: 300,
            width: 900,
          },
          {
            name: 'focalTest4',
            height: 400,
            width: 300,
          },
          {
            name: 'focalTest5',
            height: 600,
            width: 300,
          },
          {
            name: 'focalTest6',
            height: 800,
            width: 300,
          },
          {
            name: 'focalTest7',
            height: 300,
            width: 300,
          },
          {
            name: 'undefinedHeight',
            width: 300,
          },
        ],
        pasteURL: false,
      },
    },
    {
      slug: animatedTypeMedia,
      fields: [],
      upload: {
        staticDir: path.resolve(dirname, './media'),
        resizeOptions: {
          position: 'center',
          width: 200,
          height: 200,
        },
        imageSizes: [
          {
            name: 'squareSmall',
            width: 480,
            height: 480,
            position: 'centre',
            withoutEnlargement: false,
          },
          {
            name: 'undefinedHeight',
            width: 300,
            height: undefined,
          },
          {
            name: 'undefinedWidth',
            width: undefined,
            height: 300,
          },
          {
            name: 'undefinedAll',
            width: undefined,
            height: undefined,
          },
        ],
      },
    },
    {
      slug: enlargeSlug,
      fields: [],
      upload: {
        imageSizes: [
          {
            name: 'accidentalSameSize',
            height: 80,
            width: 320,
            withoutEnlargement: false,
          },
          {
            name: 'sameSizeWithNewFormat',
            formatOptions: { format: 'jpg', options: { quality: 90 } },
            height: 80,
            width: 320,
            withoutEnlargement: false,
          },
          {
            name: 'resizedLarger',
            height: 480,
            width: 640,
            withoutEnlargement: false,
          },
          {
            name: 'resizedSmaller',
            height: 50,
            width: 180,
          },
          {
            name: 'widthLowerHeightLarger',
            fit: 'contain',
            height: 300,
            width: 300,
          },
          {
            name: 'undefinedHeightWithoutEnlargement',
            width: 4000,
            height: undefined,
            withoutEnlargement: undefined,
          },
        ],
        mimeTypes: [
          'image/png',
          'image/jpg',
          'image/jpeg',
          'image/gif',
          'image/svg+xml',
          'audio/mpeg',
        ],
        staticDir: path.resolve(dirname, './media/enlarge'),
      },
    },
    {
      slug: reduceSlug,
      fields: [],
      upload: {
        imageSizes: [
          {
            name: 'accidentalSameSize',
            height: 80,
            width: 320,
            withoutEnlargement: false,
          },
          {
            name: 'sameSizeWithNewFormat',
            formatOptions: { format: 'jpg', options: { quality: 90 } },
            height: 80,
            width: 320,
            withoutReduction: true,
          },
          {
            name: 'resizedLarger',
            height: 480,
            width: 640,
          },
          {
            name: 'resizedSmaller',
            height: 50,
            width: 180,
            withoutReduction: true,
          },
        ],
        mimeTypes: [
          'image/png',
          'image/jpg',
          'image/jpeg',
          'image/gif',
          'image/svg+xml',
          'audio/mpeg',
        ],
        staticDir: path.resolve(dirname, './media/reduce'),
      },
    },
    {
      slug: 'media-trim',
      fields: [],
      upload: {
        imageSizes: [
          {
            name: 'trimNumber',
            height: undefined,
            trimOptions: 0,
            width: 1024,
          },
          {
            name: 'trimString',
            height: undefined,
            trimOptions: 0,
            width: 1024,
          },
          {
            name: 'trimOptions',
            height: undefined,
            trimOptions: {
              background: '#000000',
              threshold: 50,
            },
            width: 1024,
          },
        ],
        mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'],
        staticDir: path.resolve(dirname, './media-trim'),
        trimOptions: 0,
      },
    },
    {
      slug: customFileNameMediaSlug,
      fields: [],
      upload: {
        imageSizes: [
          {
            name: 'custom',
            height: 500,
            width: 500,
            generateImageName: ({ extension, height, width, sizeName }) =>
              `${sizeName}-${width}x${height}.${extension}`,
          },
        ],
        mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'],
        staticDir: path.resolve(dirname, `./${customFileNameMediaSlug}`),
      },
    },
    {
      slug: unstoredMediaSlug,
      fields: [],
      upload: {
        disableLocalStorage: true,
      },
    },
    {
      slug: 'externally-served-media',
      fields: [],
      upload: {
        // Either use another web server like `npx serve -l 4000` (http://localhost:4000) or use the static server from the previous collection to serve the media folder (http://localhost:3000/media)
        staticDir: path.resolve(dirname, './media'),
      },
    },
    Uploads1,
    Uploads2,
    AdminThumbnailFunction,
    AdminThumbnailWithSearchQueries,
    AdminThumbnailSize,
    {
      slug: 'optional-file',
      fields: [],
      upload: {
        filesRequiredOnCreate: false,
        staticDir: path.resolve(dirname, './optional'),
      },
    },
    {
      slug: 'required-file',
      fields: [],
      upload: {
        filesRequiredOnCreate: true,
        staticDir: path.resolve(dirname, './required'),
      },
    },
    {
      slug: versionSlug,
      fields: [
        {
          name: 'title',
          type: 'text',
        },
      ],
      upload: {
        filesRequiredOnCreate: true,
        staticDir: path.resolve(dirname, `./${versionSlug}`),
      },
      versions: {
        drafts: true,
      },
    },
    CustomUploadFieldCollection,
    {
      slug: mediaWithRelationPreviewSlug,
      fields: [
        {
          name: 'title',
          type: 'text',
        },
      ],
      upload: {
        displayPreview: true,
      },
    },
    {
      slug: mediaWithoutCacheTagsSlug,
      fields: [
        {
          name: 'title',
          type: 'text',
        },
      ],
      upload: {
        cacheTags: false,
      },
    },
    {
      slug: mediaWithoutRelationPreviewSlug,
      fields: [
        {
          name: 'title',
          type: 'text',
        },
      ],
      upload: {
        displayPreview: false,
      },
    },
    {
      slug: relationPreviewSlug,
      fields: [
        {
          name: 'imageWithPreview1',
          type: 'upload',
          relationTo: mediaWithRelationPreviewSlug,
        },
        {
          name: 'imageWithPreview2',
          type: 'upload',
          relationTo: mediaWithRelationPreviewSlug,
          displayPreview: true,
        },
        {
          name: 'imageWithoutPreview1',
          type: 'upload',
          relationTo: mediaWithRelationPreviewSlug,
          displayPreview: false,
        },
        {
          name: 'imageWithoutPreview2',
          type: 'upload',
          relationTo: mediaWithoutRelationPreviewSlug,
        },
        {
          name: 'imageWithPreview3',
          type: 'upload',
          relationTo: mediaWithoutRelationPreviewSlug,
          displayPreview: true,
        },
        {
          name: 'imageWithoutPreview3',
          type: 'upload',
          relationTo: mediaWithoutRelationPreviewSlug,
          displayPreview: false,
        },
      ],
    },
    {
      slug: hideFileInputOnCreateSlug,
      upload: {
        hideFileInputOnCreate: true,
        hideRemoveFile: true,
        staticDir: path.resolve(dirname, 'uploads'),
      },
      hooks: {
        beforeOperation: [
          ({ req, operation }) => {
            if (operation !== 'create') {
              return
            }
            const buffer = Buffer.from('This file was generated by a hook', 'utf-8')
            req.file = {
              name: `${new Date().toISOString()}.txt`,
              data: buffer,
              mimetype: 'text/plain',
              size: buffer.length,
            }
          },
        ],
      },
      fields: [
        {
          name: 'title',
          type: 'text',
        },
      ],
    },
  ],
  onInit: async (payload) => {
    const uploadsDir = path.resolve(dirname, './media')
    removeFiles(path.normalize(uploadsDir))

    await payload.create({
      collection: 'users',
      data: {
        email: devUser.email,
        password: devUser.password,
      },
    })

    // Create image
    const imageFilePath = path.resolve(dirname, './image.png')
    const imageFile = await getFileByPath(imageFilePath)

    const { id: uploadedImage } = await payload.create({
      collection: mediaSlug,
      data: {},
      file: imageFile,
    })

    const { id: versionedImage } = await payload.create({
      collection: versionSlug,
      data: {
        _status: 'published',
        title: 'upload',
      },
      file: imageFile,
    })

    await payload.create({
      collection: relationSlug,
      data: {
        image: uploadedImage,
        versionedImage,
      },
    })

    // Create animated type images
    const animatedImageFilePath = path.resolve(dirname, './animated.webp')
    const animatedImageFile = await getFileByPath(animatedImageFilePath)

    await payload.create({
      collection: animatedTypeMedia,
      data: {},
      file: animatedImageFile,
    })

    await payload.create({
      collection: versionSlug,
      data: {
        _status: 'published',
        title: 'upload',
      },
      file: animatedImageFile,
    })

    const nonAnimatedImageFilePath = path.resolve(dirname, './non-animated.webp')
    const nonAnimatedImageFile = await getFileByPath(nonAnimatedImageFilePath)

    await payload.create({
      collection: animatedTypeMedia,
      data: {},
      file: nonAnimatedImageFile,
    })

    await payload.create({
      collection: versionSlug,
      data: {
        _status: 'published',
        title: 'upload',
      },
      file: nonAnimatedImageFile,
    })

    // Create audio
    const audioFilePath = path.resolve(dirname, './audio.mp3')
    const audioFile = await getFileByPath(audioFilePath)

    const file = await payload.create({
      collection: mediaSlug,
      data: {},
      file: audioFile,
    })

    await payload.create({
      collection: audioSlug,
      data: {
        audio: file.id,
      },
    })

    // Create admin thumbnail media
    await payload.create({
      collection: AdminThumbnailSize.slug,
      data: {},
      file: {
        ...audioFile,
        name: 'audio-thumbnail.mp3', // Override to avoid conflicts
      },
    })

    await payload.create({
      collection: AdminThumbnailSize.slug,
      data: {},
      file: {
        ...imageFile,
        name: `thumb-${imageFile.name}`,
      },
    })

    await payload.create({
      collection: AdminThumbnailFunction.slug,
      data: {},
      file: {
        ...imageFile,
        name: `function-image-${imageFile.name}`,
      },
    })

    await payload.create({
      collection: AdminThumbnailWithSearchQueries.slug,
      data: {},
      file: {
        ...imageFile,
        name: `searchQueries-image-${imageFile.name}`,
      },
    })

    // Create media with and without relation preview
    const { id: uploadedImageWithPreview } = await payload.create({
      collection: mediaWithRelationPreviewSlug,
      data: {},
      file: imageFile,
    })

    await payload.create({
      collection: mediaWithoutCacheTagsSlug,
      data: {},
      file: {
        ...imageFile,
        name: `withoutCacheTags-image-${imageFile.name}`,
      },
    })

    const { id: uploadedImageWithoutPreview } = await payload.create({
      collection: mediaWithoutRelationPreviewSlug,
      data: {},
      file: imageFile,
    })

    await payload.create({
      collection: relationPreviewSlug,
      data: {
        imageWithPreview1: uploadedImageWithPreview,
        imageWithPreview2: uploadedImageWithPreview,
        imageWithoutPreview1: uploadedImageWithPreview,
        imageWithoutPreview2: uploadedImageWithoutPreview,
        imageWithPreview3: uploadedImageWithoutPreview,
        imageWithoutPreview3: uploadedImageWithoutPreview,
      },
    })

    await payload.create({
      collection: 'filename-compound-index',
      data: {
        alt: 'alt-1',
      },
      file: imageFile,
    })
  },
  serverURL: undefined,
  upload: {
    // debug: true,
    abortOnLimit: true,
    limits: {
      fileSize: 2_000_000, // 2MB
    },
  },
  typescript: {
    outputFile: path.resolve(dirname, 'payload-types.ts'),
  },
})
