// material-ui
import {
    Box, Button,
    Grid, Typography
} from '@mui/material';
import ApplicationForm from "./ApplicationForm";
import {useContext, useEffect, useState} from "react";
import * as React from "react";
import axios from "axios";
import {apiPath} from "../../auth/utils";
import {
    GET_APPLICATION_AWARD_PATH,
    GET_APPLICATION_FILE_PATH,
    GET_APPLICATION_PATH,
    GET_APPLICATION_STORAGE_SIZE,
    GET_APPLICATION_VIDEO_EXIST, GET_EVENT_COMBO_PATH,
    GET_EVENT_PATH,
    GET_SUB_DIVISION_COMBO_LIST,
    GET_THUMBNAIL_PATH,
    POST_APPLICATION_PATH
} from "../../utils/ApiPathConst";
import LoadingComponent from "../extra-pages/LoadingComponent";
import {
    GeneralComboWindow,
    GeneralConfirmWindow,
    getObjectById, isUserDivisionIdInList, notifyDeleteError,
    notifyDeleteSuccess, notifyNoPermission,
    notifySaveSuccess
} from "../../utils/CommonFunction";
import FileRefCard from "./FileRefCard";
import {LIONER_BUTTON_THEME, LIONER_LONG_BUTTON_THEME} from "../../themes/colorConst";
import {useNavigate, useParams} from "react-router-dom";
import {ThemeProvider} from "@emotion/react";
import UploadContext from "../../components/UploadProvider";
import MainCard from "../../components/MainCard";
import AwardTable from "./AwardTable";
import AbilityContext from "../../components/AbilityProvider";

