import React, { useEffect, useState, useRef } from "react";
import { Box, Button, TextField, Typography, Grid, IconButton, Snackbar, Alert } from "@mui/material";
import { CameraAlt } from "@mui/icons-material";
import ScannerModal from "../components/ScannerModal";
import Storage from "../components/Storage";
import { OpenAPI, LogisticsService } from "../../../frontend/openapi";
import type { Slot as SlotSchema, Dewar } from "../../../frontend/openapi/models";
import styled from "styled-components";
import moment from "moment";
import { format } from "date-fns";

// Additional required declarations (map storage settings, props, etc.)
const slotQRCodes = [
    "A1-X06SA", "A2-X06SA", "A3-X06SA", "A4-X06SA", "A5-X06SA",
    "B1-X06SA", "B2-X06SA", "B3-X06SA", "B4-X06SA", "B5-X06SA",
    "C1-X06SA", "C2-X06SA", "C3-X06SA", "C4-X06SA", "C5-X06SA",
    "D1-X06SA", "D2-X06SA", "D3-X06SA", "D4-X06SA", "D5-X06SA",
    "A1-X10SA", "A2-X10SA", "A3-X10SA", "A4-X10SA", "A5-X10SA",
    "B1-X10SA", "B2-X10SA", "B3-X10SA", "B4-X10SA", "B5-X10SA",
    "C1-X10SA", "C2-X10SA", "C3-X10SA", "C4-X10SA", "C5-X10SA",
    "D1-X10SA", "D2-X10SA", "D3-X10SA", "D4-X10SA", "D5-X10SA",
    "NB1", "NB2", "NB3", "NB4", "NB5", "NB6"
];

const beamlineQRCodes = [
    "X10SA-Beamline", "X06SA-Beamline", "X06DA-Beamline"
];

const outgoingQRCodes = [
    "Outgoing X10SA", "Outgoing X06SA"
];

const storageToSlotsMapping = {
    "X06SA-storage": [
        "A1-X06SA", "A2-X06SA", "A3-X06SA", "A4-X06SA", "A5-X06SA",
        "B1-X06SA", "B2-X06SA", "B3-X06SA", "B4-X06SA", "B5-X06SA",
        "C1-X06SA", "C2-X06SA", "C3-X06SA", "C4-X06SA", "C5-X06SA",
        "D1-X06SA", "D2-X06SA", "D3-X06SA", "D4-X06SA", "D5-X06SA"
    ],
    "X10SA-storage": [
        "A1-X10SA", "A2-X10SA", "A3-X10SA", "A4-X10SA", "A5-X10SA",
        "B1-X10SA", "B2-X10SA", "B3-X10SA", "B4-X10SA", "B5-X10SA",
        "C1-X10SA", "C2-X10SA", "C3-X10SA", "C4-X10SA", "C5-X10SA",
        "D1-X10SA", "D2-X10SA", "D3-X10SA", "D4-X10SA", "D5-X10SA"
    ],
    "Novartis-Box": ["NB1", "NB2", "NB3", "NB4", "NB5", "NB6"]
};

interface SlotData extends SlotSchema {
    dewar: Dewar | null;
    qr_code: string;
    dewar_name?: string;
    needsRefillWarning?: boolean;
    retrievedTimestamp?: string;        // Add timestamp map
    beamlineLocation?: string;         // Add beamline field
    shipment_name?: string;            // Add shipment
    contact?: string;                  // Add contact person
    local_contact?: string;            // Add local contact
    Time_until_refill?: number;
}


const DetailPanel = styled(Box)`
    width: 100%;
    padding: 20px;
    background-color: white;
    margin-top: 20px;
    border-radius: 10px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    display: flex;
    flex-direction: column;
`;

