'use client'
import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from "react";
import {Calendar, dayjsLocalizer, Event, SlotInfo, View} from 'react-big-calendar'
// https://day.js.org/docs/zh-CN/get-set/get-set
import dayjs, {Dayjs} from 'dayjs'
import 'react-big-calendar/lib/css/react-big-calendar.css'
import 'react-big-calendar/lib/sass/styles.scss'
import 'react-big-calendar/lib/addons/dragAndDrop/styles.scss'
import '@/ui/task/calendar/index.modules.css'
import {commonUpdate, getTaskTreeResult, OPERATION_BUTTON_TYPE} from "@/lib/task/project/data";
import {useSearchParams} from "next/dist/client/components/navigation";
import {DetailModelForm} from "@/ui/task/project/DetailModelForm";
import {SearchObject} from "@/lib/definitions";
import LocalContext from "@/ui/LocalContent";
import withDragAndDrop, {EventInteractionArgs} from "react-big-calendar/lib/addons/dragAndDrop";
import {TaskEvent} from "@/lib/task/calendar/data";
import {number} from "prop-types";
import {DATE_TIME} from "@/lib/constants";

/**
 * https://github.com/jquense/react-big-calendar?tab=readme-ov-file
 * @constructor
 */
const localizer = dayjsLocalizer(dayjs)
const DragAndDropCalendar = withDragAndDrop(Calendar)
const CalShow: React.FC = () => {
    dayjs.locale('zh-cn')
    const [view, setView] = useState<View>('week');
    const [date, setDate] = useState<Date>(new Date());
    const clickRef = useRef<number|undefined|null>(null)
    // 展示在页面的任务,默认获取当前月的信息。
    const [events, setEvents] = useState<TaskEvent[]>([]);
    const [open, setOpen] = useState(false);
    const [description, setDescription] = useState('');
    const [operationId, setOperationId] = useState(-1);
    const [itemId, setItemId] = useState(-1);
    const [expectedStartTime, setExpectedStartTime] = useState<Dayjs>();
    const [expectedEndTime, setExpectedEndTime] = useState<Dayjs>();
    const [range, setRange] = useState<{start: Date; end: Date}>({
        start: dayjs(date).startOf('week').toDate(),
        end: dayjs(date).endOf('week').toDate()
    });
    const [state, setState] = useState<string>(useContext(LocalContext).taskState);

    const handleViewChange = (newView: View) => {
        setView(newView);
    };
    var pid = useSearchParams().get('pid');
    function clearClickTimeout(){
        clickRef && typeof clickRef.current=== 'number' &&!isNaN(clickRef.current) && isFinite(clickRef.current)&&window.clearTimeout(clickRef.current)
    }
    const handleNavigate = (newDate: Date) => {
        console.log('handleNavigate', newDate)
        setDate(newDate);
        const searchList: SearchObject[] = []
        if (pid != null) {
            searchList.push({name: "pid", value: pid, operateType: "="},
                {name: 'ALL-CHILD', value: "true", operateType: "ALL-CHILD"},
                {name: 'TREE-FILTER', value: "true", operateType: "TREE-FILTER"},
            );
        }
        loadData(searchList);
    };

    useEffect(() => {
        console.log("CalShow:useEffect:range",range)
        const searchListE = []
        if (pid != null) {
            searchListE.push(
                {name: "pid", value: pid, operateType: "="},
                {name: 'ALL-CHILD', value: "true", operateType: "ALL-CHILD"},
                {name: 'TREE-FILTER', value: "true", operateType: "TREE-FILTER"},
            );
        }
        // searchListE.push({name: 'expectedStartTime', value: range.start, operateType: ">="})
        // searchListE.push({name: 'expectedStartTime', value: range.end, operateType: "<="})
        loadData(searchListE);
        /**
         * What Is This?
         * This is to prevent a memory leak, in the off chance that you
         * teardown your interface prior to the timed method being called.
         */
        return () => {
            clearClickTimeout()
        }
    }, [useContext(LocalContext),range]);
    const message = {
        week: '周',
        work_week: '工作周',
        day: '天',
        month: '月',
        previous: '前',
        next: '后',
        today: '当下',
        agenda: '日程'
    }
    const loadData = (searchList: SearchObject[]) => {
        if (state.length > 0) {
            searchList.push({name: 'state', value: state, operateType: "IN"})
        }
        // searchList.push({name: 'expectedEndTime', value: dayjs(date).endOf('month'), operateType: "NOT NULL"})
        let request = JSON.stringify({
            pageSize: 9999,
            pageNumber: 1,
            data: searchList,
            startTime:range.start,
            // startTime:dayjs(range.start).format('YYYY-MM-DD HH:mm:ss'),
            endTime:range.end,
            // endTime:dayjs(range.end).format('YYYY-MM-DD HH:mm:ss'),
            startColumn:"expected_start_time",
            endColumn:"expected_end_time"
        })
        getTaskTreeResult(request).then(responseD => {
            if (responseD.status.success) {
                let result:TaskEvent[] =responseD.data.content.map<TaskEvent>(taskState => {
                    return {
                        start: dayjs(taskState.expectedStartTime).toDate(),
                        end: dayjs(taskState.expectedEndTime).toDate(),
                        title: taskState.name,
                        resource: taskState.id,
                        id:taskState.id,
                        state:taskState.state,
                        priority:taskState.priority
                    }
                });
                console.log('responseD.data.content:',result)
                setEvents([...result])
            }
        })
    }
    const reloadData = () => {
        setOpen(false)
        handleNavigate(expectedStartTime ? expectedStartTime.toDate() : date)
    }
    const handleSelectSlot = useCallback(
        ({start, end}: SlotInfo) => {
            setExpectedEndTime(dayjs(end))
            setExpectedStartTime(dayjs(start))
            setOperationId(OPERATION_BUTTON_TYPE.ADD)
            setDescription("添加任务")
            setOpen(true);
        },
        [setEvents]
    )

    const handleSelectEvent = useCallback(
        (event: Event, e: React.SyntheticEvent<HTMLElement>) => {
            clearClickTimeout()
            clickRef.current = window.setTimeout(()=> {
                // window.alert(event.title);
                console.log(event)
                setOperationId(OPERATION_BUTTON_TYPE.DETAIL)
                setDescription("任务详情")
                setItemId(event.resource)
                setOpen(true);
            },250)
        },
        []
    )
    const {defaultDate, scrollToTime} = useMemo(
        () => ({
            defaultDate: new Date(2015, 3, 12),
            scrollToTime: new Date(1970, 1, 1, 6),
        }),
        []
    )

    const doubleClick = (event: TaskEvent, e: React.SyntheticEvent<HTMLElement>) => {
        clearClickTimeout()
        clickRef.current = window.setTimeout(()=>{
            // 数据落库
            commonUpdate({
                updateColumnList: [{
                    name: '任务状态',
                    code: 'state',
                    value: 7
                }],
                conditionColumnList: [{
                    name: 'id',
                    code: 'id',
                    operateType: '=',
                    value: event.resource
                }]
            })
            setEvents((prev: TaskEvent[]) => {
                const existing: TaskEvent | undefined = prev.find((ev: TaskEvent) => ev.resource === event.resource);
                const filtered: TaskEvent[] | undefined = prev.filter((ev: TaskEvent) => ev.resource !== event.resource);
                let result: TaskEvent[] = [];
                if (existing !== undefined&&filtered !== undefined) {
                    result= [...filtered, {...existing, state:7}];
                }
                let strings = state.split(",");
                console.log('result',result,strings)
                return result.filter((ev: TaskEvent) => strings.indexOf(ev.state.toString())>=0);
            })
        },250)
    }

    const moveEvent = useCallback(
        ({event, start, end, isAllDay: droppedOnAllDaySlot = false}: EventInteractionArgs<TaskEvent>) => {
            console.log("onEventResize || onEventDrop :",start,end)
            const {allDay} = event
            if (!allDay && droppedOnAllDaySlot) {
                event.allDay = true
            }
            // 数据落库
            commonUpdate({
                updateColumnList: [{
                    name: 'expectedStartTime',
                    code: '',
                    value: start.toLocaleString()
                }, {
                    name: 'expectedEndTime',
                    code: '',
                    value: end.toLocaleString()
                }],
                conditionColumnList: [{
                    name: 'id',
                    code: 'id',
                    operateType: '=',
                    value: event.resource
                }]
            })
            setEvents((prev: TaskEvent[]) => {
                const existing: TaskEvent | undefined = prev.find((ev: TaskEvent) => ev.resource === event.resource);
                const filtered: TaskEvent[] | undefined = prev.filter((ev: TaskEvent) => ev.resource !== event.resource);
                if (start instanceof Date && end instanceof Date && existing !== undefined) {
                    return [...filtered, {...existing, start, end, allDay}];
                }
                if (filtered !== undefined) {
                    return [...filtered];
                }
                return [];
            })
        },
        [setEvents]
    )

    const eventPropGetter = useCallback(
        (event:TaskEvent) => ({
            ...(event.state===7
                ? { className: 'completeTask' }
                : event.priority===3?{ className: 'importantUrgentTask' }:
                    event.priority===2?{ className: 'importantNotUrgentTask' }:
                        event.priority===1?{ className: 'notImportantUrgentTask' }:
                            { className: 'notImportantNotUrgentTask' }),
        }),
        [setEvents]
    )
    const rangeChange = (rangeLet: Date[]|{ start: Date; end: Date },current?:View|undefined)=>{
        console.log("rangeChange:",rangeLet,(current?current:view))
        // view 为天的时候类型为数组，index:0为当天
        if ((current?current:view)==="day"&&Array.isArray(rangeLet)) {
            if (range.start.valueOf()>rangeLet[0].valueOf()){
                setRange({...range,start:rangeLet[0]})
            }else if (range.end.valueOf()<rangeLet[0].valueOf()){
                setRange({...range,end:rangeLet[0]})
            }
        }
        //      为周的时候类型为数组，周一到周日七天
        if ((current?current:view)==="week"&&Array.isArray(rangeLet)){
            if (range.start.valueOf()>rangeLet[0].valueOf()){
                setRange({...range,start:rangeLet[0]})
            }
            if (range.end.valueOf()<rangeLet[6].valueOf()){
                setRange({...range,end:rangeLet[6]})
            }
        }
        //      为周的时候类型为对象
        if ((current?current:view)==="month"&& rangeLet && !Array.isArray(rangeLet)){
            if (range.start.valueOf()>rangeLet.start.valueOf()){
                setRange({...range,start:rangeLet.start})
            }
            if (range.end.valueOf()<rangeLet.end.valueOf()){
                setRange({...range,end:rangeLet.end})
            }
        }

    }
    return <div className="App" style={{height: '90vh'}}>
        {open && <DetailModelForm operationId={operationId} description={description} open={open} haveButton={false}
                         itemId={itemId} pid={pid?Number(pid):0}
                         reloadData={reloadData} expectedStartTime={expectedStartTime}
                         expectedEndTime={expectedEndTime}/>}
        <DragAndDropCalendar
            // 本地设置
            localizer={localizer}
            messages={message}
            // 修改style
            eventPropGetter={eventPropGetter}
            events={events}
            // 界面
            view={view}
            // 界面改变
            onView={handleViewChange}
            onRangeChange={rangeChange}
            // 时间
            date={date}
            // 条目信息改变
            onNavigate={handleNavigate}

            // 点击
            selectable
            scrollToTime={scrollToTime}
            // 双击
            onDoubleClickEvent={doubleClick}
            // 点击任务
            onSelectEvent={handleSelectEvent}
            // 点击空白处
            onSelectSlot={handleSelectSlot}
            // 改变时间长短
            resizable
            onEventResize={moveEvent}
            onEventDrop={moveEvent}
        />
    </div>
}
export default CalShow;
