import React, { Component } from "react";
import { __ } from "@wordpress/i18n";
import { ThemeProvider } from "@mui/material/styles";
import { 
    Box, Grid, FormControl, Select,
    MenuItem, TextField, Chip, Skeleton, Typography
} from "@mui/material";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import dayjs from "dayjs";

class AppointmentFields extends Component {

    state = {
        services: [],
        staffs: [],
        daysOpen: [],
        holidays: [],
        specialDate: [],
        slots: [],
        statuses: [
            "Pending",
            "Confirmed",
            "Completed",
            "Delayed",
            "On Hold",
            "Cancelled"
        ],
    }

    componentDidMount() {
        this.loadInitialData();
    }

    loadInitialData = () => {
        const { formData } = this.props;
        const ProLocation = window.ProLocation;

        if ( ProLocation ) {
            if ( formData.appointmentService !== "none" ) {
                this.handleLocationChange({ target: { name: "appointmentLocation", value: formData.appointmentLocation } }, true)
            }
        } else {
            if ( formData.appointmentService !== "none" ) {
                this.handleServiceChange({ target: { name: "appointmentService", value: formData.appointmentService } }, true)
            }
        }
    }

    handleLocationChange = ( event, initialLoad = false ) => {

        const { value } = event.target;
        const { setState } = this.props;

        const dataToSend = {};
        dataToSend.location_id = value;

        fetch(`${wpbAdmin.root}bookify/v1/services-by-location`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-WP-Nonce": wpApiSettings.nonce
            },
            body: JSON.stringify(dataToSend)
        })
        .then(response => response.json())
        .then(data => {
            setState(prevState => ({
                formData: {
                    ...prevState.formData,
                    appointmentLocation: value,
                    appointmentService: initialLoad ? prevState.formData.appointmentService : "",
                    appointmentStaff: initialLoad ? prevState.formData.appointmentStaff : "",
                    appointmentDate: initialLoad ? prevState.formData.appointmentDate : null,
                    appointmentDuration: initialLoad ? prevState.formData.appointmentDuration : [],
                    appointmentCustomer: initialLoad ? prevState.formData.appointmentCustomer : "",
                },
                errors: { 
                    ...prevState.errors,
                     appointmentLocation: false 
                },
            }));
            this.setState({
                services: data.services,
                staffs: [],
                slots: [],
                daysOpen: [],
                specialDate: [],
                holidays: []
            });

            if ( initialLoad && "none" != this.props.formData.appointmentService ) {
                this.handleServiceChange({ target: { name: "appointmentService", value: this.props.formData.appointmentService } }, true);
            }

        })
        .catch(error => {
            console.error("Error:", error);
        })
    }

    handleServiceChange = (event, initialLoad = false) => {
        const { value } = event.target;
        const { setState } = this.props;
    
        const dataToSend = {};
        dataToSend.service_id = value;
    
        fetch(`${wpbAdmin.root}bookify/v1/staffs-by-service`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-WP-Nonce": wpApiSettings.nonce
            },
            body: JSON.stringify(dataToSend)
        })
        .then(response => response.json())
        .then(data => {
            setState(prevState => ({
                formData: {
                    ...prevState.formData,
                    appointmentService: value,
                    appointmentStaff: initialLoad ? prevState.formData.appointmentStaff : "",
                    appointmentDate: initialLoad ? prevState.formData.appointmentDate : null,
                    appointmentDuration: initialLoad ? prevState.formData.appointmentDuration : [],
                    appointmentCustomer: initialLoad ? prevState.formData.appointmentCustomer : "",
                },
                errors: { 
                    ...prevState.errors,
                     appointmentService: false 
                },
            }));
            this.setState({
                staffs: data.staffs,
                slots: [],
                daysOpen: [],
                specialDate: [],
                holidays: []
            });

            if ( initialLoad && "none" != this.props.formData.appointmentStaff ) {
                this.handleStaffChange({ target: { name: "appointmentStaff", value: this.props.formData.appointmentStaff } }, true);
            }

        })
        .catch(error => {
            console.error("Error:", error);
        })
    }

    handleStaffChange = (event, initialLoad = false) => {
        const { value } = event.target;
        const { staffs } = this.state;
        const { setState } = this.props;

        const dataToSend = {};
        dataToSend.staff_id = value;

        fetch(`${wpbAdmin.root}bookify/v1/dates-by-staff`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-WP-Nonce": wpApiSettings.nonce
            },
            body: JSON.stringify(dataToSend)
        })
        .then(response => response.json())
        .then(data => {

            const selectedStaff = staffs.find(staff => staff.staff_id === value);
            const servicePrice = selectedStaff ? selectedStaff.service_price : 0;

            setState(prevState => ({
                formData: {
                    ...prevState.formData,
                    appointmentStaff: value,
                    appointmentDate: initialLoad ? prevState.formData.appointmentDate : null,
                    appointmentDuration: initialLoad ? prevState.formData.appointmentDuration : [],
                    appointmentCustomer: initialLoad ? prevState.formData.appointmentCustomer : "",
                },
                errors: { 
                    ...prevState.errors,
                    appointmentStaff: false 
                },
                servicePrice: servicePrice,
            }));
            this.setState({
                daysOpen: data.dates,
                specialDate: data.special,
                holidays: data.holidays
            });

            if (initialLoad && this.props.formData.appointmentDate) {
                this.handleDateChange( this.props.formData.appointmentDate, true );
            }
        })
        .catch(error => {
            console.error("Error:", error);
        })
    }

    handleDateChange = (date, initialLoad = false) => {
        const weekDay = date.day();
        const selectedDate = dayjs(date).format("YYYY-MM-DD");
        const { formData, setState, timeFormat } = this.props;
        const timeFormated = timeFormat === "12-hour" ? "hh:mm A" : "HH:mm";
    
        const { daysOpen, specialDate } = this.state;
    
        let timeSlots = [];
        let isSpecialDate = false;
    
        for (let key in specialDate) {
            if (specialDate[key].date === selectedDate) {
                timeSlots = specialDate[key].slots;
                isSpecialDate = true;
                break;
            }
        }
    
        if (!isSpecialDate) {
            for (let key in daysOpen) {
                if (daysOpen[weekDay]) {
                    timeSlots = daysOpen[weekDay].slots;
                    break;
                }
            }
        }
    
        const dataToSend = {};
        dataToSend.date = selectedDate;
        dataToSend.slots = JSON.stringify(timeSlots);
        dataToSend.staff_id = formData.appointmentStaff;
    
        fetch(`${wpbAdmin.root}bookify/v1/available-slots`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-WP-Nonce": wpApiSettings.nonce
            },
            body: JSON.stringify(dataToSend)
        })
        .then(response => response.json())
        .then(data => {

            const formattedAppointmentDuration = formData.appointmentDuration.map((duration) => {
                const times = duration.split(" - ");
                return times
                    .map((time) => dayjs(`1970-01-01 ${time}`).format(timeFormated))
                    .join(" - ");
            });
    
            formData.appointmentDuration = formattedAppointmentDuration;
    
            let availableSlots = data.available_slots;
            if (initialLoad && formData.appointmentDuration !== "none") {
                const updatedSlots = data.available_slots.concat( formattedAppointmentDuration );
                availableSlots = this.sortTimeSlots(updatedSlots);
            }
    
            setState(prevState => ({
                formData: {
                    ...prevState.formData,
                    appointmentDate: date,
                    appointmentDuration: initialLoad ? prevState.formData.appointmentDuration : [],
                },
                errors: { ...prevState.errors, appointmentDate: false },
                loadingData: false,
            }));
    
            this.setState({
                slots: availableSlots,
            });
        })
        .catch(error => {
            console.error("Error:", error);
        });
    };

    shouldDisableDate = (date) => {
        const { daysOpen, holidays, specialDate } = this.state;
        const day = date.day();

        const specialDates = Object.values(specialDate).map(entry => entry.date);

		if (specialDates.includes(date.format("YYYY-MM-DD"))) {
			return false;
		}

        if (daysOpen.length <= 0) {
            return true;
        }
    
        const eachDay = Object.keys(daysOpen).map(day => parseInt(day));
        const isDayOpen = eachDay.includes(day);
        
        if (holidays.length > 0) {
            const holidayObjects = JSON.parse(holidays);
            const holidayDates = Object.values(holidayObjects).map(holiday => holiday.dateFormated);
            const isHoliday = holidayDates.includes(date.format("YYYY-MM-DD"));

            return !isDayOpen || isHoliday;
        }

        return !isDayOpen;
    }

    handleInputChange = (event) => {
        const { name, value } = event.target;
        const { setState } = this.props;

        setState(prevState => ({
            formData: {
                ...prevState.formData,
                [name]: value,
            },
            errors: { ...prevState.errors, [name]: false }
        }));
    };

    sortTimeSlots = (slots) => {
        return Array.from(
            new Set(
                slots
                    .map(slot => {
                        const [start, end] = slot.split(" - ");
                        const [startHour, startMinute] = start.split(":").map(Number);
                        return {
                            slot,
                            startHour,
                            startMinute
                        };
                    })
                    .sort((a, b) => {
                        if (a.startHour !== b.startHour) return a.startHour - b.startHour;
                        return a.startMinute - b.startMinute;
                    })
                    .map(item => item.slot)
            )
        );
    };

    render() { 

        const { theme, locations, customers,  formData, errors, dateFormat, priorToggle, priorTime, loadingData } = this.props;
        const { statuses, staffs, slots } = this.state;
        const ProLocation = window.ProLocation;
        const ProMultipleBooking = window.ProMultipleBooking;
        const allservices = ProLocation ? this.state.services : this.props.services;

        let maxDate = null;
        if ( priorToggle == "Enable" ) {
            maxDate = dayjs().add(parseInt(priorTime), "month");
        }
        const appointmentStaffData = staffs.find(staff => staff.staff_id === formData.appointmentStaff);
        const staffMultipleBooking = appointmentStaffData ? JSON.parse( appointmentStaffData.mulitple_booking ) : false;

        return (
            <>
                <ThemeProvider theme={theme}>
                    {loadingData ? (
                        <Box>
                            <Grid container spacing={2}>
                                {Array.from(new Array(7)).map((_, index) => (
                                    <Grid item xs={12} key={index}>
                                        <Skeleton
                                            variant="rectangular"
                                            animation="wave"
                                            height={56}
                                            width={"100%"}
                                            sx={{
                                                borderRadius:"5px",
                                            }}
                                        />
                                    </Grid>
                                ))}
                            </Grid>
                        </Box>
                    ) : (
                        <Box component="form">
                            <Grid container spacing={3} direction="column">
                                {ProLocation && (
                                    <Grid item>
                                        <FormControl fullWidth>
                                            <Typography variant="wpbkThemeLabel" component="label" htmlFor="appointment-location">
                                                {__("Locations ", "bookify")}
                                                <span style={{color:"#A61616"}}>*</span>
                                            </Typography>
                                            <Select
                                                id="appointment-location"
                                                name="appointmentLocation"
                                                required
                                                error={errors.appointmentLocation}
                                                value={formData.appointmentLocation}
                                                onChange={(event) => this.handleLocationChange(event, false)}
                                                sx={{
                                                    height: "45px",
                                                    "& fieldset": {
                                                        border: "none",
                                                    },
                                                    "&.MuiOutlinedInput-root": {
                                                        mt: "0px",
                                                        border: "1px solid",
                                                        borderColor: errors.appointmentLocation ? "error.main" : "#BFD4D4",
                                                    },
                                                }}
                                            >
                                                <MenuItem value="" disabled>
                                                    {__("Select Location", "bookify")}
                                                </MenuItem>
                                                {locations.map((value) => (
                                                    <MenuItem key={value.id} value={value.id}>
                                                        {value.location_name}
                                                    </MenuItem>
                                                ))}
                                            </Select>
                                        </FormControl>
                                    </Grid>
                                )}
                                <Grid item>
                                    <FormControl fullWidth>
                                        <Typography variant="wpbkThemeLabel" component="label" htmlFor="appointment-services">
                                            {__("Services ", "bookify")}
                                            <span style={{color:"#A61616"}}>*</span>
                                        </Typography>
                                        <Select
                                            id="appointment-services"
                                            name="appointmentService"
                                            required
                                            error={errors.appointmentService}
                                            value={formData.appointmentService}
                                            onChange={(event) => this.handleServiceChange(event, false)}
                                            sx={{
                                                height: "45px",
                                                "& fieldset": {
                                                    border: "none",
                                                },
                                                "&.MuiOutlinedInput-root": {
                                                    mt: "0px",
                                                    border: "1px solid",
                                                    borderColor: errors.appointmentService ? "error.main" : "#BFD4D4",
                                                },
                                            }}
                                        >
                                            <MenuItem disabled>
                                                {__("Select Service", "bookify")}
                                            </MenuItem>
                                            {allservices.map((value) => (
                                                <MenuItem key={value.id} value={value.id}>
                                                    {value.service_name}
                                                </MenuItem>
                                            ))}
                                        </Select>
                                    </FormControl>
                                </Grid>
                                <Grid item>
                                    <FormControl fullWidth>
                                        <Typography variant="wpbkThemeLabel" component="label" htmlFor="appointment-staffs">
                                            {__("Staffs ", "bookify")}
                                            <span style={{color:"#A61616"}}>*</span>
                                        </Typography>
                                        <Select
                                            id="appointment-staffs"
                                            name="appointmentStaff"
                                            required
                                            error={errors.appointmentStaff}
                                            value={formData.appointmentStaff}
                                            onChange={(event) => this.handleStaffChange(event, false)}
                                            sx={{
                                                height: "45px",
                                                "& fieldset": {
                                                    border: "none",
                                                },
                                                "&.MuiOutlinedInput-root": {
                                                    mt: "0px",
                                                    border: "1px solid",
                                                    borderColor: errors.appointmentStaff ? "error.main" : "#BFD4D4",
                                                },
                                            }}
                                        >
                                            <MenuItem disabled>
                                                {__("Select Staff", "bookify")}
                                            </MenuItem>
                                            {staffs.map((value) => (
                                                <MenuItem key={value.staff_id} value={value.staff_id}>
                                                    {value.staff_name}
                                                </MenuItem>
                                            ))}
                                        </Select>
                                    </FormControl>
                                </Grid>
                                <Grid item>
                                    <FormControl fullWidth>
                                        <Typography variant="wpbkThemeLabel" component="label" htmlFor="appointment-date">
                                            {__("Date ", "bookify")}
                                            <span style={{color:"#A61616"}}>*</span>
                                        </Typography>
                                        <LocalizationProvider dateAdapter={AdapterDayjs}>
                                            <DatePicker
                                                format={dateFormat}
                                                disablePast
                                                name="appointmentDate"
                                                value={formData.appointmentDate}
                                                onChange={(event) => this.handleDateChange(event, false)}
                                                shouldDisableDate={this.shouldDisableDate}
                                                maxDate={maxDate}
                                                slotProps={{
                                                    textField: {
                                                        id: "appointment-date",
                                                        variant: "outlined",
                                                        required: true,
                                                        error: errors.appointmentDate,
                                                        sx: {
                                                            borderRadius: "5px",
                                                            justifyContent: "center",
                                                            "& fieldset": {
                                                                border: "none",
                                                            },
                                                            "& .MuiOutlinedInput-root": {
                                                                mt: "0px",
                                                                height: "43px",
                                                                border: "1px solid",
                                                                borderColor: errors.appointmentDate ? "error.main" : "#BFD4D4",
                                                            },
                                                            "& .MuiInputBase-input": {
                                                                padding: "0px 14px"
                                                            }
                                                        }
                                                    },
                                                }}
                                            />
                                        </LocalizationProvider>
                                    </FormControl>
                                </Grid>
                                <Grid item>
                                    { ProMultipleBooking && staffMultipleBooking ? (
                                        <FormControl fullWidth>
                                            <Typography variant="wpbkThemeLabel" component="label" htmlFor="appointment-duration">
                                                {__("Duration ", "bookify")}
                                                <span style={{color:"#A61616"}}>*</span>
                                            </Typography>
                                            <Select
                                                id="appointment-duration"
                                                name="appointmentDuration"
                                                required
                                                error={errors.appointmentDuration}
                                                multiple
                                                value={formData.appointmentDuration}
                                                onChange={this.handleInputChange}
                                                renderValue={(selected) => (
                                                    <Box sx={{display:"flex",flexWrap:"wrap", gap:0.5}}>
                                                        {selected.map((value) => (
                                                            <Chip key={value} label={value} />
                                                        ))}
                                                    </Box>
                                                )}
                                                sx={{
                                                    minHeight: "45px",
                                                    "& fieldset": {
                                                        border: "none",
                                                    },
                                                    "& .MuiChip-root": {
                                                        height: "23px",
                                                    },
                                                    "& .MuiChip-label": {
                                                        fontSize: "0.799rem",
                                                    },
                                                    "& .MuiOutlinedInput-input": {
                                                        padding: "10px 14px",
                                                    },
                                                    "&.MuiOutlinedInput-root": {
                                                        mt: "0px",
                                                        border: "1px solid",
                                                        borderColor: errors.appointmentDuration ? "error.main" : "#BFD4D4",
                                                    },
                                                }}
                                            >
                                                {slots.map((value) => (
                                                    <MenuItem key={value} value={value}>
                                                        {value}
                                                    </MenuItem>
                                                ))}
                                            </Select>
                                        </FormControl>
                                    ) : (
                                        <FormControl fullWidth>
                                            <Typography variant="wpbkThemeLabel" component="label" htmlFor="appointment-duration">
                                                {__("Duration ", "bookify")}
                                                <span style={{color:"#A61616"}}>*</span>
                                            </Typography>
                                            <Select
                                                id="appointment-duration"
                                                name="appointmentDuration"
                                                required
                                                error={errors.appointmentDuration}
                                                value={formData.appointmentDuration.length > 0 ? formData.appointmentDuration : ""}
                                                onChange={this.handleInputChange}
                                                sx={{
                                                    height: "45px",
                                                    "& fieldset": {
                                                        border: "none",
                                                    },
                                                    "& .MuiChip-root": {
                                                        height: "23px",
                                                    },
                                                    "& .MuiChip-label": {
                                                        fontSize: "0.799rem",
                                                    },
                                                    "&.MuiOutlinedInput-root": {
                                                        mt: "0px",
                                                        border: "1px solid",
                                                        borderColor: errors.appointmentDuration ? "error.main" : "#BFD4D4",
                                                    },
                                                }}
                                            >
                                                <MenuItem disabled>
                                                    {__("Select Duration", "bookify")}
                                                </MenuItem>
                                                {slots.map((value) => (
                                                    <MenuItem key={value} value={value}>
                                                        {value}
                                                    </MenuItem>
                                                ))}
                                            </Select>
                                        </FormControl>
                                    )}
                                </Grid>
                                <Grid item>
                                    <FormControl fullWidth>
                                        <Typography variant="wpbkThemeLabel" component="label" htmlFor="appointment-customer">
                                            {__("Customers ", "bookify")}
                                            <span style={{color:"#A61616"}}>*</span>
                                        </Typography>
                                        <Select
                                            id="appointment-customer"
                                            name="appointmentCustomer"
                                            required
                                            error={errors.appointmentCustomer}
                                            value={formData.appointmentCustomer}
                                            onChange={this.handleInputChange}
                                            sx={{
                                                height: "45px",
                                                "& fieldset": {
                                                    border: "none",
                                                },
                                                "&.MuiOutlinedInput-root": {
                                                    mt: "0px",
                                                    border: "1px solid",
                                                    borderColor: errors.appointmentCustomer ? "error.main" : "#BFD4D4",
                                                    
                                                },
                                            }}
                                        >
                                            <MenuItem disabled>
                                                {__("Select Customer", "bookify")}
                                            </MenuItem>
                                            {customers.map((value) => (
                                                <MenuItem key={value.id} value={value.id}>
                                                    {value.customer_name}
                                                </MenuItem>
                                            ))}
                                        </Select>
                                    </FormControl>
                                </Grid>
                                <Grid item>
                                    <FormControl fullWidth>
                                        <Typography variant="wpbkThemeLabel" component="label" htmlFor="appointment-status">
                                            {__("Status ", "bookify")}
                                            <span style={{color:"#A61616"}}>*</span>
                                        </Typography>
                                        <Select
                                            id="appointment-status"
                                            name="appointmentStatus"
                                            required
                                            error={errors.appointmentStatus}
                                            value={formData.appointmentStatus}
                                            onChange={this.handleInputChange}
                                            sx={{
                                                height: "45px",
                                                "& fieldset": {
                                                    border: "none",
                                                },
                                                "&.MuiOutlinedInput-root": {
                                                    mt: "0px",
                                                    border: "1px solid",
                                                    borderColor: errors.appointmentStatus ? "error.main" : "#BFD4D4",
                                                },
                                            }}
                                        >
                                            {statuses.map((value) => (
                                                <MenuItem key={value} value={value}>
                                                    {value}
                                                </MenuItem>
                                            ))}
                                        </Select>
                                    </FormControl>
                                </Grid>
                                <Grid item>
                                    <FormControl fullWidth>
                                        <Typography variant="wpbkThemeLabel" component="label" htmlFor="appointment-note">
                                            {__("Note", "bookify")}
                                        </Typography>
                                        <TextField
                                            id="appointment-note"
                                            name="appointmentNote"
                                            value={formData.appointmentNote}
                                            onChange={this.handleInputChange}
                                            multiline
                                            rows={4}
                                            sx={{
                                                border: "1px solid #BFD4D4",
                                                borderRadius: "4px",
                                                "& fieldset": {
                                                    border: "none",
                                                },
                                            }}
                                        />
                                    </FormControl>
                                </Grid>
                            </Grid>
                        </Box>
                    )}
                </ThemeProvider>
            </>
        )
    }

}

export default AppointmentFields;