import React, {useEffect} from 'react';
import {Alert, Snackbar, Box, Grow, Fade} from '@mui/material';
import {PTMarkScreen, MarkData, Student} from '../PTMarkScreen/PTMarkScreen';
import {CriterionState} from '../models/ProgressTrackerModels';

export interface PTDetailViewProps
{
    trackerId: number;
    partId: number;
    students: Student[];
    partGuiConfig: {
        partId: number;
        ref: string;
        name: string;
        gradeCol: "VISIBLE" | "EDITABLE" | "HIDDEN";
        scoreCol: "VISIBLE" | "EDITABLE" | "HIDDEN";
        unitCriteria: "VISIBLE" | "EDITABLE" | "HIDDEN";
        showChildJumpButton: boolean;
        showChildCriteria: boolean;
        cellSummaryResultMetric?: "grade" | "score";
    };
    markData: { [studentId: number]: MarkData };
    loading: boolean;
    onSave?: (marks: { [studentId: number]: MarkData }) => Promise<{ success: boolean; message: string }>;
    saveStatus?: 'idle' | 'saving' | 'saved' | 'error';

    // New props for lifted state
    hasChanges?: boolean;
    setHasChanges?: (hasChanges: boolean) => void;
    manuallyModifiedCriteria?: { [studentId: number]: { [criterionName: string]: boolean } };
    setManuallyModifiedCriteria?: (criteria: { [studentId: number]: { [criterionName: string]: boolean } }) => void;
    sortConfig?: {
        sortBy: keyof Student | 'score' | 'grade' | null;
        sortDirection: 'asc' | 'desc';
    };
    setSortConfig?: (config: {
        sortBy: keyof Student | 'score' | 'grade' | null;
        sortDirection: 'asc' | 'desc'
    }) => void;
    setSaveStatus?: (status: 'idle' | 'saving' | 'saved' | 'error') => void;
    snackbar?: {
        open: boolean;
        message: string;
        severity: 'success' | 'error' | 'info' | 'warning';
    };
    setSnackbar?: (snackbar: {
        open: boolean;
        message: string;
        severity: 'success' | 'error' | 'info' | 'warning'
    }) => void;

    // Add function props for handlers drilled down from parent
    onMarkChange?: (studentId: number, field: keyof MarkData, value: any) => void;
    onCriterionChange?: (studentId: number, criterionName: string, value: CriterionState | null) => void;
    onCriterionHeaderClick?: (criterionName: string) => void;
    onSnackbarClose?: () => void;

    // Reload functionality
    onReload?: () => Promise<void>;

    // Grade-related functions
    getGradeOptionsForPart?: (partId: number) => Array<{ value: string; label: string }>;
    getGradeDisplayName?: (gradeRef: string, partId: number) => string;
}

