import React, { useEffect, useState } from "react";
import { DataGrid, GridColDef, GridCellEditStopParams, GridRowModel } from "@mui/x-data-grid";
import { DewarsService } from "../../openapi";

interface SampleSpreadsheetProps {
    dewarId: number; // Selected Dewar's ID
}

const SampleSpreadsheet: React.FC<SampleSpreadsheetProps> = ({ dewarId }) => {
    const [rows, setRows] = useState<any[]>([]); // Rows for the grid
    const [columns, setColumns] = useState<GridColDef[]>([]); // Columns for the grid

    // Fetch rows and columns related to the given Dewar ID
    useEffect(() => {
        if (!dewarId) {
            console.error("Invalid or missing Dewar ID");
            return;
        }

        const fetchSamples = async () => {
            try {
                const response = await DewarsService.getDewarSamplesProtectedDewarsDewarsDewarIdSamplesGet(dewarId);
                console.log("Response from backend:", response);
                const dewarData = response; // Assume response is already in correct structure

                // Transform pucks and samples into rows for the grid
                const allRows: any[] = [];
                dewarData.pucks.forEach((puck: any) => {
                    puck.samples.forEach((sample: any) => {
                        const {
                            directory,
                            oscillation,
                            exposure,
                            totalrange,
                            transmission,
                            dose,
                            targetresolution,
                            aperture,
                            datacollectiontype,
                            processingpipeline,
                            spacegroupnumber,
                            cellparameters,
                            rescutkey,
                            rescutvalue,
                            userresolution,
                            pdbid,
                            autoprocfull,
                            procfull,
                            adpenabled,
                            noano,
                            ffcscampaig,
                            trustedhigh,
                            autoprocextraparams,
                            chiphiangles
                        } = sample.data_collection_parameters || {};

                        allRows.push({
                            id: sample.id,
                            puckId: puck.id,
                            puckName: puck.puck_name,
                            puckType: puck.puck_type,
                            dewarName: dewarData.dewar_name,
                            position: sample.position,
                            crystalName: sample.sample_name,
                            proteinName: sample.proteinname,
                            priority: sample.priority,
                            comments: sample.comments,
                            directory: directory || null,
                            oscillation: oscillation || null,
                            exposure: exposure || null,
                            totalRange: totalrange || null,
                            transmission: transmission || null,
                            dose: dose || null,
                            targetresolution: targetresolution || null,
                            aperture: aperture || null,
                            datacollectiontype: datacollectiontype || null,
                            processingpipeline: processingpipeline || null,
                            spacegroupnumber: spacegroupnumber || null,
                            cellparameters: cellparameters || {},
                            rescutkey: rescutkey || null,
                            rescutvalue: rescutvalue || null,
                            userresolution: userresolution || null,
                            pdbid: pdbid || null,
                            autoprocfull: autoprocfull || null,
                            procfull: procfull || null,
                            adpenabled: adpenabled || null,
                            noano: noano || null,
                            ffcscampaig: ffcscampaig || null,
                            trustedhigh: trustedhigh || null,
                            autoprocextraparams: autoprocextraparams || {},
                            chiphiangles: chiphiangles || null,
                        });
                    });
                });
                console.log("All rows for DataGrid:", allRows);
                setRows(allRows);

                // Define columns for the grid
                setColumns([
                    { field: "dewarName", headerName: "Dewar Name", width: 150, editable: false }, // not editable for now
                    { field: "puckName", headerName: "Puck Name", width: 150, editable: false  }, // not editable for now
                    { field: "puckType", headerName: "Puck Type", width: 150, editable: false  }, // not editable for now
                    { field: "crystalName", headerName: "Crystal Name", width: 200, editable: false }, // not editable for now
                    { field: "proteinName", headerName: "Protein Name", width: 200, editable: false }, // not editable for now
                    { field: "position", headerName: "Position", width: 100, editable: true, type: "number" },
                    { field: "priority", headerName: "Priority", width: 100, editable: true, type: "number" },
                    { field: "comments", headerName: "Comments", width: 300, editable: true },
                    { field: "directory", headerName: "Directory", width: 200, editable: true },
                    { field: "oscillation", headerName: "Oscillation", width: 150, editable: true, type: "number" },
                    { field: "exposure", headerName: "Exposure", width: 150, editable: true, type: "number" },
                    { field: "totalRange", headerName: "Total Range", width: 150, editable: true, type: "number" },
                    { field: "transmission", headerName: "Transmission", width: 150, editable: true, type: "number" },
                    { field: "dose", headerName: "Dose", width: 150, editable: true, type: "number" },
                    { field: "targetresolution", headerName: "Target Resolution", width: 150, editable: true, type: "number" },
                    { field: "aperture", headerName: "Aperture", width: 150, editable: true },
                    { field: "datacollectiontype", headerName: "Data Collection Type", width: 200, editable: true  },
                    { field: "processingpipeline", headerName: "Processing Pipeline", width: 200, editable: true },
                    { field: "spacegroupnumber", headerName: "Space Group Number", width: 200, editable: true },
                    { field: "cellparameters", headerName: "Cell Parameters", width: 300, editable: true  },
                    { field: "rescutkey", headerName: "ResCut Key", width: 150, editable: true  },
                    { field: "rescutvalue", headerName: "ResCut Value", width: 150, editable: true },
                    { field: "userresolution", headerName: "User Resolution", width: 150, editable: true },
                    { field: "pdbid", headerName: "PDB ID", width: 150, editable: true  },
                    { field: "autoprocfull", headerName: "AutoProc Full", width: 200, editable: true  },
                    { field: "procfull", headerName: "Proc Full", width: 200, editable: true  },
                    { field: "adpenabled", headerName: "ADP Enabled", width: 150, editable: true  },
                    { field: "noano", headerName: "No Anomalous", width: 150, editable: true  },
                    { field: "ffcscampaig", headerName: "FFCS Campaign", width: 150, editable: true  },
                    { field: "trustedhigh", headerName: "Trusted High", width: 150, editable: true  },
                    { field: "autoprocextraparams", headerName: "AutoProc Extra Params", width: 300, editable: true },
                    { field: "chiphiangles", headerName: "Chi Phi Angles", width: 150, editable: true  },
                ]);
            } catch (error) {
                console.error("Error fetching dewar samples:", error);
            }
        };

        fetchSamples();
    }, [dewarId]);

    // Handle cell editing to persist changes to the backend
    const handleCellEditStop = async (params: GridCellEditStopParams) => {
        const { id, field, value } = params;

        // Validation to ensure we have valid data from the cell edit
        if (!id || !field || value === undefined) {
            console.error("Invalid edit inputs:", { id, field, value });
            return;
        }

        // Fetch the current row data (old state) based on its ID
        const updatedRow = rows.find((row) => row.id === id);

        if (!updatedRow) {
            console.error("Row not found for ID:", id);
            return;
        }

        // Create the updated sample, force-overwriting the changed cell value
        const updatedSample = {
            ...updatedRow, // Include other fields from the existing row
            [field]: value, // Explicitly overwrite the updated field with new value
        };

        console.log("Payload sent to the backend:", updatedSample); // Log fixed payload

        try {
            // Optimistically update UI for better experience
            setRows((prevRows) =>
                prevRows.map((row) =>
                    row.id === id ? { ...row, [field]: value } : row
                )
            );

            // API call to persist changes
            await DewarsService.updateSampleProtectedDewarsSamplesSampleIdPut(Number(id), updatedSample);

            console.log(`Sample with ID ${id} successfully updated.`);
        } catch (error) {
            console.error(`Failed to update sample with ID ${id}:`, error);

            // Revert optimistic update on error
            setRows((prevRows) =>
                prevRows.map((row) => (row.id === id ? updatedRow : row))
            );
        }
    };

    const processRowUpdate = async (newRow: GridRowModel, oldRow: GridRowModel) => {
        try {
            console.log("Old row:", oldRow); // Log the original row
            console.log("Updated row:", newRow); // Log the updated data from the grid

            // Reconstruct 'data_collection_parameters' from the flat table structure
            const updatedDataCollectionParameters = {
                ...(oldRow.data_collection_parameters || {}), // Preserve old values
                directory: newRow.directory ?? oldRow.data_collection_parameters?.directory,
                oscillation: newRow.oscillation ?? oldRow.data_collection_parameters?.oscillation,
                exposure: newRow.exposure ?? oldRow.data_collection_parameters?.exposure,
                totalrange: newRow.totalRange ?? oldRow.data_collection_parameters?.totalrange,
                transmission: newRow.transmission ?? oldRow.data_collection_parameters?.transmission,
                dose: newRow.dose ?? oldRow.data_collection_parameters?.dose,
                targetresolution: newRow.targetresolution ?? oldRow.data_collection_parameters?.targetresolution,
                aperture: newRow.aperture ?? oldRow.data_collection_parameters?.aperture,
                datacollectiontype: newRow.datacollectiontype ?? oldRow.data_collection_parameters?.datacollectiontype,
                processingpipeline: newRow.processingpipeline ?? oldRow.data_collection_parameters?.processingpipeline,
                spacegroupnumber: newRow.spacegroupnumber ?? oldRow.data_collection_parameters?.spacegroupnumber,
                //cellparameters: newRow.cellparameters ?? oldRow.data_collection_parameters?.cellparameters,
                rescutkey: newRow.rescutkey ?? oldRow.data_collection_parameters?.rescutkey,
                rescutvalue: newRow.rescutvalue ?? oldRow.data_collection_parameters?.rescutvalue,
                userresolution: newRow.userresolution ?? oldRow.data_collection_parameters?.userresolution,
                pdbid: newRow.pdbid ?? oldRow.data_collection_parameters?.pdbid,
                autoprocfull: newRow.autoprocfull ?? oldRow.data_collection_parameters?.autoprocfull,
                procfull: newRow.procfull ?? oldRow.data_collection_parameters?.procfull,
                adpenabled: newRow.adpenabled ?? oldRow.data_collection_parameters?.adpenabled,
                noano: newRow.noano ?? oldRow.data_collection_parameters?.noano,
                ffcscampaig: newRow.ffcscampaig ?? oldRow.data_collection_parameters?.ffcscampaig,
                trustedhigh: newRow.trustedhigh ?? oldRow.data_collection_parameters?.trustedhigh,
                //autoprocextraparams: newRow.autoprocextraparams ?? oldRow.data_collection_parameters?.autoprocextraparams,
                chiphiangles: newRow.chiphiangles ?? oldRow.data_collection_parameters?.chiphiangles,
            };

            // Assemble the final payload
            const payload = {
                ...oldRow, // Include all original fields
                ...newRow, // Overwrite or add updated fields
                data_collection_parameters: updatedDataCollectionParameters, // Include the merged/validated structure
            };

            console.log("Final payload sent to backend:", payload);

            // Optimistically update the UI
            setRows((prevRows) =>
                prevRows.map((row) =>
                    row.id === newRow.id ? { ...row, ...payload } : row
                )
            );

            // Send the payload to the backend
            await DewarsService.updateSampleProtectedDewarsSamplesSampleIdPut(Number(newRow.id), payload);

            console.log(`Successfully updated sample with ID ${newRow.id}.`);
            return payload; // Return the updated row

        } catch (error) {
            console.error(`Failed to update sample with ID ${newRow.id}:`, error);

            // On failure, revert to the old row
            return oldRow;
        }
    };

    return (
        <div style={{ height: 500, width: "100%" }}>
            <DataGrid
                rows={rows}
                columns={columns}
                pageSize={10}
                processRowUpdate={processRowUpdate} // Exclusively handle updates
            />
        </div>
    );
};

export default SampleSpreadsheet;