import React, { Fragment, useState, useEffect, useLayoutEffect, useContext } from 'react';
import session from '~/Utils/session';
import fetchGet, { fetchPost, fetchDelete } from '~/Utils/fetch';
import { useToast, confirm } from '~/Components/UIControls/Message';
import Form from '~/Components/Form';
import { useForm } from 'react-hook-form';
import BottomTabBarLayout from '~/Components/Layouts/BottomTabBarLayout';
import { usePopup } from '~/Components/UIControls/Popup';
import { useAuth } from '~/Components/Hooks';
import { Util } from '~/Utils/utils';
import Theme from '~/Themes';
import { Tab, TabHeader, TabTitleGroup, TabTitle, TabContent, TabItem } from '~/Components/UIControls/Tab';
import { DateTimePicker } from '~/Components/UIControls/DateTimePicker';
import BasicInfoForm from './SubPages/BasicInfoForm';
import WorkCount from './SubPages/WorkCount';
import WorkList from './SubPages/WorkList';
import { View } from 'react-native';
import ReleaseList from './SubPages/ReleaseList';
import AccidentList from './SubPages/AccidentList';
import ComplaintList from './SubPages/ComplaintList';
import AlarmLogList from './SubPages/AlarmLogList';
import { isTrue } from '~/Components/UIControls/Common';

const SummaryNames = {
    "100": "전력 합계(kwh)",
    "101": "가스 합계(m3)",
    "102": "상수도 합계(m3)",
    "104": "등유 합계(kg)",
    "105": "LPG 합계(L)",
    "106": "중온수 합계(gcal)",
}

