import React, { useState } from "react";
import
{
    Box,
    Typography,
    CircularProgress,
    Alert,
    Fade,
} from "@mui/material";
import { Part, Student } from "../PTMarkScreen/PTMarkScreen";
import { RulePresetDialog, RuleDetail } from "./RulePresetDialog";

// Import new components
import { PTFilterControls } from "./PTFilterControls";
import { PTNavTabs } from "./PTNavTabs";
import { PTSummaryView } from "./PTSummaryView";
import { PTDetailView } from "./PTDetailView";
import { Student } from "./ProgressTrackerModels";
import { MarkData } from "../../models/ProgressTrackerModels";

// Types for the component
export interface Tracker
{
    name: string;
    qualificationId: number;
    moduleId: number;
}

// @see src/Model/ProgressTracker/TrackerPartDto.php
export interface TrackerPart
{
    trackerPartId: number;
    partId: number;
    reference: string;
    category: string;
    // helptext?: string;
    name: string;
    parent: number; // Changed from parents: number[] to a single parent
    calculationRulePreset?: string;
}

export interface PartGui
{
    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";
}

// // Student type for PTMarkScreen
// export interface Student
// {
//     id: number;
//     fullName: string;
//     targetGrade: string | null;
//     reference?: string;
//     callouts?: string[];
//     pronouns?: string;
//     links?: { rel: string; href: string; type: string; title?: string }[];
// }


// New interface for part hierarchy node
export interface PartNode
{
    part: TrackerPart;
    children: { [id: number]: PartNode };
}

// New interface to track filter hierarchy
export interface FilterHierarchy
{
    category: string;
    level: number;
    parentCategory: string | null;
    categoryName: string;
    isRoot: boolean; // Added to identify root categories
}

// Helper function to check if an option is the "Show All" option
function isShowAllOption(option: TrackerPart | null): option is TrackerPart
{
    return option !== null && option !== undefined && option.trackerPartId === -1;
}

// Updated interface with all props passed from parent
export interface ModuleProgressTrackerProps
{
    trackerId: number;

    // Data states
    tracker: Tracker | null;
    parts: TrackerPart[];
    partGuis: PartGui[];
    students: Student[];
    partsById: { [id: number]: TrackerPart };
    partsHierarchy: { [category: string]: FilterHierarchy };

    // Mark data and loading states
    markDataByPart: { [partId: number]: { [studentId: number]: MarkData } };
    markScreenLoading: { [partId: number]: boolean };
    loading: boolean;
    error: string | null;

    // Filter and selection states
    selectedPartType: string | null;
    hierarchySelections: { [category: string]: any };
    visiblePartIds: Set<number>;
    activeTabIndex: number;

    // Summary view states
    showSummaryView: boolean;
    summaryParts: Part[];
    summaryPartMarks: { [partId: number]: { [studentId: number]: MarkData } };
    summaryViewLoading: boolean;

    // Rules dialog states
    rulePresetDialogOpen: boolean;
    rulePresetDialogOnClose: () => void;
    ruleDetails: RuleDetail | null;
    ruleLoading: boolean;

    // Editing and sorting states
    hasChangesByPart: { [partId: number]: boolean };
    manuallyModifiedCriteriaByPart: {
        [partId: number]: { [studentId: number]: { [criterionName: string]: boolean } }
    };
    sortConfigByPart: {
        [partId: number]: { sortBy: keyof Student | 'score' | 'grade' | null; sortDirection: 'asc' | 'desc' }
    };
    saveStatusByPart: { [partId: number]: 'idle' | 'saving' | 'saved' | 'error' };

    // UI notification state
    snackbar: {
        open: boolean;
        message: string;
        severity: 'success' | 'error' | 'info' | 'warning';
    };

    // Helper functions
    getPartTypeGroups: () => { [key: string]: TrackerPart[] };
    getParentCategories: (category: string) => string[];
    getChildCategories: (category: string) => string[];
    shouldShowContent: (category: string) => boolean;
    getMissingFilterName: (category: string) => string;
    getDeepestSelectedFilter: () => string | null;

