<script lang="ts">
export default {
    name: "header-manage",
};
</script>

<script setup lang="ts">
import { onMounted, reactive, ref, computed, toRefs } from "vue";
import {
    ElTable,
    ElForm,
    ElMessage,
    ElMessageBox,
    UploadProps,
} from "element-plus";
import { Plus, Delete, UploadFilled } from "@element-plus/icons-vue";
import {
    headerList,
    createHeader,
    deleteHeader,
    updateHeader,
    enableHeader,
    disableHeader,
} from "@/api/cms";
import { HeaderQueryParam, HeaderItem, HeaderFormData } from "@/types/api/cms";
import { getAccessToken } from "@/utils/auth-token";

const internalUriOptions = [
    { label: "首页", value: "/" },
    { label: "行情", value: "/market" },
    { label: "合约交易-BTCUSDT", value: "/futures/BTCUSDT" },
    { label: "合约交易-ETHUSDT", value: "/futures/ETHUSDT" },
    { label: "跟单广场", value: "/copy-trading" },
    { label: "我的跟单", value: "/my-copy-trading" },
    { label: "申请带单", value: "/trader-apply" },
    { label: "我的带单", value: "/my-trades" },
    { label: "资产总览", value: "/asset" },
    { label: "充币", value: "/asset/deposit" },
    { label: "提币", value: "/asset/withdraw" },
    { label: "划转", value: "/asset/transfer" },
    { label: "资产记录", value: "/asset/history" },
    { label: "邀请返佣", value: "/user/referral" },
    { label: "个人中心", value: "/user" },
    { label: "账户设置", value: "/user/account" },
    { label: "身份认证(KYC)", value: "/user/kyc" },
    { label: "API管理", value: "/user/api-keys" },
    { label: "帮助中心", value: "/user/help" },
    { label: "经纪商", value: "/broker" },
    { label: "自定义URI", value: "__custom__" },
];

const dataTableRef = ref(ElTable);
const queryFormRef = ref(ElForm);
const dataFormRef = ref(ElForm);

const emptyForm = (): HeaderFormData => ({
    title: "",
    mediaType: "image",
    displayType: 0,
    mediaUrl: "",
    dayMediaUrl: "",
    nightMediaUrl: "",
    linkType: "internal",
    linkUrl: "/",
    sort: 0,
    status: 1,
    startTime: "",
    endTime: "",
});

const state = reactive({
    loading: true,
    ids: [] as number[],
    multiple: true,
    queryParams: { pageNo: 1, pageSize: 15 } as HeaderQueryParam,
    list: [] as HeaderItem[],
    total: 0,
    dialog: { title: "", visible: false },
    formData: emptyForm() as HeaderFormData,
    selectedInternalUri: "/",
    customLinkUrl: "",
    rules: {
        title: [{ required: true, message: "请输入Header标题", trigger: "blur" }],
        mediaType: [{ required: true, message: "请选择媒体类型", trigger: "change" }],
        displayType: [{ required: true, message: "请选择展示类型", trigger: "change" }],
        linkType: [{ required: true, message: "请选择跳转类型", trigger: "change" }],
        linkUrl: [{ required: true, message: "请填写跳转地址", trigger: "blur" }],
    },
    uploadImageAction: `${import.meta.env.VITE_APP_BASE_API}/admin/common/upload/oss/image`,
    uploadVideoAction: `${import.meta.env.VITE_APP_BASE_API}/admin/common/upload/oss/video`,
});

const {
    loading, multiple, queryParams, list, total,
    dialog, formData, rules, uploadImageAction, uploadVideoAction,
} = toRefs(state);

const uploadHeaders = computed(() => {
    const token = getAccessToken();
    return token ? { Authorization: token } : {};
});

function handleQuery() {
    state.loading = true;
    headerList(state.queryParams).then(({ data }) => {
        state.list = data.content;
        state.total = data.totalElements;
        state.loading = false;
    });
}

function handleSelectionChange(selection: any) {
    state.ids = selection.map((item: any) => item.id);
    state.multiple = !selection.length;
}

function resetFormData() {
    state.formData = emptyForm();
    state.selectedInternalUri = "/";
    state.customLinkUrl = "";
}

function handleAdd() {
    state.dialog = { title: "添加Header", visible: true };
    resetFormData();
}

function viewEdit(row: any) {
    state.dialog = { title: "查看/编辑", visible: true };
    state.formData = {
        id: row.id,
        title: row.title,
        mediaType: row.mediaType || "image",
        displayType: row.displayType ?? 0,
        mediaUrl: row.mediaUrl || "",
        dayMediaUrl: row.dayMediaUrl || "",
        nightMediaUrl: row.nightMediaUrl || "",
        linkType: row.linkType,
        linkUrl: row.linkUrl,
        sort: row.sort,
        status: row.status,
        startTime: row.startTime || "",
        endTime: row.endTime || "",
    };
    if (row.linkType === "internal") {
        const preset = internalUriOptions.find(
            (o) => o.value === row.linkUrl && o.value !== "__custom__"
        );
        state.selectedInternalUri = preset ? row.linkUrl : "__custom__";
        state.customLinkUrl = preset ? "" : row.linkUrl;
    }
}

function onMediaTypeChange() {
    state.formData.mediaUrl = "";
    state.formData.dayMediaUrl = "";
    state.formData.nightMediaUrl = "";
}

function onDisplayTypeChange() {
    state.formData.mediaUrl = "";
    state.formData.dayMediaUrl = "";
    state.formData.nightMediaUrl = "";
}

function onLinkTypeChange() {
    state.selectedInternalUri = "/";
    state.customLinkUrl = "";
    state.formData.linkUrl = state.formData.linkType === "internal" ? "/" : "";
}

function onInternalUriChange(val: string) {
    if (val !== "__custom__") {
        state.formData.linkUrl = val;
        state.customLinkUrl = "";
    } else {
        state.formData.linkUrl = state.customLinkUrl;
    }
}

function onCustomUriInput(val: string) {
    state.formData.linkUrl = val;
}

function submitFormData() {
    // 手动校验媒体地址
    if (state.formData.displayType === 0 && !state.formData.mediaUrl) {
        ElMessage.error("请上传通用媒体文件或填写媒体地址");
        return;
    }
    if (state.formData.displayType === 1) {
        if (!state.formData.dayMediaUrl) {
            ElMessage.error("请上传日间媒体文件或填写日间地址");
            return;
        }
        if (!state.formData.nightMediaUrl) {
            ElMessage.error("请上传夜间媒体文件或填写夜间地址");
            return;
        }
    }
    dataFormRef.value.validate((valid: any) => {
        if (valid) {
            loading.value = true;
            const action = state.formData.id ? updateHeader : createHeader;
            const msg = state.formData.id ? "修改成功" : "添加成功";
            action(state.formData).then(() => {
                ElMessage.success(msg);
                cancel();
                handleQuery();
                loading.value = false;
            });
        }
    });
}

function cancel() {
    dialog.value.visible = false;
    resetFormData();
    dataFormRef.value.resetFields();
    dataFormRef.value.clearValidate();
}

function handleDelete() {
    const ids = state.ids.join(",");
    ElMessageBox.confirm(`确认删除已选中的 ${state.ids.length} 条数据?`, "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
    })
        .then(() => deleteHeader({ ids }).then(() => { ElMessage.success("删除成功"); handleQuery(); }))
        .catch(() => ElMessage.info("已取消删除"));
}

function handleToggleStatus(row: any) {
    const isEnable = row.status === 0;
    ElMessageBox.confirm(`确认${isEnable ? "启用" : "禁用"}该Header?`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
    })
        .then(() => (isEnable ? enableHeader : disableHeader)({ id: row.id })
            .then(() => { ElMessage.success(`${isEnable ? "启用" : "禁用"}成功`); handleQuery(); }))
        .catch(() => {});
}

const beforeImgUpload: UploadProps["beforeUpload"] = (rawFile) => {
    if (!["image/jpeg", "image/png", "image/bmp", "image/gif"].includes(rawFile.type)) {
        ElMessage.error("请上传图片格式文件");
        return false;
    }
    if (rawFile.size / 1024 / 1024 > 10) {
        ElMessage.error("图片大小不能超过 10MB");
        return false;
    }
    return true;
};

const beforeVideoUpload: UploadProps["beforeUpload"] = (rawFile) => {
    if (!["image/webp"].includes(rawFile.type)) {
        ElMessage.error("请上传 webp 格式文件");
        return false;
    }
    if (rawFile.size / 1024 / 1024 > 200) {
        ElMessage.error("视频大小不能超过 200MB");
        return false;
    }
    return true;
};

