<template>
    <view class="dw-page">
        <!-- 装饰背景 -->
        <view class="bg-decor bg-decor-a"></view>
        <view class="bg-decor bg-decor-b"></view>

        <!-- 顶部条 -->
        <view class="top">
            <view class="top-back" @click="handleBack">
                <view class="back-arrow"></view>
            </view>
            <view v-if="!isCropperActive" class="top-title">
                <text class="ellipsis">{{ title }}</text>
            </view>
            <view
                v-if="!pageLoading && !isCropperActive"
                class="top-meta"
                :style="{ paddingRight: menuButtonRightRpx + 'rpx' }"
            >
                <view class="top-progress">
                    <text class="cur">{{ activeIdx + 1 }}</text>
                    <text class="divider">/</text>
                    <text class="total">{{ paperList.length }}</text>
                </view>
                <view class="top-clock">
                    <image class="clock-icon" src="/static/image/svg/time.svg" mode="aspectFit" />
                    <text>{{ timeFilter }}</text>
                </view>
            </view>
        </view>

        <!-- 主体 -->
        <view v-if="!pageLoading" class="main">
            <view class="book-box">
                <Question
                    v-if="paperList.length && paperList[activeIdx]"
                    :key="`question-${activeIdx}-${paperList[activeIdx]?.id ?? ''}`"
                    :data="paperList[activeIdx]"
                    :idx="activeIdx + 1"
                    :total="paperList.length"
                    :resourceType="resourceType"
                    :reportFlag="reportFlag"
                    :subjectId="paperInfo.subjectId"
                    @submit="submitQuestion"
                    @cropper-visible-change="onCropperVisibleChange"
                />
            </view>

            <!-- 底部题号 + 操作 -->
            <view class="bottom">
                <scroll-view class="indicator" scroll-x :show-scrollbar="false">
                    <view class="indicator-track">
                        <view
                            v-for="(item, idx) in paperList"
                            v-show="!item.unLook"
                            :key="item.id || idx"
                            :class="[
                                'indicator-item',
                                {
                                    active: activeIdx === idx,
                                    success: reportFlag && (item.correctResult || item.markFlag),
                                    error: reportFlag && !(item.correctResult || item.markFlag) && (item.submitAnswer || item.submitAnswerPic),
                                    empty: !reportFlag && !item.submitAnswer && !item.submitAnswerPic,
                                    answered: !reportFlag && (item.submitAnswer || item.submitAnswerPic),
                                },
                            ]"
                            @click="switchQuestion(idx)"
                        >
                            <text>{{ idx + 1 }}</text>
                        </view>
                    </view>
                </scroll-view>

                <view
                    v-if="!reportFlag"
                    :class="['btn-next', { disabled: submitLoading, submit: activeIdx >= paperList.length - 1 }]"
                    @click="handleNext"
                >
                    <text>{{ activeIdx < paperList.length - 1 ? '下一题' : '提交' }}</text>
                    <view class="btn-arrow">
                        <svg viewBox="0 0 16 16" fill="none">
                            <path d="m6 4 4 4-4 4" stroke="#FFFFFF" stroke-width="2"
                                stroke-linecap="round" stroke-linejoin="round" />
                        </svg>
                    </view>
                </view>
            </view>
        </view>

        <!-- 加载中 -->
        <view v-else class="loading-page">
            <Loading :text="reportFlag ? '正在加载报告中...' : '正在精选题目中...'" />
        </view>
    </view>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import {
    startExam,
    saveRecordAnswer,
    submitExam,
    getPaperRecordDetail,
} from '@/api/homework';
import {
    resource_type_homework,
    normalizeResourceType,
    isHomeworkExamResourceType,
} from '@/constants/doWork';
import Loading from '@/components/Loading/index.vue';
import Question from './components/Question.vue';

const pageLoading = ref(true);
const submitLoading = ref(false);
const menuButtonRightRpx = ref(0);
const isCropperActive = ref(false);

const paperList = ref<any[]>([]);
const paperInfo = ref<any>({});
const activeIdx = ref(0);

const reportFlag = ref<0 | 1>(0);
const params = ref<any>({});

let timer: any = null;
const initialIdx = ref(0);

const resourceType = computed(() =>
    normalizeResourceType(params.value.resourceType || paperInfo.value.resourceType),
);

