/**
 * List Page Factory
 */

import { mdiChartTimelineVariant } from '@mdi/js';
import Head from 'next/head';
import { uniqueId } from 'lodash';
import React, { ReactElement, useState } from 'react';
import axios from 'axios';
import CardBox from '../components/CardBox';
import LayoutAuthenticated from '../layouts/Authenticated';
import SectionMain from '../components/SectionMain';
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
import BaseButton from '../components/BaseButton';
import CardBoxModal from '../components/CardBoxModal';
import DragDropFilePicker from '../components/DragDropFilePicker';
import { getPageTitle } from '../config';
import { hasPermission } from '../helpers/userPermissions';
import { useAppDispatch, useAppSelector } from '../stores/hooks';
import type { AsyncThunk } from '@reduxjs/toolkit';
import type { Filter, FilterItem } from '../types/filters';

interface ListPageConfig {
  entityName: string;
  entityTitle: string;
  TableComponent: React.ComponentType<{
    filterItems: FilterItem[];
    setFilterItems: (items: FilterItem[]) => void;
    filters: Filter[];
    showGrid?: boolean;
  }>;
  filters: Filter[];
  readPermission: string;
  createPermission: string;
  uploadCsvAction: AsyncThunk<unknown, File, object>;
  setRefetchAction: (value: boolean) => { type: string; payload: boolean };
  newItemLabel?: string;
  cardBoxId?: string;
}

export function createListPage(config: ListPageConfig) {
  const {
    entityName,
    entityTitle,
    TableComponent,
    filters,
    readPermission,
    createPermission,
    uploadCsvAction,
    setRefetchAction,
    newItemLabel = 'New Item',
    cardBoxId,
  } = config;

  const ListPage = () => {
    const dispatch = useAppDispatch();
    const { currentUser } = useAppSelector((state) => state.auth);

    const [filterItems, setFilterItems] = useState<FilterItem[]>([]);
    const [csvFile, setCsvFile] = useState<File | null>(null);
    const [isModalActive, setIsModalActive] = useState(false);

    const hasCreatePermission =
      currentUser && hasPermission(currentUser, createPermission);

    const addFilter = () => {
      const newItem: FilterItem = {
        id: uniqueId(),
        fields: {
          filterValue: '',
          filterValueFrom: '',
          filterValueTo: '',
          selectedField: filters[0]?.title || '',
        },
      };
      setFilterItems([...filterItems, newItem]);
    };

    const downloadCSV = async () => {
      const response = await axios({
        url: `/${entityName}?filetype=csv`,
        method: 'GET',
        responseType: 'blob',
      });
      const type = response.headers['content-type'];
      const blob = new Blob([response.data], { type });
      const link = document.createElement('a');
      link.href = window.URL.createObjectURL(blob);
      link.download = `${entityName}CSV.csv`;
      link.click();
    };

    const onModalConfirm = async () => {
      if (!csvFile) return;
      await dispatch(uploadCsvAction(csvFile));
      dispatch(setRefetchAction(true));
      setCsvFile(null);
      setIsModalActive(false);
    };

    const onModalCancel = () => {
      setCsvFile(null);
      setIsModalActive(false);
    };

    return (
      <>
        <Head>
          <title>{getPageTitle(entityTitle)}</title>
        </Head>
        <SectionMain>
          <SectionTitleLineWithButton
            icon={mdiChartTimelineVariant}
            title={entityTitle}
            main
          >
            {''}
          </SectionTitleLineWithButton>
          <CardBox
            id={cardBoxId}
            className='mb-6'
            cardBoxClassName='flex flex-wrap'
          >
            {hasCreatePermission && (
              <BaseButton
                className='mr-3'
                href={`/${entityName}/${entityName}-new`}
                color='info'
                label={newItemLabel}
              />
            )}
            <BaseButton
              className='mr-3'
              color='info'
              label='Filter'
              onClick={addFilter}
            />
            <BaseButton
              className='mr-3'
              color='info'
              label='Download CSV'
              onClick={downloadCSV}
            />
            {hasCreatePermission && (
              <BaseButton
                color='info'
                label='Upload CSV'
                onClick={() => setIsModalActive(true)}
              />
            )}
            <div className='md:inline-flex items-center ms-auto'>
              <div id='delete-rows-button'></div>
            </div>
          </CardBox>
          <CardBox className='mb-6' hasTable>
            <TableComponent
              filterItems={filterItems}
              setFilterItems={setFilterItems}
              filters={filters}
              showGrid={false}
            />
          </CardBox>
        </SectionMain>
        <CardBoxModal
          title='Upload CSV'
          buttonColor='info'
          buttonLabel='Confirm'
          isActive={isModalActive}
          onConfirm={onModalConfirm}
          onCancel={onModalCancel}
        >
          <DragDropFilePicker
            file={csvFile}
            setFile={setCsvFile}
            formats='.csv'
          />
        </CardBoxModal>
      </>
    );
  };

  ListPage.getLayout = function getLayout(page: ReactElement) {
    return (
      <LayoutAuthenticated permission={readPermission}>
        {page}
      </LayoutAuthenticated>
    );
  };

  return ListPage;
}

export default createListPage;
