<template>
    <div v-if="recordShow" v-loading="loading">
        <div class="app-status card-interval">
            <el-card>
                <div class="flex w-full flex-col gap-4 md:flex-row">
                    <div class="flex flex-wrap gap-4 ml-3">
                        <el-popover
                            v-if="dialogData.rowData.name.length >= 15"
                            placement="top-start"
                            trigger="hover"
                            width="250"
                            :content="$t('cronjob.' + dialogData.rowData.type) + ' - ' + dialogData.rowData.name"
                        >
                            <template #reference>
                                <el-tag style="float: left" effect="dark" type="success">
                                    {{ $t('cronjob.' + dialogData.rowData.type) }} -
                                    {{ dialogData.rowData.name.substring(0, 12) }}...
                                </el-tag>
                            </template>
                        </el-popover>
                        <el-tag
                            v-if="dialogData.rowData.name.length < 15"
                            class="float-left"
                            effect="dark"
                            type="success"
                        >
                            {{ $t('cronjob.' + dialogData.rowData.type) }} - {{ dialogData.rowData.name }}
                        </el-tag>

                        <Status class="mt-0.5" :status="dialogData.rowData.status" />
                    </div>
                    <div class="mt-0.5">
                        <el-button
                            type="primary"
                            v-permission
                            v-node-admin
                            :disabled="dialogData.rowData.status === 'Pending'"
                            @click="onHandle(dialogData.rowData)"
                            link
                        >
                            {{ $t('commons.button.handle') }}
                        </el-button>
                        <el-divider direction="vertical" v-if="dialogData.rowData.status !== 'Pending'" />
                        <el-button
                            type="primary"
                            v-if="dialogData.rowData.status === 'Enable'"
                            v-permission
                            v-node-admin
                            @click="onChangeStatus(dialogData.rowData.id, 'disable')"
                            link
                        >
                            {{ $t('commons.button.disable') }}
                        </el-button>
                        <el-button
                            type="primary"
                            v-if="dialogData.rowData.status === 'Disable'"
                            v-permission
                            v-node-admin
                            @click="onChangeStatus(dialogData.rowData.id, 'enable')"
                            link
                        >
                            {{ $t('commons.button.enable') }}
                        </el-button>
                        <el-divider direction="vertical" />
                        <el-button
                            v-permission
                            v-node-admin
                            :disabled="!hasRecords"
                            type="primary"
                            @click="onClean"
                            link
                        >
                            {{ $t('commons.button.clean') }}
                        </el-button>
                    </div>
                </div>
            </el-card>
        </div>

        <LayoutContent :title="$t('cronjob.record')" :reload="true">
            <template #rightToolBar>
                <el-date-picker
                    class="mr-2.5"
                    @change="search(true)"
                    v-model="timeRangeLoad"
                    type="datetimerange"
                    range-separator="-"
                    :start-placeholder="$t('commons.search.timeStart')"
                    :end-placeholder="$t('commons.search.timeEnd')"
                    :shortcuts="shortcuts"
                ></el-date-picker>
                <el-select @change="search(true)" v-model="searchInfo.status" class="p-w-200">
                    <template #prefix>{{ $t('commons.table.status') }}</template>
                    <el-option :label="$t('commons.table.all')" value="" />
                    <el-option :label="$t('commons.status.success')" value="Success" />
                    <el-option :label="$t('commons.status.waiting')" value="Waiting" />
                    <el-option :label="$t('commons.status.unexecuted')" value="Unexecuted" />
                    <el-option :label="$t('commons.status.failed')" value="Failed" />
                </el-select>
                <TableRefresh @search="search(false)" />
            </template>
            <template #main>
                <div class="mainClass">
                    <el-row :gutter="20" v-show="hasRecords" class="mainRowClass row-box">
                        <el-col :span="7">
                            <el-card class="el-card">
                                <div class="infinite-list" style="overflow: auto">
                                    <ComplexTable
                                        style="cursor: pointer"
                                        :data="records"
                                        :show-header="false"
                                        @row-click="forDetail"
                                    >
                                        <el-table-column min-width="230px">
                                            <template #default="{ row }">
                                                <span v-if="row.id === currentRecord.id" class="select-sign"></span>
                                                <Status class="mr-2 mt-1 ml-1 float-left w-20" :status="row.status" />
                                                <div class="mt-0.5">
                                                    <span>
                                                        {{ row.startTime }}
                                                    </span>
                                                </div>
                                            </template>
                                        </el-table-column>
                                        <el-table-column min-width="30px">
                                            <template #default="{ row }">
                                                <el-tooltip :content="$t('cronjob.stop')">
                                                    <el-button
                                                        v-if="
                                                            dialogData.rowData.type === 'shell' &&
                                                            row.status === 'Waiting'
                                                        "
                                                        class="float-right"
                                                        link
                                                        type="primary"
                                                        @click="onStop(row.id)"
                                                        icon="SwitchButton"
                                                    />
                                                </el-tooltip>
                                            </template>
                                        </el-table-column>
                                    </ComplexTable>
                                </div>
                                <div class="page-item">
                                    <el-pagination
                                        :page-size="searchInfo.pageSize"
                                        :current-page="searchInfo.page"
                                        @current-change="handleCurrentChange"
                                        @size-change="handleSizeChange"
                                        :pager-count="5"
                                        :page-sizes="[5, 10, 20, 50, 100, 200, 500, 1000]"
                                        small
                                        layout="total, sizes, prev, pager, next"
                                        :total="searchInfo.recordTotal"
                                    />
                                </div>
                            </el-card>
                        </el-col>
                        <el-col :span="17">
                            <el-card class="el-card">
                                <el-form label-position="top">
                                    <el-row type="flex" justify="center">
                                        <el-form-item class="descriptionWide">
                                            <template #label>
                                                <span class="status-label">{{ $t('commons.search.timeStart') }}</span>
                                            </template>
                                            <span class="status-count">
                                                {{ dateFormat(0, 0, currentRecord?.startTime) }}
                                            </span>
                                        </el-form-item>
                                        <el-form-item class="description">
                                            <template #label>
                                                <span class="status-label">{{ $t('commons.table.interval') }}</span>
                                            </template>
                                            <el-button
                                                link
                                                v-if="currentRecord?.status === 'Waiting' && !currentRecord?.interval"
                                                :loading="true"
                                            />
                                            <span v-else class="status-count">
                                                {{ formatInterval(currentRecord?.interval) }}
                                            </span>
                                        </el-form-item>
                                        <el-form-item class="description">
                                            <template #label>
                                                <span class="status-label">{{ $t('commons.table.status') }}</span>
                                            </template>
                                            <Status :status="currentRecord?.status" />
                                            <el-tooltip :content="currentRecord?.message">
                                                <el-button
                                                    class="mt-0.5"
                                                    type="danger"
                                                    v-if="
                                                        currentRecord?.status === 'Failed' ||
                                                        currentRecord?.status === 'Unexecuted'
                                                    "
                                                    icon="Warning"
                                                    link
                                                />
                                            </el-tooltip>
                                        </el-form-item>
                                    </el-row>
                                    <el-row v-if="currentRecord?.taskID && currentRecord?.taskID != ''">
                                        <LogFile
                                            :defaultButton="true"
                                            class="w-full"
                                            :key="currentRecord?.taskID"
                                            @stop-reading="search(false)"
                                            :heightDiff="420"
                                            :config="{
                                                type: 'task',
                                                colorMode: 'task',
                                                taskID: currentRecord?.taskID,
                                                tail: true,
                                            }"
                                        />
                                    </el-row>
                                </el-form>
                            </el-card>
                        </el-col>
                    </el-row>
                </div>
                <div class="app-warn" v-show="!hasRecords">
                    <div>
                        <span>{{ $t('cronjob.noRecord') }}</span>
                        <div>
                            <img src="@/assets/images/no_app.svg" />
                        </div>
                    </div>
                </div>
            </template>
        </LayoutContent>

        <DialogPro v-model="open" :title="$t('commons.button.clean')" size="small">
            <el-form ref="deleteForm" label-position="left" v-loading="delLoading">
                <el-form-item>
                    <el-checkbox v-model="cleanData" :label="$t('cronjob.cleanData')" />
                    <el-checkbox v-if="cleanData" v-model="cleanRemoteData" :label="$t('cronjob.cleanRemoteData')" />
                    <span class="input-help">
                        {{ $t('cronjob.cleanDataHelper') }}
                    </span>
                </el-form-item>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="open = false" :disabled="delLoading">
                        {{ $t('commons.button.cancel') }}
                    </el-button>
                    <el-button type="primary" @click="cleanRecord">
                        {{ $t('commons.button.confirm') }}
                    </el-button>
                </span>
            </template>
        </DialogPro>
    </div>