const LogisticsTrackingTab: React.FC = () => {
    const [dewarQr, setDewarQr] = useState<string | null>(null);
    const [locationQr, setLocationQr] = useState<string | null>(null);
    const [transactionType, setTransactionType] = useState<string>("");
    const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
    const [selectedSlot, setSelectedSlot] = useState<string | null>(null);
    const [sslError, setSslError] = useState<boolean>(false);
    const [warningMessage, setWarningMessage] = useState<string | null>(null);
    const [selectedSlotData, setSelectedSlotData] = useState<SlotData | null>(null);
    const [loading, setLoading] = useState<boolean>(false);
    const [error, setError] = useState<string | null>(null);
    const [slotsData, setSlotsData] = useState<SlotData[]>([]);

    useEffect(() => {
        // Detect the current environment
        const mode = import.meta.env.MODE;

        // Dynamically set `OpenAPI.BASE` based on the 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;

        // Log warning if `OpenAPI.BASE` is unresolved
        if (!OpenAPI.BASE) {
            console.error('OpenAPI.BASE is not set. Falling back to a default value.');
            OpenAPI.BASE = 'https://default-url.com'; // Use a consistent fallback
        }

        // Debug for mode and resolved `BASE`
        console.log('Environment Mode:', mode);
        console.log('Resolved OpenAPI.BASE:', OpenAPI.BASE);
    }, []);

    const fetchDewarsAndSlots = async () => {
        try {
            console.log("Fetching dewars and slots...");
            setLoading(true);
            setError(null);
            setWarningMessage(null);

            // Fetch dewars and slots in parallel
            const [dewars, slots] = await Promise.all([
                LogisticsService.getAllDewarsLogisticsDewarsGet(),
                LogisticsService.getAllSlotsLogisticsSlotsGet(),
            ]);

            console.log("Dewars fetched:", dewars);
            console.log("Slots fetched:", slots);

            const dewarMap: { [key: string]: Dewar } = {};
            const usedDewarUniqueIds = new Map<string, string>();

            // Map dewars by unique_id
            dewars.forEach((dewar) => {
                if (dewar.unique_id) {
                    dewarMap[dewar.unique_id] = dewar;
                    console.log(`Mapped Dewar: ${dewar.unique_id}`);
                }
            });

            // Process and map slots
            const newSlotsData = slots.map((slot) => {
                let associatedDewar: Dewar | undefined;

                // Check if slot has a dewar assigned
                if (slot.dewar_unique_id) {
                    if (usedDewarUniqueIds.has(slot.dewar_unique_id)) {
                        const existingSlotId = usedDewarUniqueIds.get(slot.dewar_unique_id);
                        console.warn(`Duplicate dewar assignment: Slot ${slot.id} and Slot ${existingSlotId}`);
                        setWarningMessage(`Dewar ${slot.dewar_unique_id} is assigned to multiple slots.`);
                        return { ...slot, occupied: false, dewar: null }; // Mark unoccupied
                    } else {
                        associatedDewar = dewarMap[slot.dewar_unique_id];
                        if (associatedDewar) usedDewarUniqueIds.set(slot.dewar_unique_id, slot.id);
                    }
                }

                // Return the enriched slot
                return {
                    ...slot,
                    occupied: !!associatedDewar,
                    dewar: associatedDewar || null,
                    dewar_name: associatedDewar?.dewar_name,
                    needsRefillWarning: !associatedDewar || !slot.time_until_refill,
                };
            });

            // Sort slots by QR code
            newSlotsData.sort((a, b) => a.qr_code.localeCompare(b.qr_code));

            // Update state
            setSlotsData(newSlotsData);
        } catch (e) {
            console.error("Error fetching dewars/slots:", e);
            setError("Failed to load logistics data.");
        } finally {
            setLoading(false);
        }
    };


    useEffect(() => {
        fetchDewarsAndSlots();
    }, []);

    const formatTimestamp = (timestamp: string | undefined) => {
        if (!timestamp) return 'N/A';
        const date = new Date(timestamp);
        return format(date, 'PPpp', { addSuffix: true });
    };

    // Reference to the audio element
    const audioRef = useRef<HTMLAudioElement | null>(null);

    const handleSlotSelection = async (data: { text: string }) => {
        const scannedText = data.text.trim();
        console.log(`Detected QR code: ${scannedText}`);

        // Case 1: Scanned QR code is a Beamline QR Code
        if (beamlineQRCodes.includes(scannedText)) {
            console.log(`Detected beamline QR code: ${scannedText}`);

            // Determine the Dewar ID either from the scanned Dewar or selected slot
            const dewarId = dewarQr || slotsData.find(slot => slot.qr_code === selectedSlot)?.dewar?.unique_id;

            if (dewarId) {
                console.log(`Moving dewar ${dewarId} to beamline ${scannedText}`);
                try {
                    const timestamp = moment().toISOString();
                    // Assign the dewar to the beamline via POST request
                    await LogisticsService.scanDewarLogisticsDewarScanPost({
                        dewar_qr_code: dewarId,
                        location_qr_code: scannedText,
                        transaction_type: 'beamline',
                        timestamp: timestamp,
                    });

                    fetchDewarsAndSlots(); // Refresh state
                    setWarningMessage(`Dewar ${dewarId} successfully moved to beamline ${scannedText}.`);
                } catch (e) {
                    console.error("Error moving Dewar to beamline:", e);
                    setError("Failed to move Dewar to beamline. Please try again.");
                }
            } else {
                console.error("No Dewar QR code or selected Dewar found.");
                alert("Please select or scan a Dewar before scanning the beamline QR code.");
            }
            return;
        }

        // Case 2: Scanned QR code is an Outgoing QR Code
        if (outgoingQRCodes.includes(scannedText)) {
            console.log(`Detected outgoing QR code: ${scannedText}`);
            setDewarQr(scannedText);
            handleOutgoing();
            return;
        }

        // Case 3: Scanned QR code is a Slot QR Code
        if (slotQRCodes.includes(scannedText)) {
            console.log(`Detected slot QR code: ${scannedText}`);
            const slot = slotsData.find(slot => slot.qr_code === scannedText);

            setLocationQr(scannedText);
            setSelectedSlot(scannedText);

            if (slot?.dewar?.unique_id) {
                console.log(`Returning dewar ${slot.dewar.unique_id} to slot ${scannedText}`);
                await returnDewarToStorage(slot.dewar.unique_id, scannedText);
            } else {
                fetchDewarAndAssociate(scannedText);
            }
            return;
        }

        // Case 4: Scanned QR code is a Dewar QR Code
        console.log("Scanned text is not a slot or beamline. Assuming it is a Dewar QR code.");
        try {
            const dewar = await LogisticsService.getDewarByUniqueIdLogisticsDewarUniqueIdGet(scannedText);
            setDewarQr(dewar.unique_id);
            console.log(`Fetched Dewar: ${dewar.unique_id}`);
            if (audioRef.current) {
                audioRef.current.play();
            }
        } catch (e) {
            console.error("Error fetching Dewar details:", e);
            if (e.message.includes("404")) {
                alert("Dewar not found for this QR code.");
            } else {
                setError("Failed to fetch Dewar details. Please try again.");
            }
        }
    };

    const returnDewarToStorage = async (dewarId: string, slotQrCode: string) => {
        const payload = {
            dewar_qr_code: dewarId,
            location_qr_code: slotQrCode,
            transaction_type: "returned",
        };

        console.log("Sending payload:", payload);
        console.log(`Dewar ID: ${dewarId}, Slot QR Code: ${slotQrCode}`);

        try {
            await LogisticsService.returnToStorageLogisticsDewarsReturnPost(payload);

            fetchDewarsAndSlots();
            alert(`Dewar ${dewarId} successfully returned to storage.`);
        } catch (error) {
            console.error('Failed to return dewar to storage:', error);
            if (error.status === 400 && error.response?.data?.detail === "Selected slot is already occupied") {
                alert('Selected slot is already occupied. Please choose a different slot.');
            } else {
                console.error('Unexpected error occurred:', error);
                alert('Failed to return dewar to storage.');
            }

            setError('Failed to return dewar to storage.');
        }
    };

    const handleSlotSelect = (slot: SlotData) => {
        if (selectedSlot === slot.qr_code) {
            // Deselect if the same slot is clicked again
            setSelectedSlot(null);
            setLocationQr(null);
            setSelectedSlotData(null);
            setDewarQr(null); // Clear Dewar QR code
        } else {
            // Set the selected slot and its data
            setSelectedSlot(slot.qr_code);
            setLocationQr(slot.qr_code);
            setSelectedSlotData(slot);

            // If occupied, set the `dewar_unique_id` to the `Dewar QR Code` field
            setDewarQr(slot.dewar?.unique_id || null);
        }
    };

    const fetchDewarAndAssociate = async (scannedText: string) => {
        try {
            const dewar = await LogisticsService.getDewarByUniqueIdLogisticsDewarUniqueIdGet(scannedText);
            setDewarQr(dewar.unique_id);
            if (audioRef.current) {
                audioRef.current.play();
            }
        } catch (e) {
            console.error(e);
            if (e.message.includes('SSL')) {
                setSslError(true);
            } else {
                alert('No dewar found with this QR code.');
            }
        }
    };

    const handleRefillDewar = async (qrCode?: string) => {
        const dewarUniqueId = qrCode || slotsData.find(slot => slot.qr_code === selectedSlot)?.dewar?.unique_id;
        if (!dewarUniqueId) {
            alert('No dewar associated with the selected slot.');
            return;
        }

        try {
            const trimmedUniqueId = dewarUniqueId.trim();
            const response = await LogisticsService.refillDewarLogisticsDewarRefillPost(trimmedUniqueId);

            if (response && response.time_until_refill) {
                alert(`Dewar refilled successfully. Time until next refill: ${response.time_until_refill}`);
            } else {
                alert('Dewar refilled successfully.');
            }

            fetchDewarsAndSlots();
        } catch (e) {
            console.error(e);
            alert('Error in refilling dewar');
        }
    };

    const handleSubmit = async () => {
        if (!dewarQr || !locationQr || !transactionType) {
            alert('All fields are required.');
            return;
        }

        if (!dewarQr.trim()) {
            alert('Dewar QR code should not be empty.');
            return;
        }

        const conflictingSlots = slotsData.filter(
            slot => slot.dewar?.unique_id === dewarQr && slot.qr_code !== locationQr
        );

        if (conflictingSlots.length > 0) {
            alert(`Dewar ${dewarQr} is already assigned to slot ${conflictingSlots[0].qr_code}. Please resolve the conflict first.`);
            return;
        }

        try {
            const timestamp = moment().toISOString();
            await LogisticsService.scanDewarLogisticsDewarScanPost({
                dewar_qr_code: dewarQr.trim(),
                location_qr_code: locationQr.trim(),
                transaction_type: transactionType,
                timestamp: timestamp,
            });

            alert('Dewar status updated successfully');
            if (audioRef.current) {
                audioRef.current.play();
            }

            fetchDewarsAndSlots();
        } catch (e) {
            console.error(e);
            alert('Error updating dewar status');
        }
    };

    const handleOutgoing = async () => {
        if (!dewarQr) {
            alert('Scan a dewar QR code first.');
            return;
        }

        try {
            await LogisticsService.scanDewarLogisticsDewarScanPost({
                dewar_qr_code: dewarQr,
                location_qr_code: dewarQr, // Using dewar QR code as location for outgoing
                transaction_type: 'outgoing',
                timestamp: moment().toISOString(),
            });

            alert(`Dewar ${dewarQr} is now marked as outgoing.`);
            fetchDewarsAndSlots();
        } catch (e) {
            console.error(e);
            alert('Error marking dewar as outgoing');
        }
    };

    return (
        <Box>
            <Typography variant="h4" gutterBottom>
                Logistics Tracking
            </Typography>

            <Grid container spacing={2}>
                <Grid item xs={12} sm={6}>
                    <Box display="flex" flexDirection="column" alignItems="flex-start">
                        <Typography variant="h6">Dewar QR Code</Typography>
                        <TextField
                            label="Enter Dewar QR Code"
                            variant="outlined"
                            fullWidth
                            value={dewarQr ?? ''}
                            onChange={(e) => setDewarQr(e.target.value)}
                            sx={{ mb: 2 }}
                        />
                        <IconButton onClick={() => setIsModalOpen(true)} sx={{ fontSize: 40, mb: 2 }}>
                            <CameraAlt fontSize="inherit" />
                        </IconButton>

                        <Typography variant="h6">Selected Slot</Typography>
                        <TextField
                            label="Slot QR Code"
                            variant="outlined"
                            fullWidth
                            value={locationQr ?? ''}
                            onChange={(e) => setLocationQr(e.target.value)}
                            sx={{ mb: 2 }}
                            disabled
                        />

                        <Button
                            variant="contained"
                            onClick={() => setTransactionType('incoming')}
                            color={transactionType === 'incoming' ? 'primary' : 'default'}
                            sx={{ mb: 1 }}
                        >
                            Incoming
                        </Button>
                        <Button
                            variant="contained"
                            onClick={() => setTransactionType('outgoing')}
                            color={transactionType === 'outgoing' ? 'primary' : 'default'}
                            sx={{ mb: 2 }}
                        >
                            Outgoing
                        </Button>

                        <Button variant="contained" color="primary" onClick={handleSubmit} sx={{ mb: 2 }}>
                            Submit
                        </Button>
                        <Button variant="contained" color="secondary" onClick={() => handleRefillDewar()}>
                            Refill Dewar
                        </Button>
                    </Box>
                </Grid>

                <Grid item xs={12} sm={6}>
                    {selectedSlotData ? (
                        <Grid item xs={12} sm={6}>
                            {selectedSlotData ? (
                                <DetailPanel>
                                    <Typography variant="h6">{selectedSlotData.label}</Typography>
                                    <Typography variant="body2">{`Shipment: ${selectedSlotData.shipment_name}`}</Typography>
                                    <Typography variant="body2">{`Dewar: ${selectedSlotData.dewar_name || 'N/A'}`}</Typography>
                                    <Typography variant="body2">{`Contact Person: ${selectedSlotData.contact}`}</Typography>
                                    <Typography variant="body2">{`QR Code: ${selectedSlotData.qr_code}`}</Typography>
                                    <Typography variant="body2">{`Occupied: ${selectedSlotData.occupied ? 'Yes' : 'No'}`}</Typography>
                                    <Typography variant="body2">{`Needs Refill: ${selectedSlotData.needsRefillWarning ? 'Yes' : 'No'}`}</Typography>
                                    <Typography variant="body2">{`Time Until Refill: ${selectedSlotData.time_until_refill ?? 'N/A'}`}</Typography>
                                    <Typography variant="body2">{`Last Event: ${formatTimestamp(selectedSlotData.retrievedTimestamp)}`}</Typography>
                                    <Typography variant="body2">{`Local Contact: ${selectedSlotData.local_contact}`}</Typography>
                                    <Typography variant="body2">{`Beamline Location: ${selectedSlotData.beamlineLocation || 'N/A'}`}</Typography>
                                </DetailPanel>
                            ) : (
                                <Typography variant="h6">Select a slot to see more details.</Typography>
                            )}
                        </Grid>
                    ) : (
                        <Typography>No slot selected</Typography>
                    )}
                </Grid>
            </Grid>

            {loading ? (
                <Typography mt={2}>Loading...</Typography>
            ) : error ? (
                <Typography mt={2} color="error">{error}</Typography>
            ) : (
                <Box>
                    {['X06SA-storage', 'X10SA-storage', 'Novartis-Box'].map((storageKey) => {
                        const filteredSlots = slotsData.filter((slot) => storageToSlotsMapping[storageKey].includes(slot.qr_code));
                        return (
                            <Storage
                                key={storageKey}
                                name={storageKey}
                                selectedSlot={selectedSlot}
                                slotsData={filteredSlots}
                                onSelectSlot={handleSlotSelect}
                                onRefillDewar={handleRefillDewar}
                            />
                        );
                    })}
                </Box>
            )}

            <ScannerModal open={isModalOpen} onClose={() => setIsModalOpen(false)} onScan={handleSlotSelection} />

            <Snackbar open={sslError} autoHideDuration={6000} onClose={() => setSslError(false)}>
                <Alert onClose={() => setSslError(false)} severity="error">
                    SSL Error: Unable to establish a secure connection with the server.
                </Alert>
            </Snackbar>

            {warningMessage && (
                <Snackbar open autoHideDuration={6000} onClose={() => setWarningMessage(null)}>
                    <Alert severity="warning" onClose={() => setWarningMessage(null)}>
                        {warningMessage}
                    </Alert>
                </Snackbar>
            )}

            {error && (
                <Snackbar open autoHideDuration={6000} onClose={() => setError(null)}>
                    <Alert severity="error" onClose={() => setError(null)}>
                        {error}
                    </Alert>
                </Snackbar>
            )}

            <audio ref={audioRef} src="src/assets/50565__broumbroum__sf3-sfx-menu-validate.wav" preload="auto" />
        </Box>
    );
};

export default LogisticsTrackingTab;