import React, { useEffect, useState } from 'react';
import { useAuth, useConfig } from '@payloadcms/config-provider';
import { useRouteMatch } from 'react-router-dom';
import format from 'date-fns/format';
import usePayloadAPI from '../../../hooks/usePayloadAPI';
import Eyebrow from '../../elements/Eyebrow';
import Loading from '../../elements/Loading';
import { useStepNav } from '../../elements/StepNav';
import { StepNavItem } from '../../elements/StepNav/types';
import Meta from '../../utilities/Meta';
import { LocaleOption, CompareOption, Props } from './types';
import CompareVersion from './Compare';
import { mostRecentVersionOption } from './shared';
import Restore from './Restore';
import SelectLocales from './SelectLocales';
import RenderFieldsToDiff from './RenderFieldsToDiff';
import fieldComponents from './RenderFieldsToDiff/fields';

import { Field } from '../../../../fields/config/types';
import { FieldPermissions } from '../../../../auth';

import './index.scss';

const baseClass = 'view-version';

const VersionView: React.FC<Props> = ({ collection, global }) => {
  const { serverURL, routes: { admin, api }, admin: { dateFormat }, localization } = useConfig();
  const { setStepNav } = useStepNav();
  const { params: { id, versionID } } = useRouteMatch<{ id?: string, versionID: string }>();
  const [compareValue, setCompareValue] = useState<CompareOption>(mostRecentVersionOption);
  const [localeOptions] = useState<LocaleOption[]>(() => (localization?.locales ? localization.locales.map((locale) => ({ label: locale, value: locale })) : []));
  const [locales, setLocales] = useState<LocaleOption[]>(localeOptions);
  const { permissions } = useAuth();

  let originalDocFetchURL: string;
  let versionFetchURL: string;
  let entityLabel: string;
  let fields: Field[];
  let fieldPermissions: Record<string, FieldPermissions>;
  let compareBaseURL: string;
  let slug: string;
  let parentID: string;

  if (collection) {
    ({ slug } = collection);
    originalDocFetchURL = `${serverURL}${api}/${slug}/${id}`;
    versionFetchURL = `${serverURL}${api}/${slug}/versions/${versionID}`;
    compareBaseURL = `${serverURL}${api}/${slug}/versions`;
    entityLabel = collection.labels.singular;
    parentID = id;
    fields = collection.fields;
    fieldPermissions = permissions.collections[collection.slug].fields;
  }

  if (global) {
    ({ slug } = global);
    originalDocFetchURL = `${serverURL}${api}/globals/${slug}`;
    versionFetchURL = `${serverURL}${api}/globals/${slug}/versions/${versionID}`;
    compareBaseURL = `${serverURL}${api}/globals/${slug}/versions`;
    entityLabel = global.label;
    fields = global.fields;
    fieldPermissions = permissions.globals[global.slug].fields;
  }

  const useAsTitle = collection?.admin?.useAsTitle || 'id';

  const compareFetchURL = compareValue?.value === 'mostRecent' ? originalDocFetchURL : `${compareBaseURL}/${compareValue.value}`;

  const [{ data: doc, isLoading }] = usePayloadAPI(versionFetchURL, { initialParams: { locale: '*', depth: 1 } });
  const [{ data: originalDoc }] = usePayloadAPI(originalDocFetchURL, { initialParams: { depth: 1, draft: 'true' } });
  const [{ data: compareDoc }] = usePayloadAPI(compareFetchURL, { initialParams: { locale: '*', depth: 1, draft: 'true' } });

  useEffect(() => {
    let nav: StepNavItem[] = [];

    if (collection) {
      let docLabel = '';

      if (originalDoc) {
        if (useAsTitle) {
          if (originalDoc[useAsTitle]) {
            docLabel = originalDoc[useAsTitle];
          } else {
            docLabel = '[Untitled]';
          }
        } else {
          docLabel = originalDoc.id;
        }
      }

      nav = [
        {
          url: `${admin}/collections/${collection.slug}`,
          label: collection.labels.plural,
        },
        {
          label: docLabel,
          url: `${admin}/collections/${collection.slug}/${id}`,
        },
        {
          label: 'Versions',
          url: `${admin}/collections/${collection.slug}/${id}/versions`,
        },
        {
          label: doc?.createdAt ? format(new Date(doc.createdAt), dateFormat) : '',
        },
      ];
    }

    if (global) {
      nav = [
        {
          url: `${admin}/globals/${global.slug}`,
          label: global.label,
        },
        {
          label: 'Versions',
          url: `${admin}/globals/${global.slug}/versions`,
        },
        {
          label: doc?.createdAt ? format(new Date(doc.createdAt), dateFormat) : '',
        },
      ];
    }

    setStepNav(nav);
  }, [setStepNav, collection, global, useAsTitle, dateFormat, doc, originalDoc, admin, id]);

  let metaTitle: string;
  let metaDesc: string;
  const formattedCreatedAt = doc?.createdAt ? format(new Date(doc.createdAt), dateFormat) : '';

  if (collection) {
    metaTitle = `Version - ${formattedCreatedAt} - ${doc[useAsTitle]} - ${entityLabel}`;
    metaDesc = `Viewing version for the ${entityLabel} ${doc[useAsTitle]}`;
  }

  if (global) {
    metaTitle = `Version - ${formattedCreatedAt} - ${entityLabel}`;
    metaDesc = `Viewing version for the global ${entityLabel}`;
  }

  return (
    <div className={baseClass}>
      <Meta
        title={metaTitle}
        description={metaDesc}
      />
      <Eyebrow />
      <div className={`${baseClass}__wrap`}>
        <div className={`${baseClass}__intro`}>Version created on:</div>
        <header className={`${baseClass}__header`}>
          <h2>
            {formattedCreatedAt}
          </h2>
          <Restore
            className={`${baseClass}__restore`}
            collection={collection}
            global={global}
            originalDocID={id}
            versionID={versionID}
            versionDate={formattedCreatedAt}
          />
        </header>
        <div className={`${baseClass}__controls`}>
          {localization && (
            <SelectLocales
              onChange={setLocales}
              options={localeOptions}
              value={locales}
            />
          )}
          <CompareVersion
            baseURL={compareBaseURL}
            parentID={parentID}
            value={compareValue}
            onChange={setCompareValue}
          />
        </div>
        {isLoading && (
          <Loading />
        )}
        {doc?.version && (
          <RenderFieldsToDiff
            locales={locales.map((locale) => locale.value)}
            fields={fields}
            fieldComponents={fieldComponents}
            fieldPermissions={fieldPermissions}
            version={doc?.version}
            comparison={compareValue?.value === 'mostRecent' ? compareDoc : compareDoc?.version}
          />
        )}
      </div>
    </div>
  );
};

export default VersionView;