    // Grade-related helper methods
    getGradesForPart: (partId: number) => any[];
    getGradeSchemeForPart: (partId: number) => any;
    getGradeDisplayName: (gradeRef: string, partId: number) => string;
    getGradeOptionsForPart: (partId: number) => Array<{ value: string; label: string }>;

    // Event handlers
    onFilterChange: (category: string, part: TrackerPart | null) => void;
    onTabChange: (index: number) => void;
    onClearFilters: () => void;
    onShowRules: () => void;
    onPartHeaderClick: (partId: number) => void;
    onMarkChange: (partId: number, studentId: number, field: string, value: any) => void;
    onCriterionChange: (partId: number, studentId: number, criterionName: string, value) => void;
    onCriterionHeaderClick: (partId: number, criterionName: string, students: Student[], partGuiConfig: PartGui) => void;
    onSortRequest: (partId: number, field: keyof Student | 'score' | 'grade') => void;
    onSaveMarkData: (partId: number, updatedMarks: { [studentId: number]: MarkData }) => Promise<{
        success: boolean;
        message: string
    }>;
    onSnackbarClose: () => void;    // API functions
    fetchTracker: (trackerId: number) => Promise<Tracker>;
    fetchTrackerParts: (trackerId: number) => Promise<TrackerPart[]>;
    fetchPartGuis: (trackerId: number) => Promise<PartGui[]>;
    fetchRuleDetails?: (rulePreset: string) => Promise<RuleDetail>;
    fetchMarkData?: (trackedPartId: number) => Promise<{ [studentId: number]: MarkData }>;
    saveMarkData?: (trackedPartId: number, markData: { [studentId: string]: MarkData }) => Promise<{
        success: boolean;
        message: string
    }>;
    loadMarkDataForPart: (trackerId: number, partId: number) => Promise<void>;
    loadSummaryView: (category: string) => Promise<void>;    // Reload functions
    reloadMarkDataForPart?: (partId: number) => Promise<void>;
    reloadMarkDataForPartAndParents?: (partId: number) => Promise<void>;
    reloadCurrentView?: () => Promise<void>;
    // Adding new props for the setter functions
    setManuallyModifiedCriteria: (partId: number, modifiedCriteria: {
        [studentId: number]: { [criterionName: string]: boolean }
    }) => void;
    setSortConfig: (partId: number, config: {
        sortBy: keyof Student | 'score' | 'grade' | null;
        sortDirection: 'asc' | 'desc'
    }) => void;
    setSaveStatus: (partId: number, status: 'idle' | 'saving' | 'saved' | 'error') => void;
    setSnackbar: (snackbar: {
        open: boolean;
        message: string;
        severity: 'success' | 'error' | 'info' | 'warning'
    }) => void;
}

