import React, { useEffect, useState, useMemo } from 'react'
import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton'
import CardBoxModal from '../CardBoxModal'
import CardBox from "../CardBox";
import { fetch, update, deleteItem, setRefetch, deleteItemsByIds } from '../../stores/reservations/reservationsSlice'
import { useAppDispatch, useAppSelector } from '../../stores/hooks'
import { useRouter } from 'next/router'
import { Field, Form, Formik } from "formik";
import {
    DataGrid,
    GridColDef,
} from '@mui/x-data-grid';
import {loadColumns} from "./configureReservationsCols";
import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter'
import { getIncompleteFilterHint, isFilterItemIncomplete, pruneHiddenFilterItems } from '../../helpers/entityVisibility'
import {dataGridStyles} from "../../styles";


import BigCalendar from "../BigCalendar";
import { SlotInfo } from 'react-big-calendar';


const perPage = 25

const compactColumnVisibilityModel = {
  tenant: false,
  organization: false,
  booking_request: false,
  unit_type: false,
  actual_check_in_at: false,
  actual_check_out_at: false,
  early_check_in: false,
  late_check_out: false,
  monthly_rate: false,
  currency: false,
  internal_notes: false,
  external_notes: false,
  guests: false,
  service_requests: false,
  invoices: false,
  documents: false,
  comments: false,
}