</template>

<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { Cronjob } from '@/api/interface/cronjob';
import { searchRecords, handleOnce, updateStatus, cleanRecords, stopCronjob } from '@/api/modules/cronjob';
import { dateFormat } from '@/utils/date';
import LogFile from '@/components/log/file/index.vue';
import i18n from '@/lang';
import { ElMessageBox } from 'element-plus';
import { MsgSuccess } from '@/utils/message';
import { listDbItems } from '@/api/modules/database';
import { listAppInstalled } from '@/api/modules/app';
import { shortcuts } from '@/utils/shortcuts';
import { hasBackup } from '../helper';

const loading = ref();
const hasRecords = ref();

interface DialogProps {
    rowData: Cronjob.CronjobInfo;
}
const recordShow = ref(false);
const dialogData = ref();
const records = ref<Array<Cronjob.Record>>([]);
const currentRecord = ref<Cronjob.Record>();

const open = ref();
const delLoading = ref();
const cleanData = ref();
const cleanRemoteData = ref();

const formatInterval = (interval?: number) => {
    if (!interval || interval < 0) {
        return '-';
    }

    const totalMilliseconds = Math.floor(interval);
    const hours = Math.floor(totalMilliseconds / 3600000);
    const minutes = Math.floor((totalMilliseconds % 3600000) / 60000);
    const seconds = Math.floor((totalMilliseconds % 60000) / 1000);
    const milliseconds = totalMilliseconds % 1000;
    return [
        hours ? `${hours}h` : '',
        minutes ? `${minutes}min` : '',
        seconds ? `${seconds}s` : '',
        milliseconds ? `${milliseconds}ms` : '',
    ]
        .filter(Boolean)
        .join(' ');
};

