<template>
    <PagingTable url="/game" :where="where" ref="table">
        <template #filter>
            <ElSelect v-model="where.roomId" clearable placeholder="筛选房间">
                <ElOption v-for="item in rooms" :key="item.id" :label="item.name" :value="item.id" />
            </ElSelect>
            <ElButton :icon="Plus" @click="onEdit()">添加</ElButton>
        </template>
        <ElTableColumn prop="id" label="#" width="80" />
        <ElTableColumn prop="name" label="名称" />
        <ElTableColumn prop="type" label="类型" width="100" />
        <ElTableColumn prop="roomId" label="房间ID" />
        <ElTableColumn prop="status" label="状态" width="150" :formatter="statusFormatter" />
        <ElTableColumn prop="autoReset" label="自动重置" />
        <ElTableColumn prop="resetNum" label="重置次数" />
        <ElTableColumn prop="running" label="运行" width="100" align="center">
            <template #default="{ row }">
                <ElSwitch
                    v-if="row.status === 'initialized' || row.status === 'running'"
                    :model-value="row.status === 'running'"
                    @update:model-value="onActiveChange($event, row)"
                />
            </template>
        </ElTableColumn>
        <ElTableColumn prop="createdAt" label="创建时间" :formatter="timeFormatter" width="150" />
        <ElTableColumn label="操作" align="center" width="350">
            <template #default="{ row }">
                <ElButton @click="onEdit(row)" type="primary">编辑</ElButton>
                <ElButton v-if="row.status === 'created'" @click="onInit(row)" type="primary">初始化</ElButton>
                <ElButton v-if="row.status !== 'created'" @click="onPlay(row)" type="primary">详情</ElButton>
                <ElButton v-if="row.status !== 'created'" @click="reset(row)" type="warning">重置</ElButton>
                <ElButton @click="onDelete(row)" type="danger">删除</ElButton>
            </template>
        </ElTableColumn>
    </PagingTable>
    <EditDialog
        v-model="showEditDialog"
        :model="model"
        :rules="rules"
        :on-submit="submit"
        @success="table.refresh()"
        width="800px"
    >
        <ElFormItem prop="name" label="名称">
            <ElInput v-model="model.name" placeholder="请输入名称" />
        </ElFormItem>
        <ElFormItem prop="type" label="类型">
            <ElSelect v-model="model.type" placeholder="请选择类型">
                <ElOption v-for="item in promptTypes" :key="item" :label="item" :value="item" />
            </ElSelect>
        </ElFormItem>
        <ElFormItem prop="roomId" label="房间">
            <ElSelect v-model="model.roomId" placeholder="请选择房间">
                <ElOption v-for="item in rooms" :key="item.id" :label="item.name" :value="item.id" />
            </ElSelect>
        </ElFormItem>
        <ElFormItem prop="autoReset" label="自动重置">
            <ElRadioGroup v-model="model.autoReset">
                <ElRadio :label="true">是</ElRadio>
                <ElRadio :label="false">否</ElRadio>
            </ElRadioGroup>
        </ElFormItem>
        <ElFormItem prop="background" label="故事背景">
            <ElInput v-model="model.background" type="textarea" placeholder="请输入故事背景" />
        </ElFormItem>
        <ElFormItem prop="charactors" label="初始角色">
            <div class="charactor-form" v-for="(item, i) in model.charactors" :key="i">
                <ElForm :model="item" label-position="top" inline :rules="charactorRules" ref="charactorForms">
                    <ElFormItem prop="avatar" label="头像">
                        <SingleUpload v-model="item.avatar" />
                    </ElFormItem>
                    <ElFormItem prop="name" label="角色名称">
                        <ElInput v-model="item.name" />
                    </ElFormItem>
                    <ElFormItem prop="gender" label="性别">
                        <ElInput v-model="item.gender" />
                    </ElFormItem>
                    <ElFormItem prop="age" label="年龄">
                        <ElInput v-model="item.age" />
                    </ElFormItem>
                    <ElFormItem prop="occupation" label="职业">
                        <ElInput v-model="item.occupation" />
                    </ElFormItem>
                    <ElFormItem prop="personality" label="性格">
                        <ElInput v-model="item.personality" />
                    </ElFormItem>
                    <div class="w-full"></div>
                    <ElFormItem class="w-full" prop="background" label="背景">
                        <ElInput v-model="item.background" type="textarea" />
                    </ElFormItem>
                </ElForm>
                <ElButton type="danger" size="small" @click="removeCharactor(i)">删除</ElButton>
            </div>
            <ElButton @click="genCharactor" :loading="generating">生成</ElButton>
            <ElButton @click="onAddCharactor">添加</ElButton>
        </ElFormItem>
    </EditDialog>
    <ElDialog title="初始化" v-model="showInitDialog">
        <ElForm :model="initModel" :rules="initRules" ref="initForm" label-position="right" label-width="80">
            <ElFormItem label="日期" prop="date">
                <ElDatePicker v-model="initModel.date" />
            </ElFormItem>
            <ElFormItem label="时间" prop="time">
                <ElSelect v-model="initModel.time">
                    <ElOption label="上午" value="morning" />
                    <ElOption label="下午" value="afternoon" />
                    <ElOption label="晚上" value="evening" />
                </ElSelect>
            </ElFormItem>
            <ElFormItem label="初始剧情" prop="plot">
                <ElInput v-model="initModel.plot" type="textarea" placeholder="不填则自动生成" :rows="3" />
            </ElFormItem>
        </ElForm>
        <template #footer>
            <ElButton @click="showInitDialog = false">取消</ElButton>
            <ElButton type="primary" @click="init">确定</ElButton>
        </template>
    </ElDialog>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import PagingTable from '@/components/PagingTable.vue'