const TableSampleReservations = ({ filterItems, setFilterItems, filters, showGrid }) => {
  const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});

    const dispatch = useAppDispatch();
    const router = useRouter();

    const pagesList = [];
    const [id, setId] = useState(null);
    const [currentPage, setCurrentPage] = useState(0);
    const [filterRequest, setFilterRequest] = React.useState('');
    const [columns, setColumns] = useState<GridColDef[]>([]);
    const [selectedRows, setSelectedRows] = useState([]);
    const [sortModel, setSortModel] = useState([
        {
            field: '',
            sort: 'desc',
        },
    ]);
  
  const { reservations, loading, count, notify: reservationsNotify, refetch } = useAppSelector((state) => state.reservations)
  const { currentUser } = useAppSelector((state) => state.auth);
  const focusRing = useAppSelector((state) => state.style.focusRingColor);
  const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
  const corners = useAppSelector((state) => state.style.corners);
    const numPages = Math.floor(count / perPage) === 0 ? 1 : Math.ceil(count / perPage);
    for (let i = 0; i < numPages; i++) {
        pagesList.push(i);
    }

    const loadData = async (page = currentPage, request = filterRequest) => {
        if (page !== currentPage) setCurrentPage(page);
        if (request !== filterRequest) setFilterRequest(request);
        const { sort, field } = sortModel[0];

      const query = `?page=${page}&limit=${perPage}${request}&sort=${sort}&field=${field}`;
      dispatch(fetch({ limit: perPage, page, query }));
  };

  useEffect(() => {
      if (reservationsNotify.showNotification) {
          notify(reservationsNotify.typeNotification, reservationsNotify.textNotification);
      }
  }, [reservationsNotify.showNotification]);

  useEffect(() => {
      if (!currentUser) return;
      loadData();
  }, [sortModel, currentUser]);

  useEffect(() => {
    if (refetch) {
      loadData(0);
      dispatch(setRefetch(false));
    }
  }, [refetch, dispatch]);

  const validFilterItems = useMemo(() => pruneHiddenFilterItems(filterItems, filters), [filterItems, filters]);

  useEffect(() => {
    if (validFilterItems !== filterItems) {
      setFilterItems(validFilterItems);
    }
  }, [filterItems, setFilterItems, validFilterItems]);

  const [isModalInfoActive, setIsModalInfoActive] = useState(false)
  const [isModalTrashActive, setIsModalTrashActive] = useState(false)

  const handleModalAction = () => {
    setIsModalInfoActive(false)
    setIsModalTrashActive(false)
  }

  

  
  const handleCreateEventAction = ({ start, end }: SlotInfo) => {
      router.push(
          `/reservations/reservations-new?dateRangeStart=${start.toISOString()}&dateRangeEnd=${end.toISOString()}`,
      );
  };
  

  const handleDeleteModalAction = (id: string) => {
    setId(id)
    setIsModalTrashActive(true)
  }
  const handleDeleteAction = async () => {
      if (id) {
          await dispatch(deleteItem(id));
          await loadData(0);
          setIsModalTrashActive(false);
      }
  };

  const reservationCalendarOverview = useMemo(() => {
    const today = new Date();
    const nextSevenDays = new Date(today);
    nextSevenDays.setDate(nextSevenDays.getDate() + 7);

    const totals = reservations.reduce(
      (accumulator, item) => {
        const checkIn = item?.check_in_at ? new Date(item.check_in_at) : null;
        const checkOut = item?.check_out_at ? new Date(item.check_out_at) : null;
        const status = item?.status || 'quoted';

        accumulator.total += 1;
        accumulator[status] = (accumulator[status] || 0) + 1;

        if (checkIn && checkIn >= today && checkIn <= nextSevenDays) {
          accumulator.upcomingArrivals += 1;
        }

        if (checkOut && checkOut >= today && checkOut <= nextSevenDays) {
          accumulator.upcomingDepartures += 1;
        }

        return accumulator;
      },
      {
        total: 0,
        confirmed: 0,
        checked_in: 0,
        upcomingArrivals: 0,
        upcomingDepartures: 0,
      },
    );

    return [
      {
        label: 'Visible stays',
        value: totals.total,
        hint: 'Loaded in this calendar range',
      },
      {
        label: 'Confirmed',
        value: totals.confirmed,
        hint: 'Booked and upcoming',
      },
      {
        label: 'In house',
        value: totals.checked_in,
        hint: 'Currently checked in',
      },
      {
        label: 'Departures soon',
        value: totals.upcomingDepartures,
        hint: 'Next 7 days',
      },
    ];
  }, [reservations]);

  const generateFilterRequests = useMemo(() => {
    let request = '&';
    validFilterItems.forEach((item) => {
      const isRangeFilter = filters.find(
        (filter) =>
          filter.title === item.fields.selectedField &&
          (filter.number || filter.date),
      );

      if (isRangeFilter) {
        const from = item.fields.filterValueFrom;
        const to = item.fields.filterValueTo;
        if (from) {
          request += `${item.fields.selectedField}Range=${from}&`;
        }
        if (to) {
          request += `${item.fields.selectedField}Range=${to}&`;
        }
      } else {
        const value = item.fields.filterValue;
        if (value) {
          request += `${item.fields.selectedField}=${value}&`;
        }
      }
    });
    return request;
  }, [filters, validFilterItems]);

  const deleteFilter = (value) => {
    const newItems = validFilterItems.filter((item) => item.id !== value);

    if (newItems.length) {
        setFilterItems(newItems);
    } else {
        loadData(0, '');
        
        setFilterItems(newItems);
    }
  };

  const handleSubmit = () => {
    loadData(0, generateFilterRequests);
    
  };

  const handleChange = (id) => (e) => {
    const value = e.target.value;
    const name = e.target.name;

    setFilterItems(
      validFilterItems.map((item) => {
        if (item.id !== id) return item;
        if (name === 'selectedField') return { id, fields: { [name]: value } };

        return { id, fields: { ...item.fields, [name]: value } }
      }),
    );
  };

  const handleReset = () => {
      setFilterItems([]);
      loadData(0, '');
      
  };

  const onPageChange = (page: number) => {
    loadData(page);
    setCurrentPage(page);
  };

  
    useEffect(() => {
        if (!currentUser) return;

        loadColumns(
            handleDeleteModalAction,
            `reservations`,
            currentUser,
        ).then((newCols) => setColumns(newCols));
    }, [currentUser]);
  


  const handleTableSubmit = async (id: string, data) => {
    
    if (!_.isEmpty(data)) {
      await dispatch(update({ id, data }))
        .unwrap()
        .then((res) => res)
        .catch((err) => {
          throw new Error(err);
        });
    }
  };

  const onDeleteRows = async (selectedRows) => {
    await dispatch(deleteItemsByIds(selectedRows));
    await loadData(0);
  };

  const controlClasses =
      'w-full rounded-xl border border-white/10 bg-white/5 px-3 py-2 text-sm text-slate-100 placeholder:text-slate-400 ' +
      ' ' + bgColor + ' ' + focusRing + ' ' + corners + ' ' +
      'dark:bg-slate-800/80 my-1';


  const dataGrid = (
        <div  className='relative overflow-x-auto'>
          <DataGrid
              autoHeight
              rowHeight={56}
              sx={dataGridStyles}
              className={'datagrid--table'}
              getRowClassName={() => `datagrid--row`}
              rows={reservations ?? []}
              columns={columns}
              initialState={{
                  pagination: {
                      paginationModel: {
                          pageSize: 25,
                      },
                  },
                  columns: {
                      columnVisibilityModel: compactColumnVisibilityModel,
                  },
              }}
              disableRowSelectionOnClick
              onProcessRowUpdateError={(params) => {
                  console.log('Error', params);
              }}
              processRowUpdate={async (newRow, oldRow) => {
                const data = dataFormatter.dataGridEditFormatter(newRow);

                try {
                  await handleTableSubmit(newRow.id, data);
                  return newRow;
                } catch {
                  return oldRow;
                }
              }}
              sortingMode={'server'}
              checkboxSelection
              onRowSelectionModelChange={(ids) => {
                setSelectedRows(ids)
              }}
              onSortModelChange={(params) => {
                  params.length
                      ? setSortModel(params)
                      : setSortModel([{ field: '', sort: 'desc' }]);
              }}
              rowCount={count}
              pageSizeOptions={[25]}
              paginationMode={'server'}
              loading={loading}
              onPaginationModelChange={(params) => {
                  onPageChange(params.page);
              }}
          />
        </div>
  )

  return (
    <>
    {validFilterItems && Array.isArray(validFilterItems) && validFilterItems.length ?
        <CardBox className='mb-6 border border-white/10 shadow-none'>
            <Formik
                initialValues={{
                    checkboxes: ['lorem'],
                    switches: ['lorem'],
                    radio: 'lorem',
                }}
                onSubmit={() => null}
            >
                <Form>
                    <>
                        {validFilterItems && validFilterItems.map((filterItem) => {
                            const showIncompleteHint = isFilterItemIncomplete(filterItem, filters)
                            const incompleteHint = showIncompleteHint ? getIncompleteFilterHint(filterItem, filters) : null

                            return (
                                <div key={filterItem.id} className="mb-3 grid gap-3 rounded-2xl border border-white/10 bg-white/5 p-4 md:grid-cols-[minmax(0,1.1fr)_minmax(0,1fr)_minmax(0,14rem)]">
                                    <div className="flex min-w-0 flex-col">
                                        <div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400">Filter</div>
                                        <Field
                                            className={controlClasses}
                                            name='selectedField'
                                            id='selectedField'
                                            component='select'
                                            value={filterItem?.fields?.selectedField || ''}
                                            onChange={handleChange(filterItem.id)}
                                        >
                                            {filters.map((selectOption) => (
                                                <option
                                                    key={selectOption.title}
                                                    value={`${selectOption.title}`}
                                                >
                                                    {selectOption.label}
                                                </option>
                                            ))}
                                        </Field>
                                    </div>
                                    {filters.find((filter) => 
                                        filter.title === filterItem?.fields?.selectedField
                                    )?.type === 'enum' ? (
                                        <div className="flex min-w-0 flex-col">
                                            <div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400">
                                                Value
                                            </div>
                                            <Field
                                                className={controlClasses}
                                                name="filterValue"
                                                id='filterValue'
                                                component="select"
                                                value={filterItem?.fields?.filterValue || ''}
                                                onChange={handleChange(filterItem.id)}
                                            >
                                                <option value="">Select Value</option>
                                                {filters.find((filter) => 
                                                    filter.title === filterItem?.fields?.selectedField
                                                )?.options?.map((option) => (
                                                    <option key={option} value={option}>
                                                        {option}
                                                    </option>
                                                ))}
                                            </Field>
                                        </div>
                                    ) : filters.find((filter) => 
                                        filter.title === filterItem?.fields?.selectedField
                                    )?.number ? (
                                        <div className="grid min-w-0 gap-3 md:grid-cols-2">
                                            <div className="flex min-w-0 flex-col">
                                                <div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400">From</div>
                                                <Field
                                                    className={controlClasses}
                                                    name='filterValueFrom'
                                                    placeholder='From'
                                                    id='filterValueFrom'
                                                    value={filterItem?.fields?.filterValueFrom || ''}
                                                    onChange={handleChange(filterItem.id)}
                                                />
                                            </div>
                                            <div className="flex flex-col w-full">
                                                <div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400">To</div>
                                                <Field
                                                    className={controlClasses}
                                                    name='filterValueTo'
                                                    placeholder='to'
                                                    id='filterValueTo'
                                                    value={filterItem?.fields?.filterValueTo || ''}
                                                    onChange={handleChange(filterItem.id)}
                                                />
                                            </div>
                                        </div>
                                    ) : filters.find(
                                        (filter) =>
                                            filter.title ===
                                            filterItem?.fields?.selectedField
                                    )?.date ? (
                                        <div className='grid min-w-0 gap-3 md:grid-cols-2'>
                                            <div className='flex flex-col w-full mr-3'>
                                                <div className='text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400'>
                                                    From
                                                </div>
                                                <Field
                                                    className={controlClasses}
                                                    name='filterValueFrom'
                                                    placeholder='From'
                                                    id='filterValueFrom'
                                                    type='datetime-local'
                                                    value={filterItem?.fields?.filterValueFrom || ''}
                                                    onChange={handleChange(filterItem.id)}
                                                />
                                            </div>
                                            <div className='flex flex-col w-full'>
                                                <div className='text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400'>To</div>
                                                <Field
                                                    className={controlClasses}
                                                    name='filterValueTo'
                                                    placeholder='to'
                                                    id='filterValueTo'
                                                    type='datetime-local'
                                                    value={filterItem?.fields?.filterValueTo || ''}
                                                    onChange={handleChange(filterItem.id)}
                                                />
                                            </div>
                                        </div>
                                    ) : (
                                        <div className="flex min-w-0 flex-col">
                                            <div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400">Contains</div>
                                            <Field
                                                className={controlClasses}
                                                name='filterValue'
                                                placeholder='Contained'
                                                id='filterValue'
                                                value={filterItem?.fields?.filterValue || ''}
                                                onChange={handleChange(filterItem.id)}
                                            />
                                        </div>
                                    )}
                                    <div className="flex flex-col gap-2">
                                        <div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-400">Action</div>
                                        <BaseButton
                                            className="my-1 w-full md:w-auto"
                                            type='reset'
                                            color='whiteDark'
                                            outline
                                            label='Delete'
                                            onClick={() => {
                                                deleteFilter(filterItem.id)
                                            }}
                                        />
                                        {incompleteHint ? (
                                            <p className='rounded-xl border border-amber-500/20 bg-amber-500/10 px-3 py-2 text-xs leading-5 text-amber-100'>
                                                {incompleteHint}
                                            </p>
                                        ) : null}
                                    </div>
                                </div>
                            )
                        })}
                        <div className="flex flex-wrap items-center gap-2">
                            <BaseButton
                                className="my-1 mr-0"
                               type='submit' color='info'  
                                label='Apply'
                                onClick={handleSubmit}
                            />
                            <BaseButton
                                className="my-1"
                                 type='reset' color='whiteDark' outline  
                                label='Cancel'
                                onClick={handleReset}
                            />
                        </div>
                    </>
                </Form>
            </Formik>
        </CardBox> : null
    }
      <CardBoxModal
        title="Please confirm"
        buttonColor="info"
        buttonLabel={loading ? 'Deleting...' : 'Confirm'}
        isActive={isModalTrashActive}
        onConfirm={handleDeleteAction}
        onCancel={handleModalAction}
      >
        <p>Are you sure you want to delete this item?</p>
      </CardBoxModal>

      
        {!showGrid && (
          <>
            <div className='mb-6 grid gap-3 md:grid-cols-4'>
              {reservationCalendarOverview.map((item) => (
                <CardBox key={item.label} className='rounded-2xl border border-gray-200/80 shadow-none dark:border-dark-700'>
                  <div className='p-4'>
                    <p className='text-xs font-semibold uppercase tracking-[0.18em] text-gray-400 dark:text-gray-500'>
                      {item.label}
                    </p>
                    <p className='mt-2 text-2xl font-semibold text-gray-900 dark:text-white'>
                      {item.value}
                    </p>
                    <p className='mt-1 text-sm text-gray-500 dark:text-gray-400'>{item.hint}</p>
                  </div>
                </CardBox>
              ))}
            </div>
            <BigCalendar
              events={reservations}
              showField={'reservation_code'}
              start-data-key={'check_in_at'}
              end-data-key={'check_out_at'}
              handleDeleteAction={handleDeleteModalAction}
              pathEdit={`/reservations/reservations-edit/?id=`}
              pathView={`/reservations/reservations-view/?id=`}
              handleCreateEventAction={handleCreateEventAction}
              onDateRangeChange={(range) => {
                  loadData(0,`&calendarStart=${range.start}&calendarEnd=${range.end}`);
              }}
              isLoading={loading}
              emptyTitle='No reservations in this range'
              emptyDescription='Adjust the calendar window or add a reservation to start filling the schedule.'
              entityName={'reservations'}
            />
          </>
        )}
      

      
        {showGrid && dataGrid}
      

      {selectedRows.length > 0 &&
        createPortal(
          <BaseButton
            className='me-4'
            color='danger'
            label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
            onClick={() => onDeleteRows(selectedRows)}
          />,
          document.getElementById('delete-rows-button'),
      )}
    <ToastContainer />
    </>
  )
}

export default TableSampleReservations