const acceptParams = async (params: DialogProps): Promise<void> => {
    let itemSize = Number(localStorage.getItem(searchInfo.cacheSizeKey));
    if (itemSize) {
        searchInfo.pageSize = itemSize;
    }

    recordShow.value = true;
    dialogData.value = params;
    if (dialogData.value.rowData.type === 'database') {
        const data = await listDbItems('mysql,mariadb,mysql-cluster,postgresql,postgresql-cluster,mongodb');
        let itemDBs = data.data || [];
        for (const item of itemDBs) {
            if (item.id == dialogData.value.rowData.dbName) {
                dialogData.value.rowData.dbName = item.database + ' [' + item.name + ']';
                break;
            }
        }
    }
    if (dialogData.value.rowData.type === 'app') {
        const res = await listAppInstalled();
        let itemApps = res.data || [];
        for (const item of itemApps) {
            if (item.id == dialogData.value.rowData.appID) {
                dialogData.value.rowData.appID = item.key + ' [' + item.name + ']';
                break;
            }
        }
    }
    search(true);
};

const handleSizeChange = (val: number) => {
    searchInfo.pageSize = val;
    localStorage.setItem(searchInfo.cacheSizeKey, val + '');
    search(true);
};
const handleCurrentChange = (val: number) => {
    searchInfo.page = val;
    search(false);
};

const timeRangeLoad = ref<[Date, Date]>([
    new Date(new Date(new Date().getTime() - 3600 * 1000 * 24 * 7).setHours(0, 0, 0, 0)),
    new Date(new Date().setHours(23, 59, 59, 999)),
]);
const searchInfo = reactive({
    cacheSizeKey: 'cronjob-record-page-size',
    page: 1,
    pageSize: 10,
    recordTotal: 0,
    cronjobID: 0,
    startTime: new Date(),
    endTime: new Date(),
    status: '',
});