import { useEnumFormatter, useTimeFormatter } from '@/utils/formatter'
import { Plus } from '@vicons/tabler'
import EditDialog from '@/components/EditDialog.vue'
import { setupEditDialog } from '@/utils/editDialog'
import { http } from '@/plugins/http'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRouter } from 'vue-router'
import { ElLoading } from 'element-plus'
import { GameStatus } from '@/enums'

const router = useRouter()
const where = ref({})
const timeFormatter = useTimeFormatter()
const statusFormatter = useEnumFormatter(GameStatus)
const table = ref(null)
const model = ref({})
const rules = {
    name: [{ required: true, message: '请输入昵称', trigger: 'blur' }],
    type: [{ required: true, message: '请选择类型', trigger: 'blur' }],
    roomId: [{ required: true, message: '请选择房间', trigger: 'blur' }],
    autoReset: [{ required: true, message: '请输入自动重置', trigger: 'blur' }],
    background: [{ required: true, message: '请输入故事背景', trigger: 'blur' }],
    charactors: [
        {
            validator: (rule, value, callback) => {
                if (!value || value.length === 0) {
                    callback(new Error('请输入初始角色'))
                } else {
                    Promise.all(charactorForms.value.map((form) => form.validate()))
                        .then(() => {
                            callback()
                        })
                        .catch(() => {
                            callback(new Error('请输入初始角色'))
                        })
                }
            }
        }
    ]
}

const rooms = ref([])
const promptTypes = ref([])
onMounted(() => {
    http.post('/room').then((res) => {
        rooms.value = res.items
    })
    http.get('/prompt/types').then((res) => {
        promptTypes.value = res
    })
})

const { showEditDialog, onEdit } = setupEditDialog(model)
async function submit() {
    await http.put(model.value.id ? `/game/${model.value.id}` : '/game', model.value)
    ElMessage.success('保存成功')
}
async function onDelete(row) {
    await ElMessageBox.confirm('确认删除？', '删除', { type: 'warning' })
    await http.delete(`/game/${row.id}`)
    ElMessage.success('删除成功')
    table.value.refresh()
}
const generating = ref(false)
async function genCharactor() {
    if (!model.value.background) {
        ElMessage.error('请先输入故事背景')
        return
    }
    if (!model.value.background) {
        ElMessage.error('请先选择类型')
        return
    }
    const { value } = await ElMessageBox.prompt('生成数量：', '生成角色', {
        inputPattern: /^\d{1,2}$/,
        inputErrorMessage: 'Invalid Num'
    })
    generating.value = true
    try {
        const res = await http.post(`/game/genCharactor`, {
            type: model.value.type,
            background: model.value.background,
            num: value
        })
        generating.value = false
        model.value.charactors = (model.value.charactors || []).concat(res)
    } catch (error) {
        ElMessage.error(error.message)
        generating.value = false
    }
}
function onAddCharactor() {
    model.value.charactors = (model.value.charactors || []).concat({})
}
const charactorRules = {
    avatar: [{ required: true, message: '请上传头像', trigger: 'blur' }],
    name: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
    gender: [{ required: true, message: '请输入性别', trigger: 'blur' }],
    age: [{ required: true, message: '请输入年龄', trigger: 'blur' }],
    occupation: [{ required: true, message: '请输入职业', trigger: 'blur' }],
    personality: [{ required: true, message: '请输入性格', trigger: 'blur' }],
    background: [{ required: true, message: '请输入背景', trigger: 'blur' }]
}
const charactorForms = ref([])
function removeCharactor(index) {
    model.value.charactors.splice(index, 1)
}
function onPlay(row) {
    router.push({
        name: 'play',
        params: {
            gameId: row.id,
            roomId: row.roomId
        }
    })
}
const showInitDialog = ref(false)
const initForm = ref(null)
const initModel = ref({})
const selectedRow = ref(null)
const initRules = {
    date: [{ required: true, message: '请选择日期', trigger: 'blur' }],
    time: [{ required: true, message: '请选择时间', trigger: 'blur' }]
}
async function onInit(row) {
    selectedRow.value = row
    initModel.value = {}
    initForm.value?.clearValidate()
    showInitDialog.value = true
}
async function init() {
    await initForm.value.validate()
    const loadingInstance = ElLoading.service({
        fullscreen: true
    })
    try {
        await http.post(`/game/${selectedRow.value.id}/init`, initModel.value)
        ElMessage.success('初始化成功')
        table.value.refresh()
        showInitDialog.value = false
    } catch (error) {
        ElMessage.error(error.message)
    }
    loadingInstance.close()
}
async function onActiveChange(e, row) {
    const loadingInstance = ElLoading.service({
        fullscreen: true
    })
    try {
        if (e) {
            await http.post(`/game/${row.id}/startRun`)
        } else {
            await http.post(`/game/${row.id}/stopRun`)
        }
        table.value.refresh()
    } catch (error) {
        ElMessage.error(error.message)
    }
    loadingInstance.close()
}
async function reset(row) {
    ElMessageBox.confirm('确认重置？', '重置', {
        type: 'warning',
        beforeClose: (action, instance, done) => {
            if (action === 'confirm') {
                instance.confirmButtonLoading = true
                instance.confirmButtonText = '执行中...'
                http.post(`/game/${row.id}/reset`)
                    .then(() => {
                        ElMessage.success('重置成功')
                        table.value.refresh()
                        done()
                    })
                    .catch((error) => {
                        ElMessage.error(error.message)
                        done()
                    })
            } else {
                done()
            }
        }
    })
}
</script>
<style lang="less" scoped>
.charactor-form {
    background-color: var(--el-color-info-light-9);
    padding: 15px;
    border-radius: 8px;
    margin-bottom: 10px;
    .el-form-item {
        margin-bottom: 20px;
    }
}
</style>