export const PTDetailView: React.FC<PTDetailViewProps> = ({
                                                              trackerId,
                                                              partId,
                                                              students,
                                                              partGuiConfig,
                                                              markData,
                                                              loading = false,
                                                              onSave,
                                                              saveStatus: externalSaveStatus,
                                                              // Use the passed functions from parent instead of empty arrow functions
                                                              hasChanges = false,
                                                              setHasChanges,
                                                              manuallyModifiedCriteria = {},
                                                              setManuallyModifiedCriteria,
                                                              sortConfig = {sortBy: null, sortDirection: 'asc'},
                                                              setSortConfig,
                                                              setSaveStatus,
                                                              snackbar = {
                                                                  open: false,
                                                                  message: '',
                                                                  severity: 'success'
                                                              },
                                                              setSnackbar,
                                                              // Add drilled down handler props
                                                              onMarkChange,
                                                              onCriterionChange,                                                              onCriterionHeaderClick,
                                                              onSnackbarClose,
                                                              // Reload functionality
                                                              onReload,
                                                              // Grade-related functions
                                                              getGradeOptionsForPart,
                                                              getGradeDisplayName
                                                          }) => {
    // Use local references to the props for easier access
    const {sortBy, sortDirection} = sortConfig;

    // Update marks if markData changes from parent component
    // useEffect(() => {
    //   // Reset changes flag when receiving new mark data
    //   if (setHasChanges) {
    //     setHasChanges(false);
    //   }
    // }, [markData, setHasChanges]);

    // Lifted handlers from PTMarkScreen
    const handleMarkChange = (studentId: number, field: keyof MarkData, value: any) => {
        if (onMarkChange) {
            // Use the drilled down handler from parent
            onMarkChange(studentId, field, value);
            return;
        }

        // Fallback implementation if no handler provided
        // Create a new marks object with the updated value
        const updatedMarks = {
            ...markData,
            [studentId]: {
                ...markData[studentId],
                [field]: value
            },
        };

        // Call onSave with the updated marks object
        if (onSave) {
            onSave(updatedMarks);
        }

        if (setHasChanges) {
            setHasChanges(true);
        }
    };

    const handleCriterionChange = (studentId: number, criterionName: string, value: CriterionState | null) => {
        if (onCriterionChange) {
            // Use the drilled down handler from parent
            onCriterionChange(studentId, criterionName, value);
            return;
        }

        // Fallback implementation if no handler provided
        // Mark this criterion as manually modified (direct cell click)
        if (setManuallyModifiedCriteria) {
            setManuallyModifiedCriteria({
                ...manuallyModifiedCriteria,
                [studentId]: {
                    ...(manuallyModifiedCriteria[studentId] || {}),
                    [criterionName]: true
                },
            });
        }

        // Update the criterion value in marks
        const updatedMarks = {
            ...markData,
            [studentId]: {
                ...markData[studentId] || {},
                criteria: {
                    ...(markData[studentId]?.criteria || {}),
                    [criterionName]: value
                }
            }
        };

        // Call onSave with the updated marks object
        if (onSave) {
            onSave(updatedMarks);
        }

        if (setHasChanges) {
            setHasChanges(true);
        }
    };

    // const handleCriterionHeaderClick = (criterionName: string) => {
    //   if (onCriterionHeaderClick) {
    //     // Use the drilled down handler from parent
    //     onCriterionHeaderClick(criterionName);
    //   }
    // };

    // const handleSortRequest = (field: keyof Student | 'score' | 'grade') => {
    //   if (setSortConfig) {
    //     setSortConfig({
    //       sortBy: field,
    //       sortDirection: field === sortBy && sortDirection === 'asc' ? 'desc' : 'asc'
    //     });
    //   }
    // };

    const handleSnackbarClose = () => {
        if (onSnackbarClose) {
            onSnackbarClose();
        } else if (setSnackbar) {
            setSnackbar({
                ...snackbar,
                open: false
            });
        }
    };

    const handleSave = async () => {
        console.log("PTDetailView handleSave called");
        if (!onSave) {
            console.warn("No onSave handler provided to PTDetailView");
            return;
        }

        console.log("Setting save status to 'saving'");
        if (setSaveStatus) {
            setSaveStatus('saving');
        }

        try {
            console.log("Calling onSave with mark data:", markData);
            const result = await onSave(markData);
            console.log("Save result received in PTDetailView:", result);

            // Check if result exists before accessing its properties
            if (result) {
                if (result.success) {
                    console.log("Save successful, updating UI");
                    if (setSaveStatus) {
                        setSaveStatus('saved');
                    }

                    if (setSnackbar) {
                        setSnackbar({
                            open: true,
                            message: result.message || 'Mark data saved successfully',
                            severity: 'success'
                        });
                    }

                    if (setHasChanges) {
                        setHasChanges(false);
                    }

                    // Reset to idle after some time
                    setTimeout(() => {
                        console.log("Resetting save status to idle");
                        if (setSaveStatus) {
                            setSaveStatus('idle');
                        }
                    }, 3000);
                    return result;
                } else {
                    console.warn("Save failed:", result.message);
                    if (setSaveStatus) {
                        setSaveStatus('error');
                    }

                    if (setSnackbar) {
                        setSnackbar({
                            open: true,
                            message: result.message || 'Failed to save mark data',
                            severity: 'error'
                        });
                    }
                }
            } else {
                console.error("No result received from save operation");
                // Handle case where result is undefined
                if (setSaveStatus) {
                    setSaveStatus('error');
                }

                if (setSnackbar) {
                    setSnackbar({
                        open: true,
                        message: 'No response received from save operation',
                        severity: 'error'
                    });
                }
            }
        } catch (error) {
            console.error('Error saving mark data:', error);

            if (setSaveStatus) {
                setSaveStatus('error');
            }

            if (setSnackbar) {
                setSnackbar({
                    open: true,
                    message: error instanceof Error ? error.message : 'Failed to save mark data',
                    severity: 'error'
                });
            }
        }
    };

    // Function to check if a criterion is "locked"
    const isCriterionLocked = (studentId: number, criterionName: string): boolean => {
        // Check if the criterion was manually modified (direct cell click)
        if (manuallyModifiedCriteria[studentId]?.[criterionName]) {
            return true;
        }

        // Check if the criterion had an initial non-null value
        const initialValue = markData[studentId]?.criteria?.[criterionName];
        return initialValue !== null && initialValue !== undefined;
    };

    // Function to get the next state for a criterion
    const getNextCriterionState = (currentState: CriterionState | null): CriterionState | null => {
        // Define the cycle sequence (same as in CriterionCycleBox)
        const cycleStates: (CriterionState | null)[] = [
            {attained: true, referred: false, failed: false, attemptNumber: 1}, // A1
            {attained: false, referred: true, failed: false, attemptNumber: 1}, // R1
            {attained: true, referred: false, failed: false, attemptNumber: 2}, // A2
            {attained: false, referred: true, failed: false, attemptNumber: 2}, // R2
            {attained: false, referred: false, failed: true, attemptNumber: 2}, // F
            null, // Blank/Not attempted
        ];

        // Find current state index
        let currentIndex = cycleStates.length - 1; // Default to last (blank)
        if (currentState) {
            const foundIndex = cycleStates.findIndex(
                (state) =>
                    state !== null &&
                    state.attained === currentState.attained &&
                    state.referred === currentState.referred &&
                    state.failed === currentState.failed &&
                    state.attemptNumber === currentState.attemptNumber
            );
            if (foundIndex !== -1) {
                currentIndex = foundIndex;
            }
        }

        // Return next state in the cycle
        const nextIndex = (currentIndex + 1) % cycleStates.length;
        return cycleStates[nextIndex];
    };

    // Handle clicking on a criterion header - cycles all values for that criterion
    const handleCriterionHeaderClick = (criterionName: string) => {
        // Don't do anything if criteria are not editable
        if (partGuiConfig?.unitCriteria !== "EDITABLE") {
            return;
        }

        // Create a new marks object to store the updated marks
        const updatedMarks = {...markData};

        // For each student, cycle the criterion to the next state
        // BUT ONLY if the criterion is not "locked"
        students.forEach(student => {
            // Skip if this criterion is locked for this student
            if (isCriterionLocked(student.id, criterionName)) {
                return;
            }

            const studentMarks = updatedMarks[student.id] || {criteria: {}};
            const currentCriterionValue = studentMarks.criteria?.[criterionName] || null;
            const nextState = getNextCriterionState(currentCriterionValue);

            updatedMarks[student.id] = {
                ...studentMarks,
                criteria: {
                    ...(studentMarks.criteria || {}),
                    [criterionName]: nextState
                }
            };
        });

        // Call onSave with the updated marks
        if (onSave) {
            onSave(updatedMarks);
        }

        setHasChanges(true);
    };

    // Handle sorting when a column header is clicked
    const handleSortRequest = (field: keyof Student | 'score' | 'grade') => {
        const isAsc = sortBy === field && sortDirection === 'asc';
        setSortConfig({
            sortBy: field,
            sortDirection: isAsc ? 'desc' : 'asc'
        });
    };

    // Convert partGuiConfig to the format expected by PTMarkScreen
    const ptMarkScreenGuiConfig = {
        gradeCol: partGuiConfig.gradeCol,
        scoreCol: partGuiConfig.scoreCol,
        unitCriteria: partGuiConfig.unitCriteria,
        cellSummaryResultMetric: partGuiConfig.cellSummaryResultMetric
    };

    // Use external save status if provided, otherwise use internal
    const saveStatus = externalSaveStatus || 'idle';

    return (
        <>
            <Fade in={!loading} timeout={300}>
                <Box className="pt-detail-view">
                    <Grow in={!loading} timeout={400} style={{transformOrigin: '0 0 0'}}>
                        <div>                            <PTMarkScreen
                                trackerId={trackerId}
                                partId={partId}
                                students={students}
                                partGuiConfig={ptMarkScreenGuiConfig}
                                initialMarks={markData}
                                loading={loading}
                                onSave={handleSave}
                                saveStatus={saveStatus}
                                // Pass down all the handler functions and state
                                onMarkChange={handleMarkChange}
                                onCriterionChange={handleCriterionChange}
                                onCriterionHeaderClick={handleCriterionHeaderClick} onSortRequest={handleSortRequest}
                                sortBy={sortBy}
                                sortDirection={sortDirection}
                                manuallyModifiedCriteria={manuallyModifiedCriteria}
                                hasChanges={hasChanges}
                                onReload={onReload}
                                // Pass grade-related functions
                                getGradeOptionsForPart={getGradeOptionsForPart}
                                getGradeDisplayName={getGradeDisplayName}
                            />
                        </div>
                    </Grow>
                </Box>
            </Fade>

            {/* Snackbar for notifications - moved from PTMarkScreen to here */}
            <Snackbar
                open={snackbar.open}
                autoHideDuration={3000}
                onClose={handleSnackbarClose}
                anchorOrigin={{vertical: 'bottom', horizontal: 'right'}}
            >
                <Alert onClose={handleSnackbarClose} severity={snackbar.severity} sx={{width: '100%'}}>
                    {snackbar.message}
                </Alert>
            </Snackbar>
        </>
    );
};

export default PTDetailView;
