import {reactive} from 'vue';
import request from "../utils/request";
import {showFailToast, showSuccessToast} from "vant";
import {DateFormatter, formatDate, ImageHelper} from "~/utils";
import {Router} from "vue-router";
import {
    CourseSection,
    TaskTypes,
    UploadPhoto,
    CourseQueryParam,
    RefResource,
    RefResourceTypes, RefTypes,
} from "~/types";
import useLoading from "~/store/loading";
import useUser from "~/store/user";
import useRefResource from "~/store/ref-resource";
import useComment from "~/store/comment";

const initialEntity = (): CourseSection => ({
    id: undefined,
    course_name: '',
    section_name: ''
} as CourseSection);

interface CourseStore {
    current: CourseSection,
    mine: {
        list: CourseSection[],
        total: number,
        pages: number,
    },
    assigned: {
        list: CourseSection[],
        total: number,
        pages: number,
    }

    hanging: boolean,
    checking: boolean,
    qupuList: Partial<UploadPhoto>[],
    videoList: RefResource[],
    audioList: RefResource[],
}

const store = reactive<CourseStore>({
    current: initialEntity(),
    mine: {
        list: [],
        total: 0,
        pages: 0,
    },
    assigned: {
        list: [],
        total: 0,
        pages: 0,
    },
    hanging: false,
    checking: false,
    qupuList: [],
    videoList: [],
    audioList: []
});

