import React, { useEffect, useState } from 'react';
import { DataGridPremium, GridColDef } from '@mui/x-data-grid-premium';
import RunDetails from './RunDetails';
import './SampleImage.css';
import './ResultGrid.css';
import { OpenAPI, SamplesService } from '../../openapi';


// Extend your image info interface if needed.
interface ImageInfo {
    id: number;
    filepath: string;
    comment?: string;
}

// This represents an experiment run as returned by your API.
interface ExperimentParameters {
    id: number;
    run_number: number;
    sample_id: number;
    beamline_parameters: {
        beamSizeHeight: number;
        beamSizeWidth: number;
        beamline: string;
        beamlineFluxAtSample_ph_s: number;
        cryojetTemperature_K?: number | null;
        detector: {
            beamCenterX_px: number;
            beamCenterY_px: number;
            detectorDistance_mm: number;
            manufacturer: string;
            model: string;
            pixelSizeX_um: number;
            pixelSizeY_um: number;
            serialNumber: string;
            type: string;
        };
        rotation?: {
            chi: number;
            exposureTime_s: number;
            numberOfImages: number | null;
            omegaStart_deg: number;
            omegaStep: number;
            phi: number;
        } | null;
        gridScan?: {
            xStart: number;
            xStep: number;
            yStart: number;
            yStep: number;
            zStart: number;
            zStep: number;
            numberOfImages: number;
            exposureTime_s: number;
        } | null;
        focusingOptic?: string;
        humidifierHumidity?: number | null;
        humidifierTemperature_K?: number | null;
        jet?: any;
        monochromator?: string;
        ringCurrent_A?: number;
        ringMode?: string;
        synchrotron?: string;
        transmission?: number;
        undulator?: any;
        undulatorgap_mm?: any;
        wavelength?: number;
    };
}

// Represents a sample returned by the API.
interface SampleResult {
    sample_id: number;
    sample_name: string;
    puck_name?: string;
    dewar_name?: string;
    images: ImageInfo[];
    experiment_runs?: ExperimentParameters[];
}

// A flat tree row type for the grid.
interface TreeRow {
    id: string;
    hierarchy: (string | number)[];
    type: 'sample' | 'run';
    sample_id: number;
    sample_name?: string;
    puck_name?: string;
    dewar_name?: string;
    images?: ImageInfo[];
    run_number?: number;
    beamline_parameters?: ExperimentParameters['beamline_parameters'];
    experimentType?: string;
    numberOfImages?: number;
}

interface ResultGridProps {
    activePgroup: string;
}


