import {reactive} from 'vue';
import request from "../utils/request";
import {showFailToast, showSuccessToast} from "vant";
import dayjs from "dayjs";
import {
    Comment,
    CommentRefTypes,
    HtyBaseRoles,
    HtyRoles,
    Jihua,
    JihuaQueryParam,
    Lianxi,
    NotifyParam,
    NotifyTypes,
    PickTargets,
    Piyue,
    CourseSection,
    VersionedData, VersionedDataTypes
} from '~/types'
import useUser from "~/store/user";
import {DateFormatter, formatDate} from "~/utils";
import useLoading from "~/store/loading";
import useLianxi from "~/store/lianxi";
import useRefResource from "~/store/ref-resource";
import useComment from "~/store/comment";
import usePiyue from "~/store/piyue";
import useNotify from "~/store/notify";
import useCourseCategory from "~/store/qumu-category";
import useTask from "~/store/task";

const initialJihua = () => ({
    start_date: dayjs().startOf('day').toDate(),
    end_date: dayjs().add(6, 'day').startOf('day').toDate(),
    course_sections: [] as CourseSection[]
} as Jihua);

export interface JihuaState {
    current: Jihua,
    list: Jihua[],
    recent: Jihua[],
    total: number,
    pages: number,
    hanging: boolean,
    checking: boolean,
    current_lianxi?: Lianxi,
    query_cache?: JihuaQueryParam,
    ai_score_tried: number
}

const store = reactive<JihuaState>({
    current: initialJihua(),
    list: [],
    recent: [],
    total: 0,
    pages: 0,
    hanging: false,
    checking: false,
    ai_score_tried: 0
});