const normalizePaperList = (list: any, markUnLook = false) => {
    if (!Array.isArray(list)) return [];
    if (!markUnLook) return list;
    return list.map((item: any, idx: number) => ({
        ...item,
        unLook: idx > 0,
    }));
};

const normalizeAnswerPic = (value: any) => String(value || '')
    .split(',')
    .map((url) => String(url || '').replace(/[`]/g, '').replace(/http:\/\//gi, 'https://').trim())
    .filter(Boolean)
    .join(',');

const isUploadImageQuestion = (item: any) => {
    const typeText = [
        item?.titleChannelTypeName,
        item?.channelTypeName,
        item?.typeName,
        item?.titleTypeName,
    ].filter(Boolean).join(',');
    return /上传|拍照/.test(typeText);
};

const extractPicLinksFromAnswer = (answer: any) => {
    const raw = String(answer || '');
    if (!raw) return '';
    const links = raw.match(/https?:\/\/[^\s,]+/g) || [];
    return normalizeAnswerPic(links.join(','));
};

const getSubmitAnswerPic = (item: any) => {
    const answerPic = normalizeAnswerPic(item?.submitAnswerPic);
    if (answerPic) return answerPic;
    if (!isUploadImageQuestion(item)) return '';
    return extractPicLinksFromAnswer(item?.submitAnswer);
};

const getQuestionKey = (item: any) => item?.id || item?.itemId || item?.jobStuTittleId || '';

const normalizeCurrentMultiAnswer = () => {
    const cur = paperList.value[activeIdx.value];
    if (!cur || cur.titleChannelTypeName !== '多选题') return;
    const raw = String(cur.submitAnswer || '');
    cur.submitAnswer = raw
        .split(',')
        .flatMap((item) => item.split(''))
        .map((item) => item.trim())
        .filter(Boolean)
        .sort()
        .join(',');
};

const title = computed(() => {
    const name = paperInfo.value.paperName;
    if (name) {
        return name.replace(/-\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/, '');
    }
    return '作业';
});

const timeFilter = computed(() => {
    const cost = paperInfo.value.costTime || 0;
    const h = Math.floor(cost / 3600);
    const m = Math.floor((cost % 3600) / 60);
    const s = cost % 60;
    if (h > 0) return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
    return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
});

onLoad((options: any) => {
    initialIdx.value = Number(options.idx) || 0;
    // 与 Web route.params.id 一致：带 id 时为查看报告
    if (options.id) {
        reportFlag.value = 1;
        params.value = {
            ...options,
            id: options.id,
            recordId: options.recordId || options.id,
            resourceType: normalizeResourceType(options.resourceType),
        };
    } else {
        reportFlag.value = Number(options.reportFlag || 0) as 0 | 1;
        params.value = {
            ...options,
            resourceType: normalizeResourceType(options.resourceType),
        };
        if (reportFlag.value === 1 && params.value.recordId && !params.value.id) {
            params.value.id = params.value.recordId;
        }
    }
    init();
});

const handleBack = () => {
    if (reportFlag.value) {
        uni.navigateBack();
        return;
    }
    uni.showModal({
        title: '提示',
        content: '是否确认退出，退出后不保留答题记录',
        confirmColor: '#4f46e5',
        success: (res) => {
            if (res.confirm) {
                clearTimer();
                uni.navigateBack();
            }
        },
    });
};

const switchQuestion = async (idx?: number) => {
    if (idx === activeIdx.value) {
        if (!reportFlag.value && isHomeworkExamResourceType(resourceType.value)) {
            await saveAnswer();
        }
        return;
    }
    if (idx !== undefined) {
        if (!reportFlag.value && isHomeworkExamResourceType(resourceType.value)) {
            normalizeCurrentMultiAnswer();
            await saveAnswer();
        }
        activeIdx.value = idx;
    } else if (activeIdx.value < paperList.value.length - 1) {
        if (!reportFlag.value && isHomeworkExamResourceType(resourceType.value)) {
            normalizeCurrentMultiAnswer();
            await saveAnswer();
        }
        activeIdx.value++;
    }
    if (!reportFlag.value && paperList.value[activeIdx.value]) {
        paperList.value[activeIdx.value].unLook = false;
    }
};

const handleNext = async () => {
    if (submitLoading.value) return;
    if (activeIdx.value < paperList.value.length - 1) {
        await switchQuestion();
    } else {
        if (paperList.value.some((i) => !i.submitAnswer && !i.submitAnswerPic)) {
            uni.showModal({
                title: '提示',
                content: '还有题目未作答，确定要提交答案吗？',
                confirmColor: '#4f46e5',
                success: (res) => {
                    if (res.confirm) submitTrain();
                },
            });
        } else {
            submitTrain();
        }
    }
};

const saveAnswer = async () => {
    const cur = paperList.value[activeIdx.value];
    if (!cur) return;
    try {
        await saveRecordAnswer({
            answer: cur.submitAnswer || '',
            answerPic: cur.submitAnswerPic || '',
            costTime: (paperInfo.value.costTime || 0) * 1000,
            itemId: getQuestionKey(cur),
            recordId: params.value.recordId,
        });
    } catch (err) {
        console.error('[doWork] save err', err);
    }
};

const submitQuestion = (answer: any) => {
    if (reportFlag.value) return;
    const idx = activeIdx.value;
    if (answer.submitAnswer !== undefined) {
        paperList.value[idx].submitAnswer = answer.submitAnswer;
    }
    if (answer.submitAnswerPic !== undefined) {
        paperList.value[idx].submitAnswerPic = answer.submitAnswerPic;
    }
    if (answer.toNext && activeIdx.value < paperList.value.length - 1) {
        setTimeout(() => switchQuestion(), 300);
    }
};

const onCropperVisibleChange = (visible: boolean) => {
    isCropperActive.value = !!visible;
};

const submitTrain = async () => {
    clearTimer();
    submitLoading.value = true;
    uni.showLoading({ title: '提交中...', mask: true });
    try {
        normalizeCurrentMultiAnswer();
        await saveAnswer();
        await submitExam({
            answerDtoList: paperList.value.map((item) => ({
                itemId: getQuestionKey(item),
                answer: item.submitAnswer || '',
                answerPic: getSubmitAnswerPic(item),
            })),
            costTime: (paperInfo.value.costTime || 0) * 1000,
            recordId: params.value.recordId,
        });
        uni.hideLoading();
        uni.showModal({
            title: '提示',
            content: '试卷提交成功请等待批改',
            showCancel: false,
            confirmText: '好的',
            confirmColor: '#4f46e5',
            success: () => uni.navigateBack(),
        });
    } catch (err: any) {
        uni.hideLoading();
        uni.showToast({ title: err?.message || '提交失败', icon: 'none' });
        startTimer();
    } finally {
        submitLoading.value = false;
    }
};

const startTimer = (init?: boolean) => {
    clearTimer();
    if (init) paperInfo.value.costTime = 0;
    timer = setInterval(() => {
        paperInfo.value.costTime = (paperInfo.value.costTime || 0) + 1;
    }, 1000);
};

const clearTimer = () => {
    if (timer) {
        clearInterval(timer);
        timer = null;
    }
};

const initReport = async () => {
    const res = await getPaperRecordDetail({
        recordId: params.value.recordId || params.value.id,
        reportFlag: 1,
    });
    paperInfo.value = res.data;
    paperList.value = normalizePaperList(res.data?.titleVoList || res.data?.subjectTitleVoList);
};

const initNewTrain = async () => {
    if (resourceType.value !== resource_type_homework) {
        throw new Error('暂不支持该练习类型');
    }
    const res: any = await startExam(params.value.recordId);
    paperInfo.value = res.data || res;
    if (paperInfo.value.costTime) {
        paperInfo.value.costTime = Math.floor(paperInfo.value.costTime / 1000);
    }
    paperList.value = normalizePaperList(
        paperInfo.value?.titleVoList || paperInfo.value?.subjectTitleVoList || [],
        true,
    );
};

const getMenuButtonInfo = () => {
    try {
        // #ifdef MP-WEIXIN
        const m = uni.getMenuButtonBoundingClientRect();
        const sys = uni.getSystemInfoSync();
        if (m && sys) {
            const rightPx = sys.windowWidth - m.right;
            const widthPx = m.width;
            const pxToRpx = 750 / sys.windowWidth;
            menuButtonRightRpx.value = Math.ceil((rightPx + widthPx) * pxToRpx) + 16;
        } else {
            menuButtonRightRpx.value = 120;
        }
        // #endif
        // #ifndef MP-WEIXIN
        menuButtonRightRpx.value = 0;
        // #endif
    } catch {
        menuButtonRightRpx.value = 120;
    }
};

const init = async () => {
    try {
        pageLoading.value = true;
        if (reportFlag.value) {
            await initReport();
        } else {
            await initNewTrain();
            startTimer();
        }
        const target = Math.min(initialIdx.value, paperList.value.length - 1);
        activeIdx.value = Math.max(0, target);
        if (!reportFlag.value && paperList.value[activeIdx.value]) {
            paperList.value[activeIdx.value].unLook = false;
        }
    } catch (err: any) {
        console.error('[doWork] init err', err);
        uni.showToast({ title: err?.message || '加载失败', icon: 'none' });
        setTimeout(() => uni.navigateBack(), 1500);
    } finally {
        pageLoading.value = false;
    }
};

onMounted(() => {
    getMenuButtonInfo();
});

onUnmounted(() => {
    clearTimer();
    isCropperActive.value = false;
    paperInfo.value = {};
    paperList.value = [];
    activeIdx.value = 0;
});
</script>

<style lang="scss" scoped>
.dw-page {
    height: 100vh;
    width: 100vw;
    overflow: hidden;
    box-sizing: border-box;
    position: relative;
    background: #f5f7ff;
    display: flex;
    flex-direction: column;
}

/* 装饰背景 */
.bg-decor {
    position: absolute;
    border-radius: 50%;
    filter: blur(60rpx);
    pointer-events: none;
    z-index: 0;

    &-a {
        top: -80rpx;
        right: -80rpx;
        width: 280rpx;
        height: 280rpx;
        background: radial-gradient(circle, rgba(129, 140, 248, 0.35), transparent 70%);
    }

    &-b {
        bottom: -80rpx;
        left: -80rpx;
        width: 280rpx;
        height: 280rpx;
        background: radial-gradient(circle, rgba(34, 197, 94, 0.3), transparent 70%);
    }
}

/* 顶部条 */
.top {
    position: relative;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 3rpx 12rpx 2rpx;
    gap: 8rpx;
}

.top-back {
    width: 34rpx;
    height: 34rpx;
    flex-shrink: 0;
    background: #ffffff;
    border-radius: 10rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow:
        0 4rpx 10rpx rgba(99, 102, 241, 0.18),
        inset 0 -3rpx 0 rgba(199, 210, 254, 0.6);

    &:active {
        transform: scale(0.92);
    }
}

.back-arrow {
    width: 9rpx;
    height: 9rpx;
    border-left: 2rpx solid #4f46e5;
    border-bottom: 2rpx solid #4f46e5;
    transform: rotate(45deg);
    margin-left: 4rpx;
}

.top-title {
    flex: 1;
    min-width: 0;
    font-size: 17rpx;
    font-weight: 700;
    color: #312e81;
    text-align: center;

    text {
        max-width: 100%;
    }
}

.top-meta {
    display: flex;
    align-items: center;
    gap: 6rpx;
    flex-shrink: 0;
}

.top-progress {
    display: flex;
    align-items: baseline;
    gap: 2rpx;
    padding: 3rpx 10rpx;
    background: linear-gradient(180deg, #818cf8, #4f46e5);
    border-radius: 999rpx;
    color: #ffffff;
    box-shadow:
        0 4rpx 10rpx rgba(79, 70, 229, 0.3),
        inset 0 -3rpx 0 rgba(0, 0, 0, 0.12);

    .cur {
        font-size: 16rpx;
        font-weight: 800;
    }

    .divider {
        font-size: 11rpx;
        opacity: 0.6;
    }

    .total {
        font-size: 13rpx;
        opacity: 0.8;
    }
}

.top-clock {
    display: flex;
    align-items: center;
    gap: 4rpx;
    padding:  5rpx 10rpx;
    background: #ffffff;
    border-radius: 999rpx;
    box-shadow:
        0 4rpx 10rpx rgba(99, 102, 241, 0.15),
        inset 0 -3rpx 0 rgba(199, 210, 254, 0.5);

    .clock-icon {
        width: 17rpx;
        height: 17rpx;
        flex-shrink: 0;
    }

    text {
        font-size: 15rpx;
        font-weight: 700;
        color: #4f46e5;
        font-variant-numeric: tabular-nums;
        line-height: 20rpx;
        vertical-align: middle;
    }
}

/* 主体 */
.main {
    flex: 1;
    height: 0;
    position: relative;
    z-index: 1;
    padding: 0 10rpx;
    display: flex;
    flex-direction: column;
}

.book-box {
    flex: 1;
    overflow: hidden;
    position: relative;
}

.bottom {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 4rpx;
    padding: 3rpx 0 calc(6rpx + constant(safe-area-inset-bottom));
    padding: 3rpx 0 calc(6rpx + env(safe-area-inset-bottom));
    box-sizing: border-box;
}

.indicator {
    flex: 1;
    width: 0;
    height: 40rpx;
    white-space: nowrap;
}

.indicator-track {
    display: inline-flex;
    align-items: center;
    gap: 5rpx;
    padding: 4rpx 0;
}

.indicator-item {
    flex-shrink: 0;
    width: 31rpx;
    height: 31rpx;
    background: #ffffff;
    border-radius: 9rpx;
    border: 2rpx solid transparent;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow:
        0 4rpx 8rpx rgba(99, 102, 241, 0.12),
        inset 0 -3rpx 0 rgba(199, 210, 254, 0.5);
    transition: all 150ms ease;

    text {
        font-size: 15rpx;
        font-weight: 700;
        color: #6366f1;
    }

    &.answered {
        background: linear-gradient(180deg, #c7d2fe, #818cf8);

        text {
            color: #ffffff;
        }
    }

    &.empty {
        background: #f1f5f9;
        box-shadow: inset 0 2rpx 4rpx rgba(0, 0, 0, 0.05);

        text {
            color: #94a3b8;
        }
    }

    &.success {
        background: linear-gradient(180deg, #4ade80, #16a34a);
        box-shadow:
            0 6rpx 12rpx rgba(22, 163, 74, 0.3),
            inset 0 -3rpx 0 rgba(0, 0, 0, 0.15);

        text {
            color: #ffffff;
        }
    }

    &.error {
        background: linear-gradient(180deg, #f87171, #dc2626);
        box-shadow:
            0 6rpx 12rpx rgba(220, 38, 38, 0.3),
            inset 0 -3rpx 0 rgba(0, 0, 0, 0.15);

        text {
            color: #ffffff;
        }
    }

    &.active {
        z-index: 1;
        transform: translateY(-2rpx);
        background: linear-gradient(180deg, #818cf8, #4f46e5);
        border-color: rgba(255, 255, 255, 0.9);
        box-shadow:
            0 8rpx 16rpx rgba(79, 70, 229, 0.45),
            0 0 0 3rpx rgba(129, 140, 248, 0.18),
            inset 0 -3rpx 0 rgba(0, 0, 0, 0.15);

        text {
            color: #ffffff;
        }
    }
}

.btn-next {
    flex-shrink: 0;
    height: 32rpx;
    padding: 0 14rpx;
    border-radius: 999rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6rpx;
    background: linear-gradient(180deg, #4ade80, #16a34a);
    color: #ffffff;
    box-shadow:
        0 6rpx 14rpx rgba(22, 163, 74, 0.35),
        inset 0 -3rpx 0 rgba(0, 0, 0, 0.15);
    transition: all 150ms ease;

    text {
        font-size: 15rpx;
        font-weight: 700;
        letter-spacing: 2rpx;
    }

    .btn-arrow {
        width: 15rpx;
        height: 15rpx;

        svg {
            width: 100%;
            height: 100%;
        }
    }

    &.submit {
        background: linear-gradient(180deg, #818cf8, #4f46e5);
        box-shadow:
            0 6rpx 14rpx rgba(79, 70, 229, 0.4),
            inset 0 -3rpx 0 rgba(0, 0, 0, 0.15);
    }

    &.disabled {
        opacity: 0.6;
    }

    &:active {
        transform: translateY(2rpx);
    }
}

/* 加载 */
.loading-page {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 1;
}
</style>
