import Fuse from 'fuse.js';

// @ts-ignore
import config from '../../../../../../nitrogen.config.js';
import { Provider } from '../../../@types/settings.js';

import './ProvStrapi.scss';

const API_URL = config.apiUrl;
const API_TOKEN = import.meta.env.NITRO_API_TOKEN;
const STRAPI_COLLECTION =
  config.provider === 'strapi' ? config.strapi.collection : null;

const getFileUrl = (file: any) => `${API_URL.split('/api')[0]}${file.url}`;

const siteUrl = config.siteUrl;

const searchOptions = {
  keys: ['attributes.title'],
};

let allPages: { data: any[] } = { data: [] };
let fuse: Fuse<any> | null = null;

async function getPages() {
  const allPagesRes = await fetch(
    `http://localhost:1338/api/pages?pagination[start]=0&pagination[limit]=1000`
  );
  allPages = await allPagesRes.json();
}

async function getFuse() {
  if (fuse) return fuse;
  if (!allPages.data.length) await getPages();
  fuse = new Fuse(allPages.data, searchOptions);
  return fuse;
}

const strapi: Provider = {
  savePage: async (title, page, setPageId, pageId) => {
    if (pageId !== null && pageId !== undefined && pageId.trim() !== '') {
      await fetch(`${API_URL}/${STRAPI_COLLECTION}/${pageId}`, {
        method: 'PUT',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${API_TOKEN}`,
        },
        body: JSON.stringify({
          data: { title, data: page },
        }),
      });

      return;
    }

    const res = await fetch(`${API_URL}/${STRAPI_COLLECTION}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${API_TOKEN}`,
      },
      body: JSON.stringify({
        data: { title, data: page },
      }),
    });
    const data = await res.json();

    setPageId(`${data.data.id}`);
  },
  loadPage: async (pageId) => {
    const res = await fetch(`./pages/${pageId}.json`);
    const data = await res.json();

    return {
      title: data.data.attributes.title,
      data: data.data.attributes.data,
    };
  },
  searchUrls: async (
    query: string
  ): Promise<{ label: string; slug?: string; value: string }[]> => {
    if (query.length > 0) {
      const fuse = await getFuse();

      const fuseSearch = fuse.search(query);

      const data = fuseSearch.map((page) => ({
        label: page.item.attributes.title,
        slug: page.item.attributes.slug,
        value: siteUrl + page.item.attributes.slug,
      }));

      return data;
    }

    return [];
  },
  gallery: {
    getFileUrl,
    getFiles: async (setFiles, fileTypes) => {
      let filterQuery = '';

      if (fileTypes) {
        filterQuery = `?filters[ext][$in][]=${fileTypes.join(
          '&filters[ext][$in][]='
        )}`;
      }

      fetch(`${API_URL}/upload/files${filterQuery}`)
        .then((res) => res.json())
        .then((data) => {
          // sort by createdAt
          data.sort((a: any, b: any) => {
            return (
              new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
            );
          });
          setFiles(data);
        });
    },
    updateFile: (id, data) => {
      const formData = new FormData();

      formData.append('fileInfo', JSON.stringify(data));

      fetch(`${API_URL}/upload?id=${id}`, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${API_TOKEN}`,
        },
        body: formData,
      }).then(console.log);
    },
    uploadFiles: async (files) => {
      const formData = new FormData();

      files.forEach((file) => formData.append('files', file, file.name));

      const res = await fetch(`${API_URL}/upload`, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${API_TOKEN}`,
        },
        body: formData,
      });
      const data = await res.json();

      return data;
    },
    renderFiles: (files, selectedFile, setSelectedFile) => {
      return files.map((file) => (
        <div
          key={file.id}
          className={`strapi-gallery__container__file-container__single ${
            ['.png', '.svg', '.eps'].includes(file.ext)
              ? 'strapi-gallery__container__file-container__single-file--png-svg-eps'
              : ''
          } ${selectedFile?.id === file.id ? 'ring' : ''}`}
        >
          {file.mime.includes('image') ? (
            <img
              draggable={false}
              className={`strapi-gallery__container__file-container__single__img ${
                ['.png', '.svg', '.eps'].includes(file.ext)
                  ? 'strapi-gallery__container__file-container__single__img--object-contain'
                  : 'strapi-gallery__container__file-container__single__img--object-cover'
              }`}
              key={file.id}
              alt={file.alternativeText}
              src={`${API_URL.split('/api')[0]}${file.url}`}
              onClick={() => setSelectedFile(file)}
            />
          ) : (
            <div
              className='strapi-gallery__container__file-container__single__container'
              title={file.name}
              onClick={() => setSelectedFile(file)}
            >
              <div className='strapi-gallery__container__file-container__single__container__file'>
                <div className='strapi-gallery__container__file-container__single__container__file__name'>
                  {file.name.split('.')[0].length > 10 ? (
                    <span title={file.name}>
                      {file.name.split('.')[0].slice(0, 10)}...
                    </span>
                  ) : (
                    file.name.split('.')[0]
                  )}
                </div>
                <div className='strapi-gallery__container__file-container__single__container__file__ext'>
                  {file.ext}
                </div>
                <div className='strapi-gallery__container__file-container__single__container__file__size'>
                  {Math.round(file.size / 100) / 10} MB
                </div>
              </div>
            </div>
          )}
        </div>
      ));
    },
    renderSelectedFile: (selectedFile, updateFileData, details) => {
      const creationDate = new Date(selectedFile.createdAt);
      const creationDateFormatted = `${creationDate.getDate()}/${creationDate.getMonth()}/${creationDate.getFullYear()}`;
      return (
        <div className='strapi-selected-file-panel'>
          <div
            className={`strapi-selected-file-panel__img-container ${
              ['.png', '.svg', '.eps'].includes(selectedFile.ext)
                ? 'strapi-selected-file-panel__img-container--png-svg-eps'
                : ''
            }`}
          >
            {selectedFile.mime.includes('image') ? (
              <img
                draggable={false}
                className={`strapi-selected-file-panel__img-container__img ${
                  ['.png', '.svg', '.eps'].includes(selectedFile.ext)
                    ? 'strapi-selected-file-panel__img-container__img--object-contain'
                    : 'strapi-selected-file-panel__img-container__img--object-cover'
                }`}
                alt={selectedFile.alternativeText}
                src={getFileUrl(selectedFile)}
              />
            ) : (
              <div
                className='strapi-selected-file-panel__img-container__container'
                title={selectedFile.name}
              >
                <div className='strapi-selected-file-panel__img-container__container__file'>
                  <div className='strapi-selected-file-panel__img-container__container__file__name'>
                    {selectedFile.name.split('.')[0].length > 10 ? (
                      <span title={selectedFile.name}>
                        {selectedFile.name.split('.')[0].slice(0, 10)}...
                      </span>
                    ) : (
                      selectedFile.name.split('.')[0]
                    )}
                  </div>
                  <div className='strapi-selected-file-panel__img-container__container__file__ext'>
                    {selectedFile.ext}
                  </div>
                  <div className='strapi-selected-file-panel__img-container__container__file__size'>
                    {Math.round(selectedFile.size / 100) / 10} MB
                  </div>
                </div>
              </div>
            )}
          </div>
          {details && (
            <div className='strapi-selected-file-panel__details'>
              <div className=''>ID: {selectedFile.id}</div>
              <div className='strapi-selected-file-panel__details__filename'>
                {selectedFile.name}
              </div>
              <div className=''>{creationDateFormatted}</div>
              <div className=''>{selectedFile.size} KB</div>
              <div className=''>
                {selectedFile.width} by {selectedFile.height} pixels
              </div>
              <div className=''>Alt Text:</div>
              <textarea
                className='strapi-selected-file-panel__details__alt-text'
                value={selectedFile.alternativeText ?? ''}
                rows={3}
                onChange={(e) => {
                  updateFileData({
                    ...selectedFile,
                    alternativeText: e.target.value,
                  });
                }}
              ></textarea>
            </div>
          )}
        </div>
      );
    },
  },
};

export default strapi;
