import { Host, h } from "@stencil/core";
import { configStore, connectionJobsStore, deviceModeStore, filterChatsStore } from "../../store/store";
import { Icon } from "../internal-component/icon";
import { useTranslation } from "../../utils/utils";
import { handleGetConnectionJobs } from "../../store/job";
import { handleGetChats, resetChatFilter } from "../../store/chat";
import { checkCircleGreen, errorCircleRed, refreshCcw } from "../../utils/icon-svg";
import { initSocket, joinRoom, leaveRoom, disconnectSocket, getSocket } from "../../utils/socket";
import { deleteConnectionJob, initConnection } from "../../api";
export class BackgroundJobs {
    isExpanded = false;
    isRefresh = false;
    isShowJob = new Set();
    jobCompleted;
    socketConnectionNamespace = '/connection';
    socketZwizNamespace = '/zwiz';
    completedStates = new Set(['completed']);
    activeStates = new Set(['active', 'delayed', 'prioritized', 'waiting', 'waiting-children']);
    failedStates = new Set(['failed', 'unknown']);
    async componentWillLoad() {
        const socketConnection = initSocket(this.socketConnectionNamespace);
        const socketZwiz = initSocket(this.socketZwizNamespace);
        const jobs = connectionJobsStore.get('jobs') || [];
        const businessId = configStore.get('businessId');
        const shopId = configStore.get('shopId');
        if (jobs.length > 0) {
            for (const job of jobs) {
                if (job.channel === 'zwiz') {
                    joinRoom(`${businessId}:${shopId}:${job.id}`, this.socketZwizNamespace);
                }
                else {
                    joinRoom(job.id, this.socketConnectionNamespace);
                }
            }
            socketConnection.on('init-connection', this.onInitConnectionEvent);
            socketZwiz.on('sync', this.onZwizSyncEvent);
        }
    }
    disconnectedCallback() {
        const jobs = connectionJobsStore.get('jobs') || [];
        const businessId = configStore.get('businessId');
        const shopId = configStore.get('shopId');
        for (const job of jobs) {
            if (job.channel === 'zwiz') {
                leaveRoom(`${businessId}:${shopId}:${job.id}`, this.socketZwizNamespace);
            }
            else {
                leaveRoom(job.id, this.socketConnectionNamespace);
            }
        }
        const socketConnection = getSocket(this.socketConnectionNamespace);
        const socketZwiz = getSocket(this.socketZwizNamespace);
        socketConnection.off('init-connection', this.onInitConnectionEvent);
        socketZwiz.off('sync', this.onZwizSyncEvent);
        disconnectSocket(this.socketConnectionNamespace);
        disconnectSocket(this.socketZwizNamespace);
    }
    onInitConnectionEvent = async ({ id, channel, state }) => {
        console.log('Socket on init-connection state', id, channel, state);
        if (['completed', 'removed', 'failed'].includes(state)) {
            const jobs = connectionJobsStore.get('jobs') || [];
            if (['completed', 'failed'].includes(state)) {
                connectionJobsStore.set('jobs', jobs.map(job => {
                    if (job.id === id) {
                        return {
                            ...job,
                            init_state: state,
                        };
                    }
                    return job;
                }));
            }
            if (state === 'removed') {
                connectionJobsStore.set('jobs', jobs.filter(job => job.id !== id));
            }
        }
    };
    onZwizSyncEvent = async ({ id, channel, user, chat_message }) => {
        console.log('Socket on zwiz sync state', id, channel, user, chat_message);
        if (['completed', 'removed', 'failed'].includes(user) || ['completed', 'removed', 'failed'].includes(chat_message)) {
            const jobs = connectionJobsStore.get('jobs') || [];
            if (['completed', 'failed'].includes(user) || ['completed', 'failed'].includes(chat_message)) {
                connectionJobsStore.set('jobs', jobs.map(job => {
                    if (job.id === id) {
                        return {
                            ...job,
                            user: user,
                            chat_message: chat_message,
                        };
                    }
                    return job;
                }));
            }
            if (user === 'removed' && chat_message === 'removed') {
                connectionJobsStore.set('jobs', jobs.filter(job => job.id !== id));
            }
        }
    };
    toggleExpand = () => {
        this.isExpanded = !this.isExpanded;
    };
    getJobInfo(state) {
        if (this.activeStates.has(state.toLowerCase())) {
            return {
                title: 'background_job.in_progress',
                icon: (h("div", { class: "job-icon" }, h(Icon, { name: "LoaderCircle", addClass: "job-icon-secondary animate-spin" })))
            };
        }
        if (this.failedStates.has(state.toLowerCase())) {
            return {
                title: 'background_job.error',
                icon: (h("div", { class: "job-icon" }, h("div", { class: "size-5" }, errorCircleRed())))
            };
        }
        if (this.completedStates.has(state.toLowerCase())) {
            return {
                title: 'background_job.success',
                icon: (h("div", { class: "job-icon" }, h("div", { class: "size-5" }, checkCircleGreen())))
            };
        }
        return null;
    }
    render() {
        const t = useTranslation();
        const jobs = connectionJobsStore.get('jobs') || [];
        const isMobile = deviceModeStore.get('mode') === 'mobile';
        if (jobs.length === 0) {
            return null;
        }
        const isAllSuccess = jobs.every(job => {
            if (job.channel === 'zwiz') {
                const userSuccess = !this.activeStates.has(job.user.toLowerCase());
                const chatMessageSuccess = !this.activeStates.has(job.chat_message.toLowerCase());
                return userSuccess && chatMessageSuccess;
            }
            else {
                return !this.activeStates.has(job.init_state.toLowerCase());
            }
        });
        const title = isAllSuccess
            ? 'background_job.sync'
            : 'background_job.syncing';
        const handleRefresh = async () => {
            this.isRefresh = true;
            resetChatFilter();
            await Promise.all([
                handleGetConnectionJobs(),
                handleGetChats(filterChatsStore.get('filterChat'))
            ]);
            this.jobCompleted.emit();
            this.isRefresh = false;
        };
        const handleTryAgain = async (job, isUser = false) => {
            this.isRefresh = true;
            if (job.channel != 'zwiz') {
                await initConnection({ connectionId: job.id, channel: job.channel });
                const jobs = connectionJobsStore.get('jobs') || [];
                connectionJobsStore.set('jobs', jobs.map(_job => {
                    if (_job.id === job.id) {
                        return {
                            ..._job,
                            init_state: 'active',
                        };
                    }
                    return _job;
                }));
            }
            else {
                if (isUser) {
                    //TODO: call api retry zwiz user job
                }
                else {
                    //TODO: call api retry zwiz chat message job
                }
            }
            this.isRefresh = false;
        };
        const handleRemove = async (job) => {
            this.isRefresh = true;
            await deleteConnectionJob({ connectionId: job.id });
            this.isRefresh = false;
        };
        const renderJobDetail = (job, jobInfo, isHideDelete = false, isUser = false) => {
            return h("div", { class: "background-jobs-item whitespace-nowrap" }, h("div", { class: "row-box" }, jobInfo?.icon, h("span", { class: `text-primary truncate max-w-${jobInfo?.title === 'background_job.error' ? 42 : 56}`, title: job.name }, job.name)), t(jobInfo?.title), " ", jobInfo?.title === 'background_job.error' &&
                h("div", { class: "row-box" }, h("span", { class: "cursor-pointer underline", onClick: (event) => {
                        event.stopPropagation();
                        handleTryAgain(job, isUser);
                    } }, t('background_job.try_again')), !isHideDelete &&
                    h("div", { class: "job-delete-icon", onClick: (event) => {
                            event.stopPropagation();
                            handleRemove(job);
                        } }, h(Icon, { name: "X" }))));
        };
        return (h(Host, null, h("div", { class: `background-jobs ${isMobile ? 'right-1 bottom-1' : 'right-4 bottom-4'}` }, h("div", { class: `background-jobs-card ${isMobile ? 'w-full' : 'w-100'}` }, h("div", { class: "background-jobs-header", onClick: this.toggleExpand }, h("div", { class: "background-jobs-title" }, h("div", { class: `size-3 rotate-45 ${this.isRefresh ? 'animate-spin' : ''}` }, refreshCcw()), h("span", null, t(title)), "\u00A0", isAllSuccess &&
            h("span", { class: "cursor-pointer underline", onClick: (event) => {
                    event.stopPropagation();
                    handleRefresh();
                } }, t('background_job.refresh'))), h("div", { class: `transform transition-transform duration-300 ${this.isExpanded ? 'rotate-180' : ''}` }, h(Icon, { name: "ChevronUp", addClass: "job-icon" }))), h("div", { class: `background-jobs-list ${this.isExpanded ? 'expanded' : ''}` }, this.isRefresh
            ? h("div", { class: "background-jobs-item" }, h(Icon, { name: "LoaderCircle", addClass: "job-icon-secondary animate-spin" }))
            : jobs.map((job) => {
                if (job.channel === 'zwiz') {
                    const activeJob = this.activeStates.has(job.user.toLowerCase()) || this.activeStates.has(job.chat_message.toLowerCase());
                    const failedJob = this.failedStates.has(job.user.toLowerCase()) || this.failedStates.has(job.chat_message.toLowerCase());
                    const completedJob = this.completedStates.has(job.user.toLowerCase()) || this.completedStates.has(job.chat_message.toLowerCase());
                    const jobInfo = this.getJobInfo(activeJob ? 'active' : failedJob ? 'failed' : completedJob ? 'completed' : 'active');
                    const userJobInfo = this.getJobInfo(job.user);
                    const chatMessageJobInfo = this.getJobInfo(job.chat_message);
                    return h("div", null, h("div", { class: "background-jobs-item whitespace-nowrap" }, h("div", { class: "row-box" }, jobInfo?.icon, h("span", { class: "text-primary truncate max-w-56", title: job.name }, job.name)), h("div", { class: "row-box" }, t(jobInfo?.title), [
                        jobInfo?.title,
                        userJobInfo.title,
                        chatMessageJobInfo.title
                    ].includes('background_job.error') &&
                        h("div", { class: "row-box" }, h("div", { class: "job-delete-icon", onClick: (event) => {
                                event.stopPropagation();
                                handleRemove(job);
                            } }, h(Icon, { name: "X" }))), h("div", { class: `transform transition-transform duration-300 cursor-pointer ${this.isShowJob.has(job.id) ? 'rotate-180' : ''}`, onClick: () => {
                            const newShowJob = new Set(this.isShowJob);
                            if (newShowJob.has(job.id)) {
                                newShowJob.delete(job.id);
                            }
                            else {
                                newShowJob.add(job.id);
                            }
                            this.isShowJob = newShowJob;
                        } }, h(Icon, { name: "ChevronUp", addClass: "job-icon-secondary" })))), this.isShowJob.has(job.id) &&
                        h("div", { class: "ml-4" }, renderJobDetail({ ...job, name: t('background_job.user') }, userJobInfo, true, true), renderJobDetail({ ...job, name: t('background_job.message') }, chatMessageJobInfo, true, false)));
                }
                else {
                    const jobInfo = this.getJobInfo(job.init_state);
                    return renderJobDetail(job, jobInfo);
                }
            }))))));
    }
    static get is() { return "background-jobs"; }
    static get originalStyleUrls() {
        return {
            "$": ["background-jobs.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["background-jobs.css"]
        };
    }
    static get states() {
        return {
            "isExpanded": {},
            "isRefresh": {},
            "isShowJob": {}
        };
    }
    static get events() {
        return [{
                "method": "jobCompleted",
                "name": "jobCompleted",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }];
    }
}