const Screen = ({navigation}) => {
    const action = navigation.getParam('action', Form.VIEW);
    const editable = navigation.getParam('editable', action == Form.VIEW ? false : true);
    const setEditable = (value) => { navigation.setParams({editable: value}) };
    const refreshList = navigation.getParam('refreshList', ()=>{});
    const siteId = navigation.getParam('siteId', 0);
    const addDate = navigation.getParam('addDate', new Date());
    const setAddDate = (value) => { navigation.setParams({addDate: value}) };
    const businessFieldId = navigation.getParam('businessFieldId', 0);
    const tab = navigation.getParam('tab', 'basic-info-form');
    const { auth, userinfo } = useAuth(navigation);
    const { showMessage } = useToast();

    const [loading, setLoading] = useState(false);
    const [data, setData] = useState({});

    console.log(`====== userinfo : `, userinfo);
    console.log(`====== render, action(${action}), editable(${isTrue(editable)}), addDate(${addDate}), HumanResourceTotal(${Util.get(data, "DataObject.HumanResourceTotal")}) =========`);

    // mount
    useEffect(() => {
        fetch(false);
    }, [addDate]);

    // react hook form initialize
    const { register, unregister, setValue, handleSubmit, errors, getValues } = useForm();
    useLayoutEffect(() => {
        /* useFormFunctions 에서 useContext 사용 Provider 의 변경사항 구독하여 갱신시 다시 regist 후 data 를 setValue 처리 */
        //useFormFunctions(register, setValue, data);
        Form.setUseFormFunctions(register, setValue);
    }, [register]);

    // popup
    const { openPopup } = usePopup();

    const setDataFromJson = (result) => {
        const newData = {
            ...result,
            DataObject: JSON.parse(result.Datas)
        };
        setData(newData);
        return newData;
    };

    const generateEnergy = (energy, includeList=true, includeTotal=true) => {
        let list = [];
        let total = null;
        const first = energy.List.length > 0 ? energy.List[0] : null;

        const generateEnergyItem = (item) => {
            return {
                FacilityCode: Util.get(item, "Parameter.ParameterFacilityCode"),
                PropertyId: Util.get(item, "Parameter.ParameterPropertyId"),
                Name: Util.get(item, "MonitoringPoint.Name"),
                Today: Util.get(item, "MonitoringPoint.Today"),
                DayBefore: Util.get(item, "MonitoringPoint.DayBefore"),
                DailyUsage: Util.get(item, "MonitoringPoint.DailyUsage"),
                MonthUsage: Util.get(item, "MonitoringPoint.MonthUsage"),
            }
        }
        const generateEnergyTotal = (list, name) => {
            var result = {
                Name: name,
                Today: 0,       // 당일 검침값 합계(?) - 검침값인데 합하는게 의미가 있을까?
                DayBefore: 0,   // 전일 검침값 합계(?) - 검침값인데 합하는게 의미가 있을까?
                DailyUsage: 0,  // 당일 사용량 합계
                MonthUsage: 0,  // 당월 사용량 합계
            };

            for(var item of list) {
                result.Today += Util.get(item, "MonitoringPoint.Today");
                result.DayBefore += Util.get(item, "MonitoringPoint.DayBefore");
                result.DailyUsage += Util.get(item, "MonitoringPoint.DailyUsage");
                result.MonthUsage += Util.get(item, "MonitoringPoint.MonthUsage");
            }

            result.Today = Math.round(result.Today * 100.0) / 100.0;
            result.DayBefore = Math.round(result.DayBefore * 100.0) / 100.0;
            result.DailyUsage = Math.round(result.DailyUsage * 100.0) / 100.0;
            result.MonthUsage = Math.round(result.MonthUsage * 100.0) / 100.0;

            return result;
        }

        if(includeList && energy.List.length > 1) {
            for(var item of energy.List) {
                list.push(generateEnergyItem(item));
            }
        }

        if(includeTotal && first) {
            total = generateEnergyTotal(energy.List, SummaryNames[energy.FacilityTypeId]);
        }

        return {
            FacilityTypeId: energy.FacilityTypeId,
            FacilityTypeName: energy.FacilityTypeName,
            List: list,
            Total: total,
        };
    };

    const generateEnergies = (energies) => {
        var list = [];

        var energy100 = energies.find(v => v.FacilityTypeId == 100);
        if(energy100) list.push(generateEnergy(energy100, true, true));

        var energy101 = energies.find(v => v.FacilityTypeId == 101);
        if(energy101) list.push(generateEnergy(energy101, true, true));

        var energy102 = energies.find(v => v.FacilityTypeId == 102);
        if(energy102) list.push(generateEnergy(energy102, true, true));

        var energy104 = energies.find(v => v.FacilityTypeId == 104);
        if(energy104) list.push(generateEnergy(energy104, true, true));

        var energy105 = energies.find(v => v.FacilityTypeId == 105);
        if(energy105) list.push(generateEnergy(energy105, true, true));

        var energy106 = energies.find(v => v.FacilityTypeId == 106);
        if(energy106) list.push(generateEnergy(energy106, true, true));

        return list;
    }

    const generateMaterials = (materials) => {
        return [];
    }

    const generateJsonFromBasicInfo = (result) => {
        return {
            "Weather": result.Weather,

            "HumanResourceTotal": "",                           /* 총원 */
            "HumanResourceVacancy": "",                         /* 결원 */
            "HumanResourceVacancyName": "",                     /* 결원자명 */
            "HumanResourceOff": "",                             /* 비번 */ 
            "HumanResourceOffName": "",                         /* 비번자명 */ 
            "HumanResourceVacation": "",                        /* 휴가 */
            "HumanResourceVacationName": "",                    /* 휴가자명 */
            "HumanResourceClosed": "",                          /* 휴무 */
            "HumanResourceClosedName": "",                      /* 휴무자명 */
            "HumanResourceTrain": "",                           /* 교육 */
            "HumanResourceTrainName": "",                       /* 교육자명 */
            "HumanResourceOut": "",                             /* 출장 */
            "HumanResourceOutName": "",                         /* 출장자명 */
            "HumanResourceEtc": "",                             /* 당직 */
            "HumanResourceEtcName": "",                         /* 당직자명 */
            "HumanResourceCurrent": "",                         /* 현원 */
                            
            "Humans": [],                                       /* 인원목록(string array) */

            "Energies": generateEnergies(result.Energies),      /* 에너지목록 */

            "WorkStatus": result.WorkStatus,                    /* 작업현황 */

            "WorkCounts": result.WorkCounts,                    /* 업무분야별 작업건수 */

            "Works": result.Works,                              /* 작업내역 */

            "Materials": result.Materials,                      /* 자재사용내역 */

            "Accidents": result.Accidents,

            "Complaints": result.Complaints,

            "Alarms": result.Alarms
        };
    };

    const setDataFromGenerateJson = (result) => {
        const json = generateJsonFromBasicInfo(result);

        const newData = {
            Name: `[${Util.formatDate(addDate, 'yyyy-MM-dd w')}] 일간 보고서`,
            Contents: '',
            DataObject: json,
            Datas: JSON.stringify(json),
        };

        setData(newData);

        return newData;
    };

    const isApproved = (data) => {
        if(data.ApproverUserId) return true;
        else return false;
    }

    const isEnableApprove = (data) => {
        if(action == Form.CREATE) return false;
        if(!!data.ApproverUserId) return false;
        return true;
        /*
        if(data.ApproverUserId != userinfo.UserId
            && data.ApproverUserId2 != userinfo.UserId
            && data.ApproverUserId3 != userinfo.UserId
            && data.ApproverUserId4 != userinfo.UserId
            && data.ApproverUserId5 != userinfo.UserId) {
            return true;
        } else {
            return false;
        }
        */
    }
    
    // search
    const fetch = async (editable=false) => {
        
        setLoading(true);
        await session.load();

        if(action != Form.CREATE) {
            try {
                const result = await fetchGet(`api/app/DailyReport/Get?siteId=${siteId}&addDate=${addDate}&businessFieldId=${businessFieldId}`);
                const newData = setDataFromJson(result);
                Form.setFormData(newData);
                navigation.setParams({
                    isApproved: isApproved(newData),
                    isEnableApprove: isEnableApprove(newData),
                    editable: {edit:editable},
                });
            } catch(error) {
                showMessage(error.message);
            }
        } else {
            try {
                const result = await fetchGet(`api/app/DailyReport/GetCurrentInfo?siteId=${siteId}&addDate=${addDate}&businessFieldId=${businessFieldId}`);
                const newData = setDataFromGenerateJson(result);
                Form.setFormData(newData);
                navigation.setParams({
                    isApproved: isApproved(newData),
                    isEnableApprove: isEnableApprove(newData),
                    editable: {edit:true},
                });
            } catch(error) {
                showMessage(error.message);
            }
        }
        setLoading(false);
    }

    const onSave = (form) => {
        if(loading) {
            showMessage('처리중입니다. 잠시만기다려 주세요.');
            return;
        }
        console.log('form', form);

        confirm('저장', '저장하시겠습니까?', async () => {
            setLoading(true);
            const submit = {
                ...form,
                SiteId: userinfo.SiteId,
                RegisterUserId: userinfo.UserId,
                AddDate: addDate,
                BusinessFieldId: userinfo.BusinessFieldId,
                Datas: JSON.stringify(form.DataObject),
            };

            console.log('submit', submit);

            try {
                const result = await fetchPost(`api/app/DailyReport/Save?isCreate=${action==Form.CREATE?true:false}`, submit);

                showMessage('저장되었습니다.');
                refreshList();
                if(action == Form.CREATE) {
                    navigation.pop();
                } else {
                    fetch(false);
                }
            } catch(error) {
                showMessage(error.message);
            }
            setLoading(false);
        });
    }

    const onAction = (action) => {
        if(action == 'approve') {
            if(loading) {
                showMessage('처리중입니다. 잠시만기다려 주세요.');
                return;
            }
            confirm('결재', '결재처리 하시겠습니까?', async () => {
                setLoading(true);
                try {
                    const result = await fetchPost(`api/app/DailyReport/Approve?`
                        + `siteId=${userinfo.SiteId}&`
                        + `approverUserId=${userinfo.UserId}&`
                        + `addDate=${addDate}&`
                        + `businessFieldId=${userinfo.BusinessFieldId}`, {});
    
                    showMessage('결재처리 되었습니다.');
                    refreshList();
                    if(action == Form.CREATE) {
                        navigation.pop();
                    } else {
                        fetch(false);
                    }
                } catch(error) {
                    showMessage(error.message);
                }
                setLoading(false);
            });
        }
    }

    unregister('DataObject.Weather');
    unregister('DataObject.WorkStatus');
    unregister('DataObject.WorkCounts');
    register({name: 'DataObject.Weather'}, {});
    register({name: 'DataObject.WorkStatus'}, {});
    register({name: 'DataObject.WorkCounts'}, {});
    setValue('DataObject.Weather', Util.get(data, "DataObject.Weather"));
    setValue('DataObject.WorkStatus', Util.get(data, "DataObject.WorkStatus"));
    setValue('DataObject.WorkCounts', Util.get(data, "DataObject.WorkCounts"));

    return ( 
        <BottomTabBarLayout>
            <Form.Container id="daily-report-form" scrolling={false} style={{
                paddingLeft:0, paddingRight:0,paddingTop:0,paddingBottom:0
            }} onSave={handleSubmit(onSave)} onAction={onAction}>
            <Tab>
                <TabHeader>
                    <TabTitleGroup top={true}>
                        <TabTitle onPress={() => {
                            navigation.setParams({ tab: 'basic-info-form' });
                        }} active={tab=='basic-info-form'?true:false} title="일반정보" />
                        <TabTitle onPress={() => {
                            navigation.setParams({ tab: 'work-count' });
                        }} active={tab=='work-count'?true:false} title="작업현황" />
                        <TabTitle onPress={() => {
                            navigation.setParams({ tab: 'work-list' });
                        }} active={tab=='work-list'?true:false} title="작업내역" />
                    </TabTitleGroup>
                    <TabTitleGroup>
                        <TabTitle onPress={() => {
                            navigation.setParams({ tab: 'release-list' });
                        }} active={tab=='release-list'?true:false} title="자재사용내역" />
                        <TabTitle onPress={() => {
                            navigation.setParams({ tab: 'alarm-log-list' });
                        }} active={tab=='alarm-log-list'?true:false} title="경보" />
                        <TabTitle onPress={() => {
                            navigation.setParams({ tab: 'accident-list' });
                        }} active={tab=='accident-list'?true:false} title="사고" />
                        <TabTitle onPress={() => {
                            navigation.setParams({ tab: 'complaint-list' });
                        }} active={tab=='complaint-list'?true:false} title="민원" />
                    </TabTitleGroup>
                </TabHeader>
                <TabContent>
                    {/* 일반정보(날씨, 인원, 에너지) */}
                    <TabItem active={tab=='basic-info-form'?true:false}>
                        <BasicInfoForm navigation={navigation} 
                            register={register} unregister={unregister} 
                            data={data} setData={setData} 
                            setValue={setValue} errors={errors} />
                    </TabItem>

                    {/* 작업현황 */}
                    <TabItem active={tab=='work-count'?true:false}>
                        <WorkCount navigation={navigation} data={data} setData={setData} setValue={setValue} errors={errors} />
                    </TabItem>

                    {/* 작업내역 */}
                    <TabItem active={tab=='work-list'?true:false}>
                        <WorkList navigation={navigation} data={data} setData={setData} setValue={setValue} errors={errors} />
                    </TabItem>

                    {/* 자재사용내역 */}
                    <TabItem active={tab=='release-list'?true:false}>
                        <ReleaseList navigation={navigation} data={data} setData={setData} setValue={setValue} errors={errors} />
                    </TabItem>

                    {/* 경보 */}
                    <TabItem active={tab=='alarm-log-list'?true:false}>
                        <AlarmLogList navigation={navigation} data={data} setData={setData} setValue={setValue} errors={errors} />
                    </TabItem>

                    {/* 사고 */}
                    <TabItem active={tab=='accident-list'?true:false}>
                        <AccidentList navigation={navigation} data={data} setData={setData} setValue={setValue} errors={errors} />
                    </TabItem>

                    {/* 민원 */}
                    <TabItem active={tab=='complaint-list'?true:false}>
                        <ComplaintList navigation={navigation} data={data} setData={setData} setValue={setValue} errors={errors} />
                    </TabItem>
                </TabContent>
            </Tab>
            </Form.Container>

            {loading && <Form.Loading />}
        </BottomTabBarLayout>
    );
};

