import { useState, useRef, useEffect } from '@wordpress/element';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';

const LCPDataGrid = ({dataset}) => {


    const [rowsToAdd, setRowsToAdd] = useState(1); // Number of rows the user wants to add

    const [currentRowCount, setCurrentRowCount] = useState(dataset.length); // Track the current row count

    // Button click handler to add a new row
    const addRows = () => {
        if (gridApi) {
            const rows = [];
            // Create the specified number of new rows (empty rows in this case)
            for (let i = 0; i < rowsToAdd; i++) {
                rows.push({}); // You can customize the empty row content if needed
            }
            
            // Use the grid API to add the new rows
            gridApi.applyTransaction({ add: rows });

            // Update the current row count
            setCurrentRowCount(prevCount => prevCount + rowsToAdd);
        } else {
            console.log('Grid is not ready yet');
        }
    };
    // let gridData = [
    //     { Department2: 'Sheriffs Office 2', Budget: '150000', MeetAt: '12/12/2025', PreferredColor: '#e0e0e0', PostContent: '<div> </div>' },
    //     { Department2: 'Treasurer2', Budget: '10000', MeetAt: '12-05', PreferredColor: '#232323', PostContent: '<p> </p>' },
    //     { Department2: 'Assessor2', Budget: '40000', MeetAt: 1737718512, PreferredColor: 'red', PostContent: '<h1> </h1>' },
    // ];

    const gridData = dataset;
    // Helper function to detect the data type of a value
    const getDataType = (value) => {
        if (typeof value === 'number' && !isNaN(value)) {
            return 'number';  // Identifies numerical values
        }
        return 'text'; // Defaults to 'text' for strings and others
    };

    // Helper function to detect if a value is a valid CSS color
    const isValidCSSColor = (value) => {
        const cssColorRegex = /^(#([0-9a-fA-F]{3}){1,2}|[a-zA-Z]+|rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)|rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(0(\.\d+)?|1(\.0+)?)\)|hsl\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%\)|hsla\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%,\s*(0(\.\d+)?|1(\.0+)?)\))$/i;
        return cssColorRegex.test(value);
    };

    // Helper function to detect if a value contains HTML tags
    const isHTML = (value) => {
        const htmlRegex = /<([a-z][\s\S]*)>/i;  // A simple check for any HTML tag
        return htmlRegex.test(value);
    };

    // Helper function to detect if a value is a valid date
    const isDate = (value) => {
        const date = new Date(value);
        return !isNaN(date.getTime());  // Return true if it's a valid date
    };

    // Detect the data type of each key by checking all rows
    const detectDataTypes = (data) => {
        const keys = Object.keys(data[0]);
        let dataTypes = {};

    keys.forEach((key) => {
        // Check all values for the key across all rows
        const allValuesAreNumbers = data.every(row => !isNaN(Number(row[key])));
        const allValuesAreColors = data.every(row => isValidCSSColor(row[key]));
        const allValuesAreHTML = data.every(row => isHTML(row[key]));
        const allValuesAreDates = data.every(row => isDate(row[key]));

        // If all values for that key are valid numbers, mark it as 'number'
        if (allValuesAreNumbers) {
            dataTypes[key] = 'number';
        }
        // If all values for that key are valid CSS colors, mark it as 'color'
        else if (allValuesAreColors) {
            dataTypes[key] = 'color';
        }
        // If all values for that key contain HTML, mark it as 'html'
        else if (allValuesAreHTML) {
            dataTypes[key] = 'html';
        }
        // If all values for that key are valid dates, mark it as 'date'
        else if (allValuesAreDates) {
            dataTypes[key] = 'date';
        }
        // If neither, mark it as 'text'
        else {
            dataTypes[key] = 'text';
        }
    });

    return dataTypes;
};
    // Assuming gridData is already populated
    const gridDataTypes = detectDataTypes(gridData);  // This will detect the types of each field

    console.log(gridDataTypes); // For debugging, will output the detected types for each column

    // Helper function to convert index to letters, accounting for 'A1', 'B1', 'C1', etc.
    const getColumnLabel = (index) => {
        const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        let label = '';

        while (index >= 0) {
            label = alphabet[index % 26] + label;
            index = Math.floor(index / 26) - 1;
        }

        return label;
    };

    // Data parser for Ag Grid based on detected data types
    function lcpDataTypeParser(params) {
        const columnName = params.colDef.field;  // Get the column field name (e.g., 'Budget', 'MeetAt')
        const dataType = gridDataTypes[columnName];  // Get the data type for this column from gridDataTypes
    
        if (params.node.rowPinned) {
            // If it's the pinned top row, return the value as-is
            return params.newValue;
        } else {
            // Process based on the detected data type
            switch (dataType) {
                case 'number':
                    // If it's a number, return the number or NaN
                    return Number(params.newValue);
                case 'date':
                    // If it's a date, try to parse the value as a Date
                    const parsedDate = new Date(params.newValue);
                    return !isNaN(parsedDate.getTime()) ? parsedDate : params.newValue;  // Return parsed date or original value if invalid
                case 'color':
                    // If it's a color, we don't need to change the value (it's already a valid color)
                    return params.newValue;
                case 'html':
                    // If it's HTML, we can either sanitize or leave the value as is (for now, leaving it as is)
                    return params.newValue;
                default:
                    // If it's text (or any other type), return the value as-is
                    return params.newValue;
            }
        }
    }

    // Create columnDefs dynamically
    const [columnDefs, setColumnDefs] = useState([]);
    const [pinnedTopRowData, setPinnedTopRowData] = useState([]);

    useEffect(() => {
        if (columnDefs.length > 0) return; // Prevent rerun if columnDefs already set

        if (gridData.length > 0) {
            const keys = Object.keys(gridData[0]); // Get the keys from the first row (Department2, Budget, etc.)

            const columns = keys.map((key, index) => {
                return {
                    headerName: getColumnLabel(index),  // 'A', 'B', 'C', ...
                    field: key, // Field will match the key (Department2, Budget, etc.)
                    valueParser: lcpDataTypeParser,
                };
            });

            // Set the pinned top row data with the actual field names (like 'Department2', 'Budget')
            const topRowData = keys.reduce((acc, key) => {
                acc[key] = key; // Set key as the value in top row (use field names)
                return acc;
            }, {});

            // Ensure pinnedTopRowData is set with correct data
            setPinnedTopRowData([topRowData]);

            // Add the row number column as the first column
            const rowNumberColumn = {
                headerName: '',
                valueGetter: (params) => {
                    const rowIndex = params.node.rowPinned ? params.node.rowIndex + 1 : params.node.rowIndex + 2;
                    return rowIndex;
                },
                suppressMovable: true,
                editable: false,
                filter: false,
                sortable: false,
                width: 45,
                resizable: false,
                flex: 0,
                cellStyle: { backgroundColor: '#e0e0e0' },
            };

            setColumnDefs([rowNumberColumn, ...columns]);  // Set columns along with row number column
        }
    }, [gridData, columnDefs]); // R

    const [rowData] = useState(gridData);

    // AG Grid instance reference
    const gridRef = useRef(null);
    const [gridApi, setGridApi] = useState(null); // Store grid API in state


    // Default Column Properties
    const defaultColDef = {
        flex: 1,
        minWidth: 45,
        editable: true,
        sortable: true,
        filter: true,
        suppressMovable: true,
        cellDataType: false, //By default column can be any data type 
        cellStyle: (params) => {
            if (params.node.rowPinned) {
                return { backgroundColor: 'rgb(197, 219, 229)' };
            }
        }
    };

    const gridOptions = {
        rowDragManaged: true,
        animateRows: true,
        rowHeight: 35,
        getRowStyle: (params) => {
            if (params.node.rowPinned) {
                return { backgroundColor: 'rgb(197, 219, 229)' }; // Light gray for pinned rows
            }
            return null; // No special style for non-pinned rows
        }
    };

    const onGridReady = (params) => {
        // Store the grid API when the grid is ready
        setGridApi(params.api);
    };

    // Reset row number on sorted
    const onSortChanged = (e) => {
        e.api.refreshCells();
    };

    // Reset row number on filtered
    const onFilterChanged = (e) => {
        e.api.refreshCells();
    };

    return (
        <div>
            <div
                id="lcp-data-grid"
                className="ag-theme-alpine"
                style={{ width: '100%', height: '300px' }}
            >
                <AgGridReact
                    ref={gridRef}
                    columnDefs={columnDefs}
                    rowData={rowData}
                    defaultColDef={defaultColDef}
                    gridOptions={gridOptions}
                    pinnedTopRowData={pinnedTopRowData}
                    pinnedLeftColCount={1}
                    onSortChanged={onSortChanged}
                    onFilterChanged={onFilterChanged}
                    onGridReady={onGridReady}
                />
            </div>

            {/* Button outside the grid */}
            <div>
            {/* Input to add multiple rows */}
            <div>
                <input
                    type="number"
                    value={rowsToAdd}
                    onChange={(e) => setRowsToAdd(Math.max(1, parseInt(e.target.value, 10)))}
                    min="1"
                />
                <button onClick={addRows}>Add Row(s)</button>
            </div>
            <div>
                <span>{currentRowCount} Rows</span>
            </div>
            </div>
        </div>
    );
};

export default LCPDataGrid;