export function ModuleProgressTracker({
    trackerId,
    tracker,
    parts,
    partGuis,
    students,
    partsById,
    partsHierarchy,
    markDataByPart,
    markScreenLoading,
    loading,
    error,
    selectedPartType,
    hierarchySelections,
    visiblePartIds,
    activeTabIndex,
    showSummaryView,
    summaryParts,
    summaryPartMarks,
    summaryViewLoading,
    rulePresetDialogOpen,
    rulePresetDialogOnClose,
    ruleDetails,
    ruleLoading,
    hasChangesByPart,
    manuallyModifiedCriteriaByPart,
    sortConfigByPart,
    saveStatusByPart,
    snackbar,
    getPartTypeGroups,
    getParentCategories,
    getChildCategories,
    shouldShowContent,
    getMissingFilterName,
    getDeepestSelectedFilter,
    getGradesForPart,
    getGradeSchemeForPart,
    getGradeDisplayName,
    getGradeOptionsForPart,
    onFilterChange,
    onTabChange,
    onClearFilters,
    onShowRules,
    onPartHeaderClick,
    onMarkChange,
    onCriterionChange,
    onCriterionHeaderClick,
    onSortRequest,
    onSaveMarkData,
    onSnackbarClose,
    // todo pt Remove unused.
    fetchTracker,
    fetchTrackerParts,
    fetchPartGuis,
    fetchRuleDetails, fetchMarkData,
    loadSummaryView,    // Reload functions
    reloadMarkDataForPart,
    reloadMarkDataForPartAndParents,
    reloadCurrentView,
    // Adding new props for the setter functions
    setManuallyModifiedCriteria,
    setSortConfig,
    setSaveStatus,
    setSnackbar
}: ModuleProgressTrackerProps)
{    // Get unique part types for tabs
    const partTypes = React.useMemo(() =>
    {
        // Get all unique category references from the parts array
        const uniqueCategories = Array.from(new Set(parts.map(p => p.category)));

        // Sort categories in logical order (QUALIFICATION -> UNIT -> ASSESSMENT -> CRITERIA)
        const categoryOrder = {
            "QUALIFICATION": 1,
            "UNIT": 2,
            "ASSESSMENT": 3,
            "CRITERIA": 4
        };

        const sortedCategories = uniqueCategories.sort((a, b) =>
        {
            return (categoryOrder[a] || 999) - (categoryOrder[b] || 999);
        });

        // Map to the expected format with parts for each category
        return sortedCategories.map(categoryRef =>
        {
            // Use partsHierarchy to get category name, or fall back to categoryRef
            const categoryName = partsHierarchy[categoryRef]?.categoryName || categoryRef;
            const categoryParts = parts.filter(p => p.category === categoryRef);

            return {
                ref: categoryRef,
                name: categoryName,
                parts: categoryParts
            };
        });
    }, [parts]);

    // State to track the copied ref code status
    const [copiedRef, setCopiedRef] = useState<number | null>(null);

    // Get a GUI config for a specific part
    const getPartGuiConfig = React.useCallback((partId: number) =>
    {
        return partGuis.find(gui => gui.partId === partId);
    }, [partGuis]);

    // Handle save marks for a specific part
    const handleSaveMarks = async (partId: number) =>
    {
        // todo pt Remove console.log statements
        console.log("ModuleProgressTracker handleSaveMarks called for partId:", partId);
        console.log("hasChangesByPart:", hasChangesByPart);
        console.log("hasChangesByPart[partId]:", hasChangesByPart[partId]);

        if (!hasChangesByPart[partId])
        {
            console.log("No changes detected for this part, not saving");
            return { success: false, message: "No changes to save" };
        }

        const marks = markDataByPart[partId] || {};
        console.log("Calling onSaveMarkData with marks:", marks);

        try
        {
            const result = await onSaveMarkData(partId, marks);
            console.log("Save result received in ModuleProgressTracker:", result);
            return result;
        } catch (error)
        {
            console.error("Error in handleSaveMarks:", error);
            return { success: false, message: "Error saving mark data" };
        }
    };

    if (loading)
    {
        return (
            <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '300px' }}>
                <CircularProgress />
            </Box>
        );
    }

    if (error)
    {
        return (
            <Box sx={{ p: 3 }}>
                <Alert severity="error">{error}</Alert>
            </Box>
        );
    }

    const currentPartType = partTypes[activeTabIndex];
    const currentCategory = currentPartType?.ref || "";
    const currentPart = hierarchySelections[currentCategory] || null;
    console.log('currentPartType', currentPartType);
    console.log('currentCategory', currentCategory);
    console.log('currentPart', currentPart);
    console.log('currentPart', currentPart);
    const currentIsShowAll = isShowAllOption(currentPart);
    // todo pt-future Use trackerPartId instead of partId ? (e.g. if a tracker wanted to override visibility etc).
    const currentGuiConfig = !currentIsShowAll && currentPart ? getPartGuiConfig(currentPart.partId) : undefined;
    const isLoading = currentIsShowAll ? summaryViewLoading : (currentPart && !isShowAllOption(currentPart)) ? markScreenLoading[currentPart.trackerPartId] : false;
    const activeCategory = getDeepestSelectedFilter() || currentCategory;
    const activeSelectedPart = hierarchySelections[activeCategory];
    const activeIsShowAll = isShowAllOption(activeSelectedPart);

    return (
        <Box sx={{ width: '100%' }} className="module-progress-tracker">
            {/* Simple heading for tracker name */}
            <h1>{tracker?.name || "Progress Tracker"}</h1>

            {/* Navigation Tabs */}
            <PTNavTabs
                partTypes={partTypes.map(type => ({ ref: type.ref, name: type.name }))}
                activeTabIndex={activeTabIndex}
                onTabChange={onTabChange}
            />

            {/* Content for each tab - render only the active one */}
            {partTypes.map((type, index) =>
            {
                // Only process the active tab
                if (index !== activeTabIndex) return null;

                const category = type.ref;

                return (
                    <Box key={`tab-content-${type.ref}`} sx={{ width: '100%', display: 'block' }}>
                        {/* Filter Controls */}
                        <PTFilterControls
                            selectedPartType={selectedPartType}
                            hierarchySelections={hierarchySelections}
                            partsHierarchy={partsHierarchy}
                            partTypeGroups={getPartTypeGroups()}
                            activeTabIndex={activeTabIndex}
                            parts={parts}
                            getParentCategories={getParentCategories}
                            onFilterChange={onFilterChange}
                            onClearFilters={onClearFilters}
                            onShowRules={onShowRules}
                        />

                        {/* Content area - either show summary view, detail view, or message */}
                        <Fade in={true} timeout={300}>
                            <Box className="">
                                {shouldShowContent(category) ? (
                                    <Box sx={{ mt: 2 }}>
                                        {isLoading ? (
                                            <Box sx={{ display: 'flex', justifyContent: 'center', p: 3 }}>
                                                <CircularProgress />
                                            </Box>) : students.length > 0 ? (
                                                <>
                                                    {/* Summary View */}
                                                    {activeIsShowAll && showSummaryView && summaryParts.length > 0 && (
                                                        <PTSummaryView
                                                            key={index}
                                                            trackerId={trackerId}
                                                            students={students}
                                                            summaryParts={summaryParts}
                                                            summaryPartMarks={summaryPartMarks}
                                                            loading={summaryViewLoading}
                                                            onPartHeaderClick={onPartHeaderClick}
                                                            getGradeOptionsForPart={getGradeOptionsForPart}
                                                            getGradeDisplayName={getGradeDisplayName}
                                                        />
                                                    )}

                                                    {/* Regular Detail View */}
                                                    {!activeIsShowAll && activeSelectedPart && currentGuiConfig && (
                                                        <>
                                                            {/* Title showing the reference code and part name - only show for non-root parts */}
                                                            {!partsHierarchy[activeSelectedPart.category]?.isRoot && (
                                                                <Typography variant="h6" sx={{
                                                                    mb: 2,
                                                                    color: 'text.primary',
                                                                    fontWeight: 'medium'
                                                                }}>

                                                                    {activeSelectedPart.name}

                                                                    <Box
                                                                        component="span"
                                                                        sx={{
                                                                            display: 'inline-flex',
                                                                            alignItems: 'center',
                                                                            backgroundColor: 'rgba(0, 0, 0, 0.04)',
                                                                            border: '1px solid rgba(0, 0, 0, 0.12)',
                                                                            borderRadius: '4px',
                                                                            px: 1,
                                                                            py: 0.3,
                                                                            ml: 1.5,
                                                                            cursor: 'pointer',
                                                                            fontSize: '0.85rem',
                                                                            '&:hover': {
                                                                                backgroundColor: 'rgba(0, 0, 0, 0.08)',
                                                                            }
                                                                        }}
                                                                        onClick={() =>
                                                                        {
                                                                            navigator.clipboard.writeText(activeSelectedPart.reference);
                                                                            // Set the copied ref id to show feedback
                                                                            setCopiedRef(activeSelectedPart.trackerPartId);
                                                                            // Reset after 2 seconds
                                                                            setTimeout(() =>
                                                                            {
                                                                                setCopiedRef(null);
                                                                            }, 2000);
                                                                        }}
                                                                        title="Click to copy reference code"
                                                                    >
                                                                        {copiedRef === activeSelectedPart.trackerPartId ? "✓ Copied" : activeSelectedPart.reference}
                                                                    </Box>

                                                                </Typography>
                                                            )}
                                                            <PTDetailView
                                                                trackerId={trackerId}
                                                                partId={activeSelectedPart.trackerPartId}
                                                                students={students}
                                                                partGuiConfig={currentGuiConfig} markData={markDataByPart[activeSelectedPart.trackerPartId] || {}}
                                                                loading={markScreenLoading[activeSelectedPart.trackerPartId] || false}
                                                                onSave={() => handleSaveMarks(activeSelectedPart.trackerPartId)} hasChanges={hasChangesByPart[activeSelectedPart.trackerPartId] || false}
                                                                setHasChanges={(hasChanges) => onMarkChange(activeSelectedPart.trackerPartId, -1, 'changes', hasChanges)}
                                                                manuallyModifiedCriteria={manuallyModifiedCriteriaByPart[activeSelectedPart.trackerPartId] || {}} setManuallyModifiedCriteria={(modifiedCriteria) => setManuallyModifiedCriteria(activeSelectedPart.trackerPartId, modifiedCriteria)}
                                                                sortConfig={sortConfigByPart[activeSelectedPart.trackerPartId] || {
                                                                    sortBy: null,
                                                                    sortDirection: 'asc'
                                                                }} setSortConfig={(config) => setSortConfig(activeSelectedPart.trackerPartId, config)}
                                                                saveStatus={saveStatusByPart[activeSelectedPart.trackerPartId] || 'idle'}
                                                                setSaveStatus={(status) => setSaveStatus(activeSelectedPart.trackerPartId, status)}
                                                                snackbar={snackbar}
                                                                setSnackbar={setSnackbar} onMarkChange={(studentId, field, value) => onMarkChange(activeSelectedPart.trackerPartId, studentId, field, value)} onCriterionChange={(studentId, criterionName, value) => onCriterionChange(activeSelectedPart.trackerPartId, studentId, criterionName, value)} onCriterionHeaderClick={(criterionName) => onCriterionHeaderClick(activeSelectedPart.trackerPartId, criterionName, students, currentGuiConfig)}
                                                                onSnackbarClose={onSnackbarClose}
                                                                onReload={reloadMarkDataForPartAndParents ? () => reloadMarkDataForPartAndParents(activeSelectedPart.trackerPartId) : undefined}
                                                                getGradeOptionsForPart={getGradeOptionsForPart}
                                                                getGradeDisplayName={getGradeDisplayName}
                                                            />
                                                        </>
                                                    )}                                                {/* Message when no content is displayed (e.g., multiple "Show All" filters selected) */}
                                                    {!(activeIsShowAll && showSummaryView && summaryParts.length > 0) &&
                                                        !(!activeIsShowAll && activeSelectedPart && currentGuiConfig) && (
                                                            <div className="message magnify mt-5" style={{
                                                                textAlign: 'center',
                                                                color: '#666'
                                                            }}>
                                                                Please select a specific item from one or more of the dropdown filters above to view content
                                                            </div>
                                                        )}
                                                </>
                                            ) : (
                                            <div className="warn message mt-5">
                                                No student data available. Please ensure students are enrolled in this
                                                module.
                                            </div>
                                        )}
                                    </Box>
                                ) : (
                                    <div className="message ml-1 mt-5">
                                        Please select a {getMissingFilterName(category)} item to view content
                                    </div>
                                )}
                            </Box>
                        </Fade>
                    </Box>
                );
            })}

            {/* Rules Dialog */}
            <RulePresetDialog
                open={rulePresetDialogOpen}
                onClose={rulePresetDialogOnClose}
                rulePreset={currentPart?.calculationRulePreset}
                ruleDetails={ruleDetails}
                loading={ruleLoading}
            />
        </Box>
    );
}

export default ModuleProgressTracker;