export default function useJihua() {

    const usingUser = useUser();
    const {create_lianxi, check_lianxi_tasks, remove_lianxi} = useLianxi();
    const {create_comment, check_comments_task, load_comments, get_resource_note_group, check_resource_notes_task, get_resource_note_group_by_ref_id} = useComment()
    const { create_piyue } = usePiyue()
    const {notify_ws} = useNotify();
    const {get_hty_resource_by_id} = useRefResource()
    const { isTaskFinished } = useTask();
    const notify = (params: NotifyParam, role_key: HtyRoles) =>  notify_ws(params, role_key);
    const {load_start, load_done} = useLoading()

    const usingQC = useCourseCategory()
    usingQC.query();

    function reset() {
        if (!store.hanging) {
            store.current = initialJihua();
        }
        store.hanging = false;
    }

    function show_versioned_date (item: Jihua) {
        let { versioned_data } = item;
        if (versioned_data?.length) {
            for (let i = versioned_data.length - 1; i >= 0; i--) {
                let {to_data} = versioned_data[i]
                item.yanqi_start_date = to_data.start_date;
                item.yanqi_end_date = to_data.end_date;
                if (dayjs(to_data.start_date).valueOf() <= dayjs().startOf('date').valueOf()) {
                    break;
                }
            }
        }
    }

    async function query(params: JihuaQueryParam): Promise<boolean> {
        let {current: {hty_id}, currentRole} = usingUser.store;
        if (currentRole === HtyBaseRoles.TEACHER) {
            params.teacher_id = hty_id;
        } else if (currentRole === HtyBaseRoles.STUDENT) {
            params.student_id = hty_id;
        }
        store.query_cache = params;
        load_start()
        const {r, d, e} = await request({url: '/api/v1/ws/find_jihuas_with_sections_by_user_id', params});
        load_done()
        if (r) {
            if (params.page === 1) {
                store.list = [];
            }
            let [list, pages, total] = d;
            list.forEach(x => {
                convert(x)
                show_versioned_date(x)
            })
            store.list = [...store.list, ...list];
            store.total = total;
            store.pages = pages;
        } else {
            showFailToast(e);
        }
        return Promise.resolve(r);
    }

    async function query_recent(): Promise<boolean> {
        let {current: {hty_id}, currentRole} = usingUser.store;

        let params = {
            page: 1, page_size: 20, is_compare_current_date: true
        } as JihuaQueryParam;
        if (currentRole === HtyBaseRoles.TEACHER) {
            params.teacher_id = hty_id;
        } else if (currentRole === HtyBaseRoles.STUDENT) {
            params.student_id = hty_id;
        }
        load_start()
        const {r, d, e} = await request({url: '/api/v1/ws/find_jihuas_with_sections_by_user_id', params});
        load_done()
        if (r) {
            let [list, pages, total] = d;
            list.forEach(x => {
                convert(x)
                show_versioned_date(x)
            })
            store.recent = list;
        } else {
            showFailToast(e);
        }
        return Promise.resolve(r);
    }

    const convert = (jihua: Jihua) => {
        let { course_sections, course_sections2 } = jihua;
        let lianxiDict = {};
        course_sections.forEach(qs => {
            lianxiDict[qs.id] = qs
        })
        if (course_sections2?.vals?.length) {
            jihua.course_sections = course_sections2.vals
            jihua.course_sections.forEach(qs => {
                let tmp = lianxiDict[qs.id];
                qs.lianxis = tmp?.lianxis;
                qs.lianxi_count = tmp?.lianxi_count;
                qs.not_piyue_count = tmp?.not_piyue_count

            })
        }
    }

    async function get_qs_resource_note_groups() {
        for (let i = 0; i < store.current.course_sections.length; i++) {
            let qs = store.current.course_sections[i]
            if (!qs.resource_note_group) {
                await get_resource_note_group(qs)
            } else {
                // we need to set comments to global state by check_comments_tasks function
                await check_resource_notes_task(qs.resource_note_group)
            }
        }
    }

    async function check_tasks() {
        if (store.checking) return;
        store.checking = true;
        store.ai_score_tried = 0;
        await check_comments_task(store.current.id)
        await check_lianxi_tasks(store.current.course_sections);
        store.checking = false;
    }

    async function read(id: string, forceReload = false) {
        if (!id) return;
        if (store.current.id === id && !forceReload) return;
        load_start()
        const {r, d, e} = await request({url: `/api/v1/ws/find_jihua_by_id2/${id}`});
        if (r) {
            convert(d);
            store.current = d;
            show_versioned_date(d)
            await load_comments(id);
            await get_qs_resource_note_groups();
        } else {
            reset()
            showFailToast(e);
        }
        load_done()
    }

    function valid() {
        let { start_date, student_id, course_sections } = store.current;
        if (!start_date) {
            showFailToast("请选择计划起始日期！")
            return false;
        }
        if (!student_id) {
            showFailToast("请选择学生！")
            return false;
        }
        if (!course_sections.length) {
            showFailToast('请添加课程！')
            return false;
        }
        return true
    }

    async function prepare(qs?: CourseSection) {
        let { course_sections, course_sections2, ...rest } = store.current

        console.log(qs)
        let qsData = {vals: []}
        for (let i = 0; i < course_sections.length; i++) {
            if (qs?.id === course_sections[i].id) {
                course_sections[i] = qs;
                store.current.course_sections[i] = qs;
            }
            let { resources, ref_resources, id, resource_note_group, ...rest } = course_sections[i];
            ref_resources = ref_resources || resources;
            if (!resource_note_group) {
                resource_note_group = await get_resource_note_group_by_ref_id(id)
            }
            qsData.vals.push({id, ref_resources, ...rest, resource_note_group})
        }
        console.log(qsData)
        return {...rest, course_sections: qsData, course_section_ids: course_sections.map(x => x.id),}
    }

    async function create() {
        if (!valid()) return 0
        load_start()
        let data = await prepare();
        if (!data) {
            load_done();
            return 0;
        }
        data.teacher_id = usingUser.store.current.hty_id;
        data.teacher_name = usingUser.store.current.real_name;
        data.created_by = usingUser.store.current.hty_id;
        console.log(data)
        const {r, d, e} = await request({url: `/api/v1/ws/create_jihua`, data, method: 'POST'});
        load_done()
        if (r) {
            showSuccessToast('创建成功！');
            reset()
            notify({ hty_id: data.student_id, jihua_id: d.id, notify_type: NotifyTypes.JihuaCreate } as NotifyParam, HtyBaseRoles.STUDENT)
            return d.id;
        } else {
            showFailToast(e);
        }
    }

    async function update(qs?: CourseSection) {
        if (!valid()) return Promise.reject()
        load_start()
        let data = await prepare(qs);
        if (!data) {
            load_done();
            return 0;
        }
        console.log(data)
        const {r, e} = await request({
            url: `/api/v1/ws/update_jihua`, data, method: 'POST'
        });
        load_done()
        if (r) {
            showSuccessToast('保存成功');
            reset()
            notify({ hty_id: data.student_id, jihua_id: data.id, notify_type: NotifyTypes.JihuaUpdate } as NotifyParam, HtyBaseRoles.STUDENT)
        } else {
            load_done()
            showFailToast(e);
        }
        return r;
    }

    async function remove() {
        load_start()
        let { id } = store.current
        const {r, e} = await request({
            url: `/api/v1/ws/delete_jihua_by_id/${id}`,
            method: 'POST'
        });
        load_done()
        notify({ hty_id: store.current.student_id, jihua_id: id, notify_type: NotifyTypes.JihuaDelete } as NotifyParam, HtyBaseRoles.STUDENT)
        if (!r) {
            showFailToast(e);
        }
        return r;
    }

    async function get_shifan(jihua_course_section_id?: string) {
        let relation = store.current.relations?.find(r => r.id === jihua_course_section_id);
        let course_section = store.current.course_sections.find(qs => qs.id === relation?.course_section_id);
        let audio_type = course_section?.course_category_key || usingQC.getDefault()?.category_key;
        let shifan = (course_section?.ref_resources || course_section?.resources)?.find(r => r.is_shifan);
        if (shifan) {
            let url = shifan.resource_url;
            if (shifan.hty_resource_id) {
                let resource = await get_hty_resource_by_id(shifan.hty_resource_id);
                if (resource) {
                    url = resource.url;
                }
            }
            return { shifan_url: url, audio_type }
        }
        return;
    }

    async function create_jihua_lianxi(data: Lianxi) {
        load_start()
        let shifan = await get_shifan(data.jihua_course_section_id);
        let lianxi_id = await create_lianxi(data, shifan)
        if (lianxi_id) {
            await read(store.current.id, true);
        }
        load_done()
        return lianxi_id;
    }

    async function delete_jihua_lianxi(data: Lianxi) {
        let relation = store.current.relations?.find(r => r.id === data.jihua_course_section_id);
        let course_section = store.current.course_sections.find(qs => qs.id === relation?.course_section_id);
        const r = await remove_lianxi(data.id);
        if (r) {
            notify({ hty_id: store.current.teacher_id, lianxi_id: data.id, notify_type: NotifyTypes.LianxiDelete } as NotifyParam, HtyBaseRoles.TEACHER)
            await read(store.current.id, true);
        }
        return r;
    }

    async function create_jihua_piyue(piyue: Piyue) {
        const piyue_id = await create_piyue(piyue);
        if (piyue_id) {
            await read(store.current.id, true);
            notify({
                hty_id: store.current.student_id,
                lianxi_id: piyue.lianxi_id, piyue_id,
                notify_type: NotifyTypes.PiyueCreate
            } as NotifyParam, HtyBaseRoles.STUDENT)
        }
        return piyue_id
    }

    async function create_jihua_comment(comment: Comment) {
        // @ts-ignore
        let qs = store.current.course_sections.find(x => x.lianxis?.includes(store.current_lianxi));
        let shifan_url = qs?.resources?.find(r => r.is_shifan)?.resource_url
        let audio_type = qs?.course_category_key
        const created = await create_comment(comment, {shifan_url, audio_type});
        if (created) {
            let piyues = store.current_lianxi?.piyues;
            if (comment.ref_type === CommentRefTypes.Piyue) {
                piyues?.forEach(x => {
                    if (x.id === comment.ref_id) {
                        if (!x.comments.includes(created)) {
                            x.comments.push(created)
                        }
                    }
                })
            } else if (comment.ref_type === CommentRefTypes.ResourceNote) {
                piyues?.forEach(x => {
                    x.resource_note_group?.resource_notes?.forEach(y => {
                        if (y.id === comment.ref_id) {
                            if (!y.comments?.includes(created)) {
                                y.comments?.push(created)
                            }
                        }
                    })
                })
            }
            return created
        }
    }

    async function delay() {
        let { start_date, end_date, student_id, id, versioned_data } = store.current;
        if (versioned_data && versioned_data.length) {
            let latest = versioned_data[versioned_data.length - 1]
            start_date = latest.to_data.start_date;
            end_date = latest.to_data.end_date;
        }
        let origin = {start_date, end_date}
        // clean data
        let target = {
            start_date: dayjs(start_date).add(7, 'day').format(DateFormatter.DateTimeSave),
            end_date: dayjs(end_date).add(7, 'day').format(DateFormatter.DateTimeSave),
        }
        let data: VersionedData = {
            ref_id: id, ref_type: PickTargets.JIHUA, data_type: VersionedDataTypes.DateRange,
            from_data: origin, to_data: target
        }
        load_start()
        const {r, d, e} = await request({url: `/api/v1/ws/create_versioned_data`, data, method: 'POST'});
        load_done()
        if (r) {
            let { course_sections, ...rest } = store.current
            await request({
                url: `/api/v1/ws/update_jihua`,
                data: {...rest, is_yanqi: true, end_date: target.end_date, course_section_ids: course_sections.map(x => x.id)}, method: 'POST'
            });
            showSuccessToast('计划已延后一周！');
            notify({ hty_id: student_id, jihua_id: id, notify_type: NotifyTypes.JihuaUpdate } as NotifyParam, HtyBaseRoles.STUDENT)
            let res = await request({url: `/api/v1/ws/get_versioned_data_by_ref_id/${id}`})
            if (res.r) {
                store.current.versioned_data = res.d;
                store.current.end_date = target.end_date;
                store.current.is_yanqi = true;
                show_versioned_date(store.current)
            }
        } else {
            showFailToast(e);
        }
        return d;
    }

    function get_lianxi_by_id(lianxi_id: string) {
        let lianxi;
        store.current.course_sections.forEach(qs => {
            qs.lianxis?.forEach(lx => {
                if (lx.id === lianxi_id) {
                    lianxi =lx;
                    return;
                }
            })
        })
        return lianxi;
    }


    return {
        store, query, read, create, update, remove, reset, create_jihua_lianxi, notify, get_shifan, prepare,
        delete_jihua_lianxi, create_jihua_piyue, delay, check_tasks, query_recent, create_jihua_comment, load_comments, get_lianxi_by_id
    };


}