export default function useCourseSection(router?: Router) {

    const { load_start, load_done} = useLoading()
    const {check_resources_task} = useRefResource()
    const {get_resource_note_group} = useComment()
    const usingUser = useUser();

    function normalizeCourseSectionPagedPayload(payload: unknown, scene: string): [CourseSection[], number, number] {
        if (Array.isArray(payload) && payload.length >= 3 && Array.isArray(payload[0])) {
            return [payload[0] as CourseSection[], Number(payload[1]) || 0, Number(payload[2]) || 0];
        }
        const debugInfo = {
            scene,
            payload_type: Object.prototype.toString.call(payload),
            is_array: Array.isArray(payload),
            timestamp: new Date().toISOString(),
        };
        console.warn("[CourseSectionPayloadDebug]", debugInfo, payload);
        window.localStorage.setItem("CourseSectionPayloadDebug", JSON.stringify(debugInfo));
        showFailToast("课程列表数据格式异常，已回退为空列表");
        return [[], 0, 0];
    }

    function normalizeCourseSectionListPayload(payload: unknown, scene: string): CourseSection[] {
        if (Array.isArray(payload)) {
            return payload as CourseSection[];
        }
        const debugInfo = {
            scene,
            payload_type: Object.prototype.toString.call(payload),
            is_array: Array.isArray(payload),
            timestamp: new Date().toISOString(),
        };
        console.warn("[CourseSectionPayloadDebug]", debugInfo, payload);
        window.localStorage.setItem("CourseSectionPayloadDebug", JSON.stringify(debugInfo));
        return [];
    }

    function normalizeCourseSectionResources(list: CourseSection[], scene: string): CourseSection[] {
        return list.map((courseSectionItem) => {
            const resourceList = (courseSectionItem as Record<string, unknown>).resources;
            if (resourceList === undefined || Array.isArray(resourceList)) {
                return courseSectionItem;
            }
            const debugInfo = {
                scene,
                course_section_id: courseSectionItem.id,
                resources_type: Object.prototype.toString.call(resourceList),
                timestamp: new Date().toISOString(),
            };
            console.warn("[CourseSectionResourceDebug]", debugInfo, resourceList);
            window.localStorage.setItem("CourseSectionResourceDebug", JSON.stringify(debugInfo));
            return {
                ...courseSectionItem,
                resources: [],
            };
        });
    }

    async function query(params: CourseQueryParam, key: "mine" | "assigned"): Promise<boolean> {
        load_start()
        let {hty_id} = usingUser.store.current;
        let field = {mine: "created_by", assigned: "teacher_id"}[key];
        const {r, d, e} = await request({
            url: `/api/v1/ws/find_all_course_sections_by_${field}_with_page`,
            data: {...params, [field]: hty_id}
        });
        load_done()
        if (r) {
            let temp = store[key];
            if (params.page === 1) {
                temp.list = [];
            }
            let [list, pages, total] = normalizeCourseSectionPagedPayload(d, `query_${key}`);
            list = normalizeCourseSectionResources(list, `query_${key}`);
            temp.list = [...temp.list, ...list];
            temp.total = total;
            temp.pages = pages;
            let hty_ids = new Set<string>();
            list.forEach(({created_by, updated_by}: CourseSection) => {
                if (created_by) {
                    hty_ids.add(created_by)
                }
                if (updated_by) {
                    hty_ids.add(updated_by)
                }
            });
            Promise.all([...hty_ids].map(x => usingUser.getHtyUser(x))).then((users) => {
                temp.list.forEach(qs => {
                    let creator = users.find(u => u.hty_id === qs.created_by);
                    if (creator) {
                        qs.creator_name = creator.real_name
                    }
                    let updator = users.find(u => u.hty_id === qs.updated_by);
                    if (updator) {
                        qs.updator_name = updator.real_name
                    }
                })
            })
            store[key] = temp;
        } else {
            console.warn("[CourseSectionQueryFail]", {
                tab: key,
                urlField: field,
                error: e,
                requestParams: {...params, [field]: hty_id},
            });
            showFailToast(e);
        }
        return Promise.resolve(r);
    }

    function reset() {
        if (!store.hanging) {
            store.current = initialEntity();
            store.qupuList = [];
            store.videoList = [];
        }
    }

    async function read(id: string, editing = false) {
        if (!id) return;
        if (store.hanging) {
            store.hanging = false;
            return;
        }
        load_start()
        const {r, d, e} = await request({url: `/api/v1/ws/find_course_section_by_id/${id}`});

        if (r) {
            store.current = d;
            d.resources = Array.isArray(d.resources) ? d.resources : [];
            check_resources_task(d.resources)
            if (editing) {
                let qupu_resource = d.resources?.find((r: RefResource) => r.ref_type === RefTypes.CourseSection && r.resource_type === RefResourceTypes.Picture);
                if (qupu_resource && qupu_resource.resource_url) {
                    store.qupuList = [{url: qupu_resource.resource_url, hty_resource_id: qupu_resource.hty_resource_id}];
                }
                store.videoList = (d.resources || []).filter((r: RefResource) => r.resource_type === RefResourceTypes.Video);
                store.audioList = (d.resources || []).filter((r: RefResource) => r.resource_type === RefResourceTypes.Audio);
            }
            await get_resource_note_group(d)
        } else {
            reset();
            showFailToast(e);
        }
        load_done()
    }

    async function query_by_ids(ids) {
        load_start()
        try {
            const {r, d, e} = await request({
                url: `/api/v1/ws/find_course_sections_by_ids`, method: "POST", data: {vals: ids}
            });
            if (r) {
                load_done();
                const list = normalizeCourseSectionListPayload(d, "query_by_ids");
                return normalizeCourseSectionResources(list, "query_by_ids");
            }
            console.log(e)
        } catch (e) {
            console.log(e)
        }
        load_done()
    }

    function valid(qupuList: Partial<UploadPhoto>[], current: CourseSection, videoList: Partial<RefResource>[]) {
        if (!current.course_id) {
            showFailToast('请选择课程体系！')
            return false;
        }
        if (!current.course_category_key) {
            showFailToast('请选择课程体系类型！')
            return false;
        }
        if (!current.section_name) {
            showFailToast('请填写章节！')
            return false
        }
        if (!current.course_text) {
            showFailToast('请填写说明！')
            return false
        }
        // if (!qupuList.length && !videoList.length) {
        //     showFailToast('请添加图片或视频！')
        //     return false
        // }
        return true
    }

    async function create() {
        let {qupuList, videoList, current} = store;
        if (!valid(qupuList, current, videoList)) {
            return Promise.reject()
        }
        load_start()
        let task_id;
        if(qupuList.length) {
            task_id = await ImageHelper.combine_by_form(qupuList);
            if (!task_id) {
                load_done()
                return Promise.reject();
            }
        }

        let resources = [...videoList]
        if (task_id) {
            resources.push({
                ref_type: RefTypes.CourseSection, ref_name: "图片", resource_type: RefResourceTypes.Picture,
                tasks: {vals: [{task_id, task_type: TaskTypes.UPLOAD_PICTURE}]}
            } as RefResource)
        }

        let data = {...current, resources};
        const {r, d, e} = await request({url: `/api/v1/ws/create_course_section`, method: 'POST', data});
        load_done()
        if (r) {
            showSuccessToast({message: '课程创建成功！', onClose: () => router?.replace(`/course/section/detail?id=${d.id}`)});
            reset();
        } else {
            showFailToast(e);
        }
    }

    async function save_draft(data: CourseSection) {
        data.is_draft = true;
        if (data.id) {
            const {r, d, e} = await request({url: `/api/v1/ws/update_course_section_by_id`, method: 'POST', data});
            if (r) {
                store.current = d;
                store.videoList = d.resources || [];
            }
        } else {
            const {r, d, e} = await request({url: `/api/v1/ws/create_course_section`, method: 'POST', data});
            if (r) {
                store.current = d;
                store.videoList = d.resources || [];
            }
        }
    }

    async function clone(router: Router, id?: string) {
        let data = {...store.current};
        if (id) {
            const {r, d, e} = await request({url: `/api/v1/ws/find_course_section_by_id/${id}`});
            if (r) {
                data = {...d}
            } else {
                showFailToast(e)
                return Promise.reject();
            }
        }
        data.cloned_from = data.id;
        delete data.id;
        data.section_name += "(" + formatDate(new Date(), DateFormatter.DateTime) + "复制)"
        const {r, d, e} = await request({url: `/api/v1/ws/create_course_section`, method: 'POST', data});
        if (r) {
            showSuccessToast({
                message: "课程复制成功！",
                onClose: () => {
                    if (id) {
                        router.push('/course/section/detail?id=' + d.id)
                    } else {
                        router.replace('/course/section/detail?id=' + d.id)
                    }
                }
            })

        } else {
            showFailToast(e);
        }
    }

    async function update() {
        let {qupuList, current, videoList, audioList} = store;
        if (!valid(qupuList, current, videoList)) {
            return Promise.reject()
        }

        load_start()
        let data: CourseSection = {...current};
        let resources = [...videoList, ...audioList];
        if (qupuList.length) {
            // @ts-ignore
            if (qupuList.some(x => !x.hty_resource_id)) {
                let task_id = await ImageHelper.combine_by_form(qupuList);
                if (!task_id) {
                    load_done()
                    return Promise.reject();
                }
                resources.push({
                    ref_type: "CourseSection", ref_name: "图片", resource_type: RefResourceTypes.Picture,
                    tasks: {vals: [{task_id, task_type: TaskTypes.UPLOAD_PICTURE}]}
                } as RefResource);
            } else {
                // restore qupu resource
                resources.push(...(current.resources || []).filter(r => r.resource_type === RefResourceTypes.Picture));
            }
        }
        if (data.is_draft) {
            data.created_at = new Date()
            data.created_by = usingUser.store.current.hty_id;
            data.is_draft = false;
        } else {
            data.updated_by = new Date();
            data.updated_by = usingUser.store.current.hty_id;
        }
        data.resources = resources.map(({ref_id, ...rest}) => ({...rest, ref_id: current.id}));
        const {r, e} = await request({url: `/api/v1/ws/update_course_section_by_id`, method: 'POST', data});
        load_done()
        if (r) {
            showSuccessToast({message: '课程保存成功', onClose: () => router?.replace(`/course/section/detail?id=${data.id}`)});
            reset();
        } else {
            showFailToast(e);
        }
    }

    async function remove(id: string, callback: () => void) {
        load_start()
        const {r, e} = await request({
            url: `/api/v1/ws/delete_course_section_by_id/${id || store.current.id}`, method: 'POST'
        });
        load_done()
        if (r) {
            showSuccessToast({message: '课程删除成功！', onClose: callback});
            reset();
        } else {
            showFailToast(e);
        }
    }

    async function check_is_in_use(id: string) {
        load_start()
        const {r, d, e} = await request({
            url: `/api/v1/ws/is_course_section_in_use/${id}`
        });
        load_done();
        if (r) {
            return d;
        } else {
            showFailToast(e)
        }
    }


    async function find_draft() {
        load_start()
        const {r, d, e} = await request({
            url: `/api/v1/ws/find_draft_course_sections_of_user`
        });
        load_done();
        if (r) {
            return d[0];
        } else {
            showFailToast(e)
        }
    }

    async function remove_current() {
        await remove(store.current.id as string, () => router?.go(-1))
    }


    return {
        store, query, read, create, update, remove, remove_current, reset, check_is_in_use, find_draft, save_draft, clone, query_by_ids
    };


}