function makeUploadSuccess(field: "mediaUrl" | "dayMediaUrl" | "nightMediaUrl"): UploadProps["onSuccess"] {
    return (response) => {
        const res = typeof response === "string" ? JSON.parse(response) : response;
        if (res.code === 0) {
            (state.formData as any)[field] = res.data;
        } else {
            ElMessage.error("上传失败: " + res.message);
        }
    };
}

const handleMediaSuccess = makeUploadSuccess("mediaUrl");
const handleDayMediaSuccess = makeUploadSuccess("dayMediaUrl");
const handleNightMediaSuccess = makeUploadSuccess("nightMediaUrl");
const errorUpload = () => ElMessage.error("上传失败");

onMounted(() => { handleQuery(); });
</script>

<template>
    <div class="app-container">
        <!-- 操作栏 -->
        <el-form ref="queryFormRef" :model="queryParams" :inline="true">
            <el-form-item>
                <el-button type="success" :icon="Plus" @click="handleAdd">添加</el-button>
                <el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
            </el-form-item>
        </el-form>

        <!-- 数据表格 -->
        <el-table
            ref="dataTableRef"
            v-loading="loading"
            :data="list"
            @selection-change="handleSelectionChange"
            highlight-current-row
            border
        >
            <el-table-column type="selection" width="55" align="center" />
            <el-table-column label="ID" prop="id" width="70" align="center" />
            <el-table-column label="媒体预览" width="140" align="center">
                <template #default="scope">
                    <template v-if="scope.row.displayType === 1">
                        <div class="preview-pair">
                            <div class="preview-pair-item">
                                <span class="preview-label">日</span>
                                <el-image :src="scope.row.dayMediaUrl" class="table-preview-img"
                                    :preview-src-list="[scope.row.dayMediaUrl]" preview-teleported />
                            </div>
                            <div class="preview-pair-item">
                                <span class="preview-label night">夜</span>
                                <el-image :src="scope.row.nightMediaUrl" class="table-preview-img"
                                    :preview-src-list="[scope.row.nightMediaUrl]" preview-teleported />
                            </div>
                        </div>
                    </template>
                    <template v-else>
                        <el-image :src="scope.row.mediaUrl" class="table-preview-img"
                            :preview-src-list="[scope.row.mediaUrl]" preview-teleported />
                    </template>
                </template>
            </el-table-column>
            <el-table-column label="标题" prop="title" align="center" min-width="100" />
            <el-table-column label="媒体类型" width="90" align="center">
                <template #default="scope">
                    <el-tag :type="scope.row.mediaType === 'video' ? 'warning' : 'primary'">
                        {{ scope.row.mediaType === "video" ? "视频" : "图片" }}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column label="展示类型" width="110" align="center">
                <template #default="scope">
                    <el-tag :type="scope.row.displayType === 1 ? 'warning' : 'success'">
                        {{ scope.row.displayType === 1 ? "日间/夜间" : "通用" }}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column label="跳转类型" width="100" align="center">
                <template #default="scope">
                    <el-tag :type="scope.row.linkType === 'internal' ? 'primary' : 'warning'">
                        {{ scope.row.linkType === "internal" ? "内部页面" : "外部网页" }}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column label="跳转地址" prop="linkUrl" align="center" show-overflow-tooltip />
            <el-table-column label="排序" prop="sort" width="70" align="center" />
            <el-table-column label="状态" width="80" align="center">
                <template #default="scope">
                    <el-tag :type="scope.row.status === 1 ? 'success' : 'info'">
                        {{ scope.row.status === 1 ? "启用" : "禁用" }}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column label="有效时间" min-width="160" align="center">
                <template #default="scope">
                    <p v-if="scope.row.startTime">开始：{{ scope.row.startTime }}</p>
                    <p v-if="scope.row.endTime">结束：{{ scope.row.endTime }}</p>
                    <span v-if="!scope.row.startTime && !scope.row.endTime">不限</span>
                </template>
            </el-table-column>
            <el-table-column label="创建时间" prop="createTime" width="160" align="center" />
            <el-table-column label="操作" align="center" width="180" fixed="right">
                <template #default="scope">
                    <el-button type="primary" size="small" @click.stop="viewEdit(scope.row)">编辑</el-button>
                    <el-button
                        :type="scope.row.status === 1 ? 'warning' : 'success'"
                        size="small"
                        @click.stop="handleToggleStatus(scope.row)"
                    >{{ scope.row.status === 1 ? "禁用" : "启用" }}</el-button>
                </template>
            </el-table-column>
        </el-table>

        <!-- 分页 -->
        <pagination
            v-if="total > 0"
            :total="total"
            v-model:page="queryParams.pageNo"
            v-model:limit="queryParams.pageSize"
            @pagination="handleQuery"
        />

        <!-- 表单弹窗 -->
        <el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" destroy-on-close>
            <el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">

                <el-form-item label="Header标题" prop="title">
                    <el-input v-model="formData.title" placeholder="请输入Header标题" />
                </el-form-item>

                <el-form-item label="媒体类型" prop="mediaType">
                    <el-radio-group v-model="formData.mediaType" @change="onMediaTypeChange">
                        <el-radio label="image">图片</el-radio>
                        <el-radio label="video">视频</el-radio>
                    </el-radio-group>
                </el-form-item>

                <el-form-item label="展示类型" prop="displayType">
                    <el-radio-group v-model="formData.displayType" @change="onDisplayTypeChange">
                        <el-radio :label="0">通用</el-radio>
                        <el-radio :label="1">日间/夜间</el-radio>
                    </el-radio-group>
                    <div class="media-tip">
                        通用：上传一个文件供所有模式使用；日间/夜间：分别上传日间和夜间各一个文件
                    </div>
                </el-form-item>

                <!-- ===== 通用模式 ===== -->
                <template v-if="formData.displayType === 0">
                    <el-form-item label="上传媒体" prop="mediaUrl">
                        <el-upload
                            :action="formData.mediaType === 'video' ? uploadVideoAction : uploadImageAction"
                            :headers="uploadHeaders"
                            :show-file-list="false"
                            :before-upload="formData.mediaType === 'video' ? beforeVideoUpload : beforeImgUpload"
                            :on-success="handleMediaSuccess"
                            :on-error="errorUpload"
                        >
                            <template v-if="formData.mediaUrl">
                                <img :src="formData.mediaUrl" class="media-preview-img" />
                            </template>
                            <el-button v-else size="default" :icon="UploadFilled">
                                上传{{ formData.mediaType === "video" ? "视频" : "图片" }}
                            </el-button>
                        </el-upload>
                        <div class="media-tip" v-if="formData.mediaType === 'image'">支持 jpg/png，≤10MB</div>
                        <div class="media-tip" v-else>支持 webp，≤200MB</div>
                    </el-form-item>
                    <el-form-item label="媒体地址">
                        <el-input v-model="formData.mediaUrl" placeholder="上传后自动填入，也可手动填写URL" />
                    </el-form-item>
                </template>

                <!-- ===== 日间/夜间模式 ===== -->
                <template v-if="formData.displayType === 1">
                    <!-- 日间 -->
                    <el-form-item label="日间媒体">
                        <el-upload
                            :action="formData.mediaType === 'video' ? uploadVideoAction : uploadImageAction"
                            :headers="uploadHeaders"
                            :show-file-list="false"
                            :before-upload="formData.mediaType === 'video' ? beforeVideoUpload : beforeImgUpload"
                            :on-success="handleDayMediaSuccess"
                            :on-error="errorUpload"
                        >
                            <template v-if="formData.dayMediaUrl">
                                <img :src="formData.dayMediaUrl" class="media-preview-img" />
                            </template>
                            <el-button v-else size="default" :icon="UploadFilled">
                                上传日间{{ formData.mediaType === "video" ? "视频" : "图片" }}
                            </el-button>
                        </el-upload>
                    </el-form-item>
                    <el-form-item label="日间地址">
                        <el-input v-model="formData.dayMediaUrl" placeholder="上传后自动填入，也可手动填写URL" />
                    </el-form-item>

                    <!-- 夜间 -->
                    <el-form-item label="夜间媒体">
                        <el-upload
                            :action="formData.mediaType === 'video' ? uploadVideoAction : uploadImageAction"
                            :headers="uploadHeaders"
                            :show-file-list="false"
                            :before-upload="formData.mediaType === 'video' ? beforeVideoUpload : beforeImgUpload"
                            :on-success="handleNightMediaSuccess"
                            :on-error="errorUpload"
                        >
                            <template v-if="formData.nightMediaUrl">
                                <img :src="formData.nightMediaUrl" class="media-preview-img" />
                            </template>
                            <el-button v-else size="default" :icon="UploadFilled">
                                上传夜间{{ formData.mediaType === "video" ? "视频" : "图片" }}
                            </el-button>
                        </el-upload>
                    </el-form-item>
                    <el-form-item label="夜间地址">
                        <el-input v-model="formData.nightMediaUrl" placeholder="上传后自动填入，也可手动填写URL" />
                    </el-form-item>
                </template>

                <!-- 跳转类型 -->
                <el-form-item label="跳转类型" prop="linkType">
                    <el-radio-group v-model="formData.linkType" @change="onLinkTypeChange">
                        <el-radio label="internal">APP内部页面</el-radio>
                        <el-radio label="external">外部网页</el-radio>
                    </el-radio-group>
                </el-form-item>

                <el-form-item v-if="formData.linkType === 'internal'" label="内部页面" prop="linkUrl">
                    <el-select v-model="state.selectedInternalUri" placeholder="请选择跳转页面"
                        style="width: 100%" @change="onInternalUriChange">
                        <el-option v-for="item in internalUriOptions" :key="item.value"
                            :label="item.label" :value="item.value" />
                    </el-select>
                    <el-input v-if="state.selectedInternalUri === '__custom__'"
                        v-model="state.customLinkUrl"
                        placeholder="请输入自定义 URI，如 /futures/SOLUSDT"
                        style="margin-top: 8px"
                        @input="onCustomUriInput" />
                    <div class="uri-tip" v-if="formData.linkUrl">当前地址：<b>{{ formData.linkUrl }}</b></div>
                </el-form-item>

                <el-form-item v-if="formData.linkType === 'external'" label="外部链接" prop="linkUrl">
                    <el-input v-model="formData.linkUrl" placeholder="请输入完整URL，如 https://example.com" />
                </el-form-item>

                <el-form-item label="排序" prop="sort">
                    <el-input-number v-model="formData.sort" :min="0" :max="9999" />
                    <span class="sort-tip">数值越大越靠前</span>
                </el-form-item>

                <el-form-item label="状态" prop="status">
                    <el-radio-group v-model="formData.status">
                        <el-radio :label="1">启用</el-radio>
                        <el-radio :label="0">禁用</el-radio>
                    </el-radio-group>
                </el-form-item>

                <el-form-item label="开始时间" prop="startTime">
                    <el-date-picker v-model="formData.startTime" style="width: 100%"
                        format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
                        type="datetime" placeholder="不填则不限制开始时间" clearable />
                </el-form-item>

                <el-form-item label="结束时间" prop="endTime">
                    <el-date-picker v-model="formData.endTime" style="width: 100%"
                        format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
                        type="datetime" placeholder="不填则不限制结束时间" clearable />
                </el-form-item>
            </el-form>

            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="submitFormData">确 定</el-button>
                    <el-button @click="cancel">取 消</el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>

<style lang="scss" scoped>
.table-preview-img {
    width: 80px;
    height: 44px;
    object-fit: cover;
}
.table-preview-video {
    width: 80px;
    height: 44px;
    object-fit: cover;
}
.preview-pair {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.preview-pair-item {
    display: flex;
    align-items: center;
    gap: 4px;
}
.preview-label {
    font-size: 11px;
    color: #fff;
    background: #409eff;
    border-radius: 2px;
    padding: 1px 4px;
    flex-shrink: 0;
}
.preview-label.night {
    background: #606266;
}
.media-preview-img {
    max-width: 220px;
    max-height: 90px;
    object-fit: contain;
    display: block;
}
.media-preview-video {
    max-width: 260px;
    max-height: 146px;
    display: block;
}
.media-tip {
    color: #999;
    font-size: 12px;
    margin-top: 4px;
}
.sort-tip {
    color: #999;
    font-size: 12px;
    margin-left: 8px;
}
.uri-tip {
    color: #666;
    font-size: 12px;
    margin-top: 4px;
}
</style>