import {isObjEmpty} from "../../utils/Utils";
import {LIONER_FORM_THEME, CARD_MAX_WIDTH} from "../../themes/themeConst";
import {useLocation} from "react-router";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const ApplicationPanel = () => {
    const params = useParams();
    const navigate = useNavigate()
    const { setIsUploading } = useContext(UploadContext);
    const ability = useContext(AbilityContext);
    const location = useLocation();
    const queryParams = new URLSearchParams(location.search);
    const refId = queryParams.get("refId");

    const [userEventComboList, setUserEventComboList] = useState([]);
    const [selectedEvenet, setSelectedEvent] = useState(null);
    const [isCopyWindowOpen, setIsCopyWindowOpen] = React.useState(false);
    const handleCopyClose = () => {
        setIsCopyWindowOpen(false);
    };

    function updateCopyData(){
        setIsCopyWindowOpen(false);
        navigate(`/application/maintain/-1/${selectedEvenet.id}?refId=${params.id}`);
    }

    const createNewApplication = () => {
        setIsCopyWindowOpen(true);
    };

    const [onReady, setOnReady] = useState(false);
    const [isCollectData, setIsCollectData] = useState(false);
    const [userConfirm, setUserConfirm] = useState(false);
    const [isNewRecord, setIsNewRecord] = useState(false);
    const [applicationDetail, setApplicationDetail] = useState({});
    const [subDivisionCombo, setSubDivisionCombo] = useState([]);
    const [refFileList, setRefFileList] = useState([]);
    const [refTagList, setRefTagList] = useState([]);
    const [refSubDivisionList, setRefSubDivisionList] = useState([]);
    const [thumbnailList, setThumbnailList] = useState([]);
    const [eventDetail, setEventDetail] = useState({});
    const [awardList, setAwardList ] = useState([]);
    const [isEditing, setIsEditing] = useState(false);
    const [usedFileSize, setUsedFileSize ] = useState(0);
    const [videoCount, setVideoCount ] = useState(0);
    const [responseError, setResponseError] = useState({});
    const [eventName, setEventName] = useState("");
    //const [tagCombo, setTagCombo] = useState({});

// ==============================|| DELETE WINDOW RELATED ||============================== //
    const [isWindowOpen, setIsWindowOpen] = React.useState(false);

    const handleClose = () => {
        setIsWindowOpen(false);
    };

    const handleDeleteClick = () => {
        setIsWindowOpen(true);
    };

    const createNewAward = () =>{
        navigate(`/award/maintain/-1/${applicationDetail.eventId}/${applicationDetail.id}`);
    }
    function updateData(){
        if(awardList.length > 0 || refFileList.length > 0){
            notifyDeleteError("Delete restricted. Attachment exists in this application.")
            setIsWindowOpen(false);
        }
        else{
            axios.delete(`${apiPath}${GET_APPLICATION_PATH}/${params.id}`,
            )
                .then((response) => {
                    if (response.status === 204) {
                        notifyDeleteSuccess();
                        setIsWindowOpen(false);
                        returnSearchPage();
                    }
                })
                .catch(error => {
                    console.log(error);
                    return false;
                });
        }
    }
// ==============================|| DELETE WINDOW RELATED ||============================== //

    function updateApplicationDetail(applicationData) {
        setApplicationDetail(applicationData);
    }

    function getUserEventCombo(){
        axios.get(`${apiPath}${GET_EVENT_COMBO_PATH}`,{
            params:{
                userSubDivisionId: ability.can('EDIT','ALL_RECORD') ? null : localStorage.getItem('subDivisionId'),
            }
        })
            .then((response) => {
                if (response.status === 200) {
                    setUserEventComboList(response.data.records);
                }
            })
            .catch(error => {
                console.log(error);
                return false;
            });
    }

    useEffect(() => {
        if(refId !== null){
            setIsEditing(true);
            setIsNewRecord(true);
            getApplicationDetail(refId);
            getEventDetail();
        }
        else if(params.id<0){
            if(!ability.can('EDIT','APPLICATION')){
                notifyNoPermission();
                navigate('/');
            }
            setIsEditing(true);
            setIsNewRecord(true);
            getEventDetail();
        }
        else{
            getApplicationDetail(params.id);
            getAwardList();
        }
        getGroupList();
        getFileList();
        getUserEventCombo();
    }, []);

    useEffect(() => {
        if (Object.keys(subDivisionCombo).length > 0
            && subDivisionCombo !== undefined
            && !isObjEmpty(applicationDetail)
            && (!isObjEmpty(thumbnailList) || refFileList.length === 0)
        ) {
            setOnReady(true);
        }
        else if(isNewRecord && Object.keys(eventDetail).length > 0){
            setOnReady(true);
        }
    }, [subDivisionCombo,applicationDetail, eventDetail, thumbnailList, refFileList]);

    function reloadData(){
        getApplicationDetail(params.id);
        getGroupList();
        getFileList();
    }

    function reloadList(){
        getFileList();
    }

    function returnSearchPage(){
        navigate('/application');
    }

    const submitData = () => {
        setUserConfirm(true);
        setIsCollectData(!isCollectData);
    }

    const updateIsEdit = () => {
        setIsEditing(!isEditing);
    }

    useEffect(() => {
        if (userConfirm && onReady) {
            postApplication();
        }
        setUserConfirm(false);
    }, [applicationDetail]);

    function postApplication(){
        setIsUploading(true);
        axios.post(`${apiPath}${POST_APPLICATION_PATH}`,
            applicationDetail,
            {
                headers: {
                    'Content-Type': 'multipart/form-data',
                }
            }
        )
            .then((response) => {
                if (response.status === 200) {
                    notifySaveSuccess();
                    setIsEditing(false);
                    if(isNewRecord){
                        setIsUploading(false);
                        navigate('/application')
                    }
                    else{
                        setIsUploading(false);
                        reloadData();
                    }
                    setIsCollectData(!isCollectData);

                }
            })
            .catch(error => {
                if (error.response.status === 422){
                    const formErrors = {};
                    formErrors.subDivision = error.response.data.error;
                    setIsUploading(false);
                    setUserConfirm(false);
                    setIsCollectData(false);
                    setResponseError(formErrors);
                }
                else{
                    setIsUploading(false);
                    setUserConfirm(false);
                    setIsCollectData(false);
                    notifyDeleteError("Server busy, please try again later.");
                }
                console.log(error);
                return false;
            });
    }

    function getEventDetail() {
        axios.get(`${apiPath}${GET_EVENT_PATH}/${params.eventId}`,
        )
            .then((response) => {
                if (response.status === 200) {
                    setEventDetail(response.data.data);
                }
            })
            .catch(error => {
                console.log(error);
                return false;
            });
    }

    function getGroupList() {
        axios.get(`${apiPath}${GET_SUB_DIVISION_COMBO_LIST}`,
        )
            .then((response) => {
                if (response.status === 200) {
                    setSubDivisionCombo(response.data.records);
                }
            })
            .catch(error => {
                console.log(error);
                return false;
            });
    }

    function getAwardList() {
        const byDivision = {
            applicationId: params.id,
            userSubDivisionId: ability.can('VIEW', 'ALL_RECORD') ? null : localStorage.getItem('subDivisionId'),
        }
        axios.get(`${apiPath}${GET_APPLICATION_AWARD_PATH}`,
            {
                params: byDivision,
            }
        )
            .then((response) => {
                if (response.status === 200) {
                    setAwardList(response.data.records);
                }
            })
            .catch(error => {
                console.log(error);
                return false;
            });
    }

    function getFileList() {
        axios.get(`${apiPath}${GET_APPLICATION_FILE_PATH}/${params.id}`,
        )
            .then((response) => {
                if (response.status === 200) {
                    setRefFileList(response.data.records);
                    if(response.data.records.length >0){
                        setThumbnailList([]);
                        setOnReady(false);
                    }
                }
            })
            .catch(error => {
                console.log(error);
                return false;
            });
    }

    function getApplicationDetail(applicationId){
        axios.get(`${apiPath}${GET_APPLICATION_PATH}/${applicationId}`,
        )
            .then((response) => {
                if (response.status === 200) {
                    setApplicationDetail(response.data.data);
                    setEventName(response.data.data.eventName)
                    setRefTagList(response.data.tagList);
                    setRefSubDivisionList(response.data.subDivisionList);
                }
            })
            .catch(error => {
                console.log(error);
                return false;
            });
    }

    useEffect(() => {
        const tempList = [];
        if (refFileList.length > 0) {
            // for(let i=0 ; i < refFileList.length ; i++){
            //     axios.get(`${apiPath}${GET_THUMBNAIL_PATH}/${refFileList[i].id}/${refFileList[i].skey}/${refFileList[i].filename}`,
            //         { responseType: 'blob' })
            //         .then((response) => {
            //             if (response.status === 200) {
            //                 const tempURL = URL.createObjectURL(new Blob([response.data],{type: refFileList[i].mimetype}));
            //                 if(getObjectById(thumbnailList,refFileList[i].filename) === null){
            //                     tempList.push({
            //                         "id": refFileList[i].id,
            //                         "fileId": refFileList[i].id,
            //                         "skey": refFileList[i].skey,
            //                         "mimetype": refFileList[i].mimetype.split('/')[0],
            //                         "key": refFileList[i].filename,
            //                         "remarks": refFileList[i].remarks,
            //                         "src": tempURL,
            //                         "fileSize": response.data.size,
            //                     });
            //                     setThumbnailList([...tempList]);
            //                 }
            //             }
            //         })
            //         .catch(error => {
            //             console.log(error);
            //             return false;
            //         });
            // }
            const promises = refFileList.reduce((accumulator, refFile) => {
                const promise = axios
                  .get(`${apiPath}${GET_THUMBNAIL_PATH}/${refFile.id}/${refFile.skey}/${refFile.filename}`, { responseType: 'blob' })
                  .then((response) => {
                    if (response.status === 200) {
                      const tempURL = URL.createObjectURL(new Blob([response.data], { type: refFile.mimetype }));
                      if (getObjectById(thumbnailList, refFile.filename) === null) {
                        const thumbnail = {
                          id: refFile.id,
                          fileId: refFile.id,
                          skey: refFile.skey,
                          key: refFile.filename + refFile.id,
                          filename: refFile.filename,
                          mimetype: refFile.mimetype.split('/')[0],
                          remarks: refFile.remarks,
                          src: tempURL,
                          fileSize: response.data.size
                        };
                        return thumbnail;
                      }
                    }
                  })
                  .catch((error) => {
                    console.log(error);
                    // create a empty thumbnail object instead of block the form load
                    const thumbnail = {
                      id: refFile.id,
                      fileId: refFile.id,
                      skey: refFile.skey,
                      key: refFile.filename + refFile.id,
                      filename: refFile.filename,
                      mimetype: refFile.mimetype.split('/')[0],
                      remarks: refFile.remarks,
                      fileSize: 0
                    };
                    return thumbnail;
                  });
        
                accumulator.push(promise);
                return accumulator;
              }, []);
        
              Promise.all(promises)
                .then((thumbnails) => {
                  const filteredThumbnails = thumbnails.filter((thumbnail) => thumbnail !== false);
                  const arrCopy = Array.from(filteredThumbnails);
                  arrCopy.sort((a, b) => a.key.localeCompare(b.key));
                  setThumbnailList([...arrCopy]);
                })
                .catch((error) => {
                  console.log(error);
                });
        } 
        else {
            setThumbnailList(tempList);
        }

        axios.get(`${apiPath}${GET_APPLICATION_STORAGE_SIZE}/${params.id}`)
            .then((response) => {
                if (response.status === 200) {
                    setUsedFileSize(response.data.size);
                }
            })
            .catch(error => {
                console.log(error);
                return false;
            });

        axios.get(`${apiPath}${GET_APPLICATION_VIDEO_EXIST}/${params.id}`)
            .then((response) => {
                if (response.status === 200) {
                    setVideoCount(response.data.count);
                }
            })
            .catch(error => {
                console.log(error);
                return false;
            });

        setThumbnailList([...tempList]);
    }, [refFileList]);

    return (
        !onReady ?
            <LoadingComponent/>
            :
            <Grid container rowSpacing={3} columnSpacing={2.75}>
                <ThemeProvider theme={LIONER_FORM_THEME}>
                <Grid item xs={12} md={12} lg={12}>
                    <Grid container justifyContent="flex-start" alignItems="center">
                        <Grid item xs={3} sx={{mt:-1, mb: -2.25}} >
                            <Box sx={{ display: 'flex', alignItems: 'center'}}>
                                <Typography align="center" variant="h5" >{isNewRecord? "New Application" : "Maintain Application"}</Typography>
                            </Box>
                        </Grid>
                    </Grid>
                </Grid>

                {/*row 1*/}
                <Grid item xs={12} md={12} lg={12}>
                    <ApplicationForm
                        eventName={eventName}
                        eventDetail={eventDetail}
                        applicationDetail={applicationDetail}
                        updateApplicationDetail={updateApplicationDetail}
                        setUserConfirm={setUserConfirm}
                        setIsCollectData={setIsCollectData}
                        isCollectData={isCollectData}
                        isNewRecord={isNewRecord}
                        refTagList={refTagList}
                        refSubDivisionList={refSubDivisionList}
                        isEditing={isEditing}
                        usedFileSize={usedFileSize}
                        videoCount={videoCount}
                        responseError={responseError}
                        canEdit={ability.can('EDIT','ALL_RECORD') ? false : !(ability.can('EDIT','APPLICATION') && isUserDivisionIdInList(localStorage.getItem('subDivisionId'),refSubDivisionList))}
                    />
                </Grid>

                {/*row 2*/}
                {
                    (isEditing ) ?
                <Grid container maxWidth justifyContent="space-between" sx={{width:CARD_MAX_WIDTH}} >
                    <ThemeProvider theme={LIONER_BUTTON_THEME}>
                        <Grid item>
                            <Grid container>
                                <Grid item sx={{ml:3, mr:1.5, mb:1}}>
                                    <Button
                                        variant="contained"
                                        type="submit"
                                        color="save"
                                        onClick={submitData}
                                    >
                                        Save
                                    </Button>
                                </Grid>
                                <Grid item sx={{ml:1.5, mr:1.5, mb:1}}>
                                    <Button
                                        variant="contained"
                                        type="submit"
                                        color="cancel"
                                        onClick={returnSearchPage}
                                    >
                                        Cancel
                                    </Button>

                                </Grid>
                                <Grid item sx={{ml:{xs:1.5,md:1.5,lg:1.5}, mr:3}}>
                                    <Button
                                        variant="contained"
                                        type="submit"
                                        color="delete"
                                        onClick={handleDeleteClick}
                                        disabled={isNewRecord || !ability.can('DELETE','APPLICATION')}
                                    >
                                        Delete
                                    </Button>
                                    <GeneralConfirmWindow
                                        isWindowOpen={isWindowOpen}
                                        title={"Attention"}
                                        //content={`Confirm to delete Application "${applicationDetail.name}" ?`}
                                        content={`Are you sure to delete this application?`}
                                        onNormalClose={handleClose}
                                        onConfirmClose={updateData}
                                    />
                                </Grid>
                            </Grid>
                        </Grid>
                        <Grid item>
                            <Grid container>
                                {
                                    ability.can('EDIT','AWARD')?
                                        <Grid container>
                                            <ThemeProvider theme={LIONER_LONG_BUTTON_THEME}>

                                                <Grid item sx={{ml:{xs:1.5,md:1.5,lg:3}, mb:1}}>
                                                    <Button
                                                        variant="contained"
                                                        color="saveAs"
                                                        onClick={createNewApplication}
                                                        disabled={isNewRecord}
                                                    >
                                                        Copy as new
                                                    </Button>
                                                    <GeneralComboWindow
                                                        isWindowOpen={isCopyWindowOpen}
                                                        title={"New Application"}
                                                        content={"Event"}
                                                        comboList={userEventComboList}
                                                        setValueCallback={setSelectedEvent}
                                                        onNormalClose={handleCopyClose}
                                                        onConfirmClose={updateCopyData}
                                                    />
                                                </Grid>

                                                <Grid item sx={{ml:3, mr:3, mt:{xs:2, md:0}}}>
                                                    <ThemeProvider theme={LIONER_LONG_BUTTON_THEME}>
                                                        <Button
                                                            variant="contained"
                                                            type="submit"
                                                            color="create"
                                                            onClick={createNewAward}
                                                            disabled={isNewRecord || !ability.can('EDIT','AWARD')}
                                                        >
                                                            New Award
                                                        </Button>
                                                    </ThemeProvider>
                                                </Grid>


                                            </ThemeProvider>
                                        </Grid>
                                        :
                                        <Grid/>
                                }
                            </Grid>
                        </Grid>
                    </ThemeProvider>
                </Grid>
                        :
                        <Grid container maxWidth justifyContent="space-between" sx={{ml:2, mr:2}}>
                            <ThemeProvider theme={LIONER_BUTTON_THEME}>
                                <Grid item>
                                    <Grid container>
                                        <Grid item sx={{ml:1, mr:3, mb:1, mt:2}}>
                                            <Button
                                                variant="contained"
                                                color="save"
                                                onClick={updateIsEdit}
                                                disabled={ability.can('EDIT','ALL_RECORD') ? false : !(ability.can('EDIT','APPLICATION') && isUserDivisionIdInList(localStorage.getItem('subDivisionId'),refSubDivisionList))}
                                            >
                                                Edit
                                            </Button>
                                        </Grid>
                                    </Grid>
                                </Grid>
                                <Grid item>
                                </Grid>
                            </ThemeProvider>
                        </Grid>
                }

                {/*row 3*/}
                {
                    params.id > 0 ?
                        <Grid sx={{mt:-2}} item xs={12} md={12} lg={12}>
                            <FileRefCard
                                thumbnailList={thumbnailList}
                                applicationId={params.id}
                                reloadList={reloadList}
                                canEdit={ability.can('EDIT','ALL_RECORD') ? false : !(ability.can('EDIT','APPLICATION') && isUserDivisionIdInList(localStorage.getItem('subDivisionId'),refSubDivisionList))}
                            />
                            {/*<FilePreviewGrid fileList={thumbnailList}/>*/}
                        </Grid>
                        :
                        <Grid/>
                }


                {/* row 4 */}
                {
                    params.id > 0 ?
                        <Grid item xs={12} md={12} lg={12}>
                            <MainCard sx={{width:CARD_MAX_WIDTH}}>
                                <AwardTable recordList={awardList}/>
                            </MainCard>
                        </Grid>
                        :
                        undefined
                }
                </ThemeProvider>
            </Grid>
    );
};

export default ApplicationPanel;