const onHandle = async (row: Cronjob.CronjobInfo) => {
    loading.value = true;
    await handleOnce(row.id)
        .then(() => {
            loading.value = false;
            MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
            search(true);
        })
        .catch(() => {
            loading.value = false;
        });
};

const onChangeStatus = async (id: number, status: string) => {
    ElMessageBox.confirm(i18n.global.t('cronjob.' + status + 'Msg'), i18n.global.t('cronjob.changeStatus'), {
        confirmButtonText: i18n.global.t('commons.button.confirm'),
        cancelButtonText: i18n.global.t('commons.button.cancel'),
    }).then(async () => {
        let itemStatus = status === 'enable' ? 'Enable' : 'Disable';
        await updateStatus({ id: id, status: itemStatus });
        MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
        dialogData.value.rowData.status = itemStatus;
    });
};

const search = async (changeToLatest: boolean) => {
    if (timeRangeLoad.value && timeRangeLoad.value.length === 2) {
        searchInfo.startTime = timeRangeLoad.value[0];
        searchInfo.endTime = timeRangeLoad.value[1];
    } else {
        searchInfo.startTime = new Date(new Date().setHours(0, 0, 0, 0));
        searchInfo.endTime = new Date();
    }
    let params = {
        page: searchInfo.page,
        pageSize: searchInfo.pageSize,
        cronjobID: dialogData.value.rowData!.id,
        startTime: searchInfo.startTime,
        endTime: searchInfo.endTime,
        status: searchInfo.status,
    };
    const res = await searchRecords(params);
    records.value = res.data.items;
    searchInfo.recordTotal = res.data.total;
    hasRecords.value = searchInfo.recordTotal !== 0;
    if (!hasRecords.value) {
        return;
    }
    if (changeToLatest || !currentRecord.value) {
        currentRecord.value = records.value[0];
        return;
    }
    for (const item of records.value) {
        if (item.id === currentRecord.value.id) {
            currentRecord.value = item;
            break;
        }
    }
};

const forDetail = (row: Cronjob.Record) => {
    currentRecord.value = row;
};

const onClean = async () => {
    if (!hasBackup(dialogData.value.rowData.type)) {
        ElMessageBox.confirm(i18n.global.t('commons.msg.clean'), i18n.global.t('commons.button.clean'), {
            confirmButtonText: i18n.global.t('commons.button.confirm'),
            cancelButtonText: i18n.global.t('commons.button.cancel'),
            type: 'warning',
        }).then(async () => {
            await cleanRecords(dialogData.value.rowData.id, cleanData.value, cleanRemoteData.value)
                .then(() => {
                    delLoading.value = false;
                    MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
                    search(true);
                })
                .catch(() => {
                    delLoading.value = false;
                });
        });
    } else {
        open.value = true;
    }
};

const onStop = async (id: number) => {
    ElMessageBox.confirm(i18n.global.t('cronjob.stopHelper'), i18n.global.t('cronjob.stop'), {
        confirmButtonText: i18n.global.t('commons.button.confirm'),
        cancelButtonText: i18n.global.t('commons.button.cancel'),
        type: 'warning',
    }).then(async () => {
        await stopCronjob(id);
        MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
    });
};

const cleanRecord = async () => {
    delLoading.value = true;
    await cleanRecords(dialogData.value.rowData.id, cleanData.value, cleanRemoteData.value)
        .then(() => {
            delLoading.value = false;
            open.value = false;
            MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
            search(true);
        })
        .catch(() => {
            delLoading.value = false;
        });
};

defineExpose({
    acceptParams,
});
</script>

<style lang="scss" scoped>
.infinite-list {
    height: calc(100vh - 320px);
    .select-sign {
        &::before {
            float: left;
            margin-left: -3px;
            position: relative;
            width: 3px;
            height: 24px;
            content: '';
            background: $primary-color;
            border-radius: 20px;
        }
    }
    .el-tag {
        margin-left: 20px;
        margin-right: 20px;
    }
}

.descriptionWide {
    width: 40%;
}
.description {
    width: 30%;
}
.page-item {
    margin-top: 10px;
    font-size: 12px;
    float: right;
}

@media only screen and (max-width: 1400px) {
    .mainClass {
        overflow: auto;
    }
    .mainRowClass {
        min-width: 1200px;
    }
}
</style>