const TitleComponent = ({editable, addDate, setAddDate}) => {
    return (
        <DateTimePicker 
            style={{
                width:80, height:31,
                borderWidth:0, flex:-1,
                paddingLeft:0, paddingRight:0,
                backgroundColor: editable ? '#0b83e6' : '#9aa3ac',
            }} 
            labelStyle={{
                fontFamily:Theme.Fonts.Regular, fontSize:14, lineHeight:20,
                textAlign:'center', textAlignVertical:'center', 
                letterSpacing:-1.4, includeFontPadding:false, 
                color:'white',
            }}
            date={addDate} editable={editable} hideDownIcon={true} onChange={(newDate) => {
            setAddDate(Util.toDateString(newDate));
        }} />
    )
}

Screen.navigationOptions = ({navigation}) => { 
    const action = navigation.getParam('action', Form.VIEW);    // create, edit, view
    const editable = navigation.getParam('editable', action == Form.VIEW ? false : true);
    const isApproved = navigation.getParam('isApproved', false);
    const isEnableApprove = navigation.getParam('isEnableApprove', false);
    const { auth } = useAuth(navigation);
    const addDate = navigation.getParam('addDate', new Date());
    const setAddDate = (value) => { navigation.setParams({addDate: value}) };

    return { 
        header: () => (
            <Header 
                navigation={navigation} 
                title={'일간보고서'}
                main={false}
                buttons={
                    <Fragment>
                        <TitleComponent editable={isTrue(editable)} addDate={addDate} setAddDate={setAddDate} />
                        {action != Form.CREATE && auth.Action1 && isEnableApprove && (
                            <Form.ActionButton id="daily-report-form" action="approve" title="결재" navigation={navigation} />
                        )}
                        {!isApproved && (
                            <Fragment>
                                {!isTrue(editable) && (
                                    <Fragment>
                                        {auth.Update && (<Form.EditButton id="daily-report-form" navigation={navigation} type="primary" />)}
                                    </Fragment>
                                )}
                                {isTrue(editable) && (
                                    <Fragment>
                                        {auth.Update && (<Form.SaveButton id="daily-report-form" type="primary" />)}
                                        {action != Form.CREATE && auth.Update && <Form.CancelEditButton id="daily-report-form" navigation={navigation} />}
                                    </Fragment>
                                )}
                            </Fragment>
                        )}
                    </Fragment>
                }
            /> 
        )
    } 
};

export default Screen;