import React, {useEffect, useState} from 'react';
import Table from './dataTable/Table';
import TableHead from './dataTable/TableHeader';
import TableBody from './dataTable/TableBody';
import Footer from './dataTable/Footer';
import Loader from "./Loader";
import TableFilters from "./dataTable/TableFilters";

type Headers = {
    [key: string]: string;
}

type TableDefinition = {
    headers: Headers,
    downloadSpreadsheet: {
        url: string,
    },
    baseUrl: string,
}

export const BulkMark = ({headers, downloadSpreadsheet, baseUrl}: TableDefinition) => {
    const [loading, setLoading] = useState(true);
    const [data, setBulkMarks] = useState([]);
    const [pagination, setPagination] = useState(null);
    const [params, setParams] = useState(new URLSearchParams(window.location.search));
    const [orderBy, setOrderBy] = useState<number | null>(null);
    const [orderDirection, setOrderDirection] = useState<string | null>(null);
    const [searchTerm, setSearchTerm] = useState<string>('');
    const [start, setStart] = useState<string>('');
    const [end, setEnd] = useState<string>('');
    const [isShowOnlyMyRecords, setIsShowOnlyMyRecords] = useState(0);


    const loadTableData = () => {
        const url = baseUrl + 'bulkmark/data?' + params.toString();
        setLoading(true);

        fetch(url, {
            method: 'GET',
            headers: {
                'X-Requested-With': 'XMLHttpRequest',
                'Content-Type': 'application/json'
            }
        })
            .then((resp) => resp.json())
            .then((bulkMarks) => {
                if (bulkMarks?.status === 'error') {
                    console.log(bulkMarks.message);
                    return;
                }

                setBulkMarks(bulkMarks?.data);
                setPagination(bulkMarks?.pagination);
                setLoading(false);
            }).catch((error) => {
            console.error(error);
        });
    }

    const updateParamsAndRefreshData = (newParams: URLSearchParams | null = null) => {
        window.history.replaceState(
            null,
            "CEDAR - Bulk Mark Entries",
            `${window.location.pathname}?${newParams ? newParams.toString() : params.toString()}`
        );

        newParams
            ? setParams(newParams) // Store the new params in state after updating the URL
            : loadTableData();
    };

    const handleRecordsPerPage = (e: React.ChangeEvent<HTMLSelectElement>) => {
        params.set('page', '1');
        params.set('limit', e.target.value);
        updateParamsAndRefreshData();
    }

    const sortTableByColumn = (index: number) => {
        let sortDirection: string;
        let sortColumnIndex: number;

        if (orderBy === null || orderBy !== index) {
            // If no column is sorted, or the clicked column is different from the previous one, set the default sort direction to 'asc'
            sortDirection = 'asc';
            sortColumnIndex = index;
        } else {
            // If the same column is clicked again, toggle the sort direction
            if (orderDirection === 'asc') {
                sortDirection = 'desc';
                sortColumnIndex = index;
            } else {
                if (orderDirection === 'desc') {
                    // If it's already descending, reset sorting to no sorting
                    sortDirection = ''; // Reset sort direction
                    sortColumnIndex = -1; // No column is sorted
                } else {
                    // This ensures that if there is no direction, we toggle back to 'asc'
                    sortDirection = 'asc';
                    sortColumnIndex = index;
                }
            }
        }

        if (sortColumnIndex !== -1) {
            // Set the parameters for sorting (only if there is a valid column to sort by)
            params.set('order_by', String(sortColumnIndex));
            params.set('order_direction', sortDirection);
        } else {
            // If resetting the sorting, remove sorting parameters
            params.delete('order_by');
            params.delete('order_direction');
        }

        setOrderBy(sortColumnIndex);
        setOrderDirection(sortDirection);

        updateParamsAndRefreshData();
    }

    const handlePageChange = (page: number) => {
        params.set('page', String(page));
        updateParamsAndRefreshData();
    }

    const handleSearch = (e: React.KeyboardEvent<HTMLInputElement> | null) => {
        if (!loading && (e?.key == 'Enter' || e == null)) {
            params.set('s', searchTerm);
            params.set('page', '1');
            updateParamsAndRefreshData();
        }
    }

    const handleReset = () => {
        if (!loading && params.size > 0) {
            setSearchTerm('');
            setOrderBy(null);
            setOrderDirection(null);
            setStart('');
            setEnd('');
            setIsShowOnlyMyRecords(0);

            const newParams = new URLSearchParams();
            if (params.get('limit')) {
                newParams.set('limit', params.get('limit'));
            }

            updateParamsAndRefreshData(newParams);
        }
    }

    const handleDateRangeFilter = () => {
        params.set('start', start);
        params.set('end', end);
        params.set('page', '1');
        updateParamsAndRefreshData();
    }

    const handleShowMyRecords = (value: number) => {
        const newVal = value ? 0 : 1;
        setIsShowOnlyMyRecords(newVal)
        params.set('show_only_my_records', String(newVal));
        params.set('page', '1');
        updateParamsAndRefreshData();
    }

    useEffect(() => {
        const ordBy = params.get('order_by');
        const ordDirection = params.get('order_direction');
        const start = params.get('start');
        const end = params.get('end');
        const isShowOnlyMyRecords = parseInt(params.get('show_only_my_records')) ?? 0;

        if (ordBy) {
            setOrderBy(parseInt(ordBy, 10));
        }

        if (ordDirection) {
            setOrderDirection(ordDirection);
        }

        if (start) {
            setStart(start);
        }

        if (end) {
            setEnd(end);
        }

        if (isShowOnlyMyRecords) {
            setIsShowOnlyMyRecords(isShowOnlyMyRecords);
        }

        setSearchTerm(params.get('s') ?? '');

        loadTableData();
    }, [params]);

    return (
        <>
            <TableFilters handleSearch={handleSearch}
                          handleReset={handleReset}
                          handleDateRangeFilter={handleDateRangeFilter}
                          handleShowMyRecords={handleShowMyRecords}
                          searchTerm={searchTerm}
                          setSearchTerm={setSearchTerm}
                          setStart={setStart}
                          setEnd={setEnd}
                          start={start}
                          end={end}
                          isShowOnlyMyRecords={isShowOnlyMyRecords}
            />
            <div className="datagrid-container">
                {loading && <Loader/>}
                <div className="table-container long">
                    <Table className="datagrid ops_datagrid tablesorter tablesorter-default">
                        <TableHead headers={headers}
                                   handleSort={sortTableByColumn}
                                   orderBy={orderBy}
                                   orderDirection={orderDirection}/>
                        <TableBody
                            headers={headers}
                            data={data ?? []}
                        />
                    </Table>
                </div>
                <Footer handleRecordsPerPage={handleRecordsPerPage}
                        handlePageChange={handlePageChange}
                        download={downloadSpreadsheet}
                        pagination={pagination ?? null}/>
            </div>
        </>
    );
}