const ResultGrid: React.FC<ResultGridProps> = ({ activePgroup }) => {
    const [rows, setRows] = useState<TreeRow[]>([]);
    const [basePath, setBasePath] = useState('');
    const [detailPanelHeights, setDetailPanelHeights] = useState<{ [key: string]: number }>({}); // Store dynamic heights

    const hasProcessingResults = (row: TreeRow): boolean => {
        // You can later replace this placeholder with actual logic.
        // Mocking the logic by returning `true` for demonstration.
        return row.type === 'run' && !!row.beamline_parameters?.detector;
    };

    // Helper function to safely get the number of images.
    const getNumberOfImages = (run: ExperimentParameters): number => {
        const params = run.beamline_parameters;
        if (params.rotation && params.rotation.numberOfImages != null) {
            return params.rotation.numberOfImages;
        } else if (params.gridScan && params.gridScan.numberOfImages != null) {
            return params.gridScan.numberOfImages;
        }
        return 0;
    };

    const getRowClassName = (params: { row: TreeRow }) => {
        const { row } = params;

        // Light green if the run contains processing results
        if (hasProcessingResults(row)) {
            return 'row-light-green';
        }

        // Light yellow if the row type is 'run'
        if (row.type === 'run') {
            return 'row-light-yellow';
        }

        // No special styling
        return '';
    };

    // Helper function to determine the experiment type.
    const getExperimentType = (run: ExperimentParameters): string => {
        const params = run.beamline_parameters;
        if (
            params.rotation &&
            params.rotation.numberOfImages != null &&
            params.rotation.omegaStep != null
        ) {
            const numImages = params.rotation.numberOfImages;
            const omegaStep = params.rotation.omegaStep;
            if ([1, 2, 4].includes(numImages) && omegaStep === 90) {
                return 'Characterization';
            }
            return 'Rotation';
        } else if (params.gridScan) {
            return 'Grid Scan';
        }
        return 'Rotation';
    };

    useEffect(() => {
        // Set OpenAPI.BASE depending on environment mode
        const mode = import.meta.env.MODE;
        OpenAPI.BASE =
            mode === 'test'
                ? import.meta.env.VITE_OPENAPI_BASE_TEST
                : mode === 'prod'
                    ? import.meta.env.VITE_OPENAPI_BASE_PROD
                    : import.meta.env.VITE_OPENAPI_BASE_DEV;

        if (!OpenAPI.BASE) {
            console.error('OpenAPI.BASE is not set. Falling back to a default value.');
            OpenAPI.BASE = 'https://default-url.com';
        }
        setBasePath(`${OpenAPI.BASE}/`);
    }, []);

    useEffect(() => {
        // Fetch sample details and construct rows
        SamplesService.getSampleResultsSamplesResultsGet(activePgroup)
            .then((response: SampleResult[]) => {
                const treeRows: TreeRow[] = [];

                response.forEach((sample) => {
                    const sampleRow: TreeRow = {
                        id: `sample-${sample.sample_id}`,
                        hierarchy: [sample.sample_id],
                        type: 'sample',
                        sample_id: sample.sample_id,
                        sample_name: sample.sample_name,
                        puck_name: sample.puck_name,
                        dewar_name: sample.dewar_name,
                        images: sample.images,
                    };
                    treeRows.push(sampleRow);

                    if (sample.experiment_runs) {
                        sample.experiment_runs.forEach((run) => {
                            const experimentType = getExperimentType(run);
                            const numImages = getNumberOfImages(run);
                            const runRow: TreeRow = {
                                id: `run-${sample.sample_id}-${run.run_number}`,
                                hierarchy: [sample.sample_id, run.run_number],
                                type: 'run',
                                sample_id: sample.sample_id,
                                run_number: run.run_number,
                                beamline_parameters: run.beamline_parameters,
                                experimentType,
                                numberOfImages: numImages,
                                images: sample.images,
                            };
                            treeRows.push(runRow);
                        });
                    }
                });

                setRows(treeRows);
            })
            .catch((error) => {
                console.error('Error fetching sample results:', error);
            });
    }, [activePgroup]);

    // Define the grid columns
    const columns: GridColDef[] = [
        {
            field: 'sample_name',
            headerName: 'Sample Name',
            width: 200,
        },
        {
            field: 'puck_name',
            headerName: 'Puck Name',
            width: 150,
        },
        {
            field: 'dewar_name',
            headerName: 'Dewar Name',
            width: 150,
        },
        {
            field: 'experimentType',
            headerName: 'Experiment Type',
            width: 150,
            renderCell: (params) => (params.row.type === 'run' ? params.value : null),
        },
        {
            field: 'numberOfImages',
            headerName: 'Number of Images',
            width: 150,
            renderCell: (params) => (params.row.type === 'run' ? params.value : null),
        },
        {
            field: 'images',
            headerName: 'Images',
            width: 300,
            renderCell: (params) => {
                const imageList: ImageInfo[] = params.row.images;
                if (!imageList || imageList.length === 0) return null;

                return (
                    <div style={{ display: 'flex', gap: '10px' }}>
                        {imageList.map((img) => {
                            const url = `${basePath}${img.filepath}`;
                            return (
                                <div key={img.id} style={{ position: 'relative' }}>
                                    <img
                                        src={url}
                                        alt={img.comment || 'sample'}
                                        className="zoom-image"
                                        style={{
                                            width: 40,
                                            height: 40,
                                            borderRadius: 4,
                                            cursor: 'pointer',
                                        }}
                                    />
                                </div>
                            );
                        })}
                    </div>
                );
            },
        },
    ];

    const handleDetailPanelHeightChange = (rowId: string, height: number) => {
        // Update the height of the specific detail panel dynamically
        setDetailPanelHeights((prev) => {
            if (prev[rowId] !== height) {
                return { ...prev, [rowId]: height };
            }
            return prev;
        });
    };

    const getDetailPanelContent = (params: any) => {
        if (params.row.type === 'run') {
            return (
                <RunDetails
                    run={params.row}
                    basePath={basePath}
                    onHeightChange={(height: number) => handleDetailPanelHeightChange(params.row.id, height)} // Pass callback for dynamic height
                />
            );
        }
        return null;
    };

    const getDetailPanelHeight = (params: any) => {
        if (params.row.type === 'run') {
            // Use the dynamically calculated height from state
            return detailPanelHeights[params.row.id] || 600; // Fallback to default height if not yet calculated
        }
        return 0;
    };



    return (
        <DataGridPremium
            rows={rows}
            columns={columns}
            getRowId={(row) => row.id}
            autoHeight
            treeData
            getRowClassName={getRowClassName}
            getTreeDataPath={(row: TreeRow) => {
                if (row.type === 'run') {
                    // Include sample_id to make the path globally unique
                    return [`Sample-${row.sample_id}`, `Run-${row.run_number}`];
                }
                // If it's a sample row, it will be at the root
                return [`Sample-${row.sample_id}`];
            }}

            defaultGroupingExpansionDepth={-1}
            disableColumnMenu
            getDetailPanelContent={getDetailPanelContent}
            getDetailPanelHeight={getDetailPanelHeight}
            sx={{
                '& .MuiDataGrid-cell': {
                    overflow: 'visible',
                },
            }}
        />

    );
};

export default ResultGrid;

