﻿<template>
    <view class="page-container">
        <NavBar :title="t('moldMaintain.moduleName')" />

        <view class="filter-bar">
            <view class="keyword-box">
                <input v-model="searchKeyword" class="keyword-input" :placeholder="t('moldMaintain.searchPlaceholder')"
                    :focus="keywordFocus" confirm-type="search" @blur="keywordFocus = false" @input="handleKeywordInput"
                    @confirm="handleSearch" />
            </view>
            <picker mode="selector" :range="jobStatusLabels" :value="jobStatusIndex" @change="onJobStatusChange">
                <view class="status-box">
                    <text class="status-box-text">{{ currentJobStatusLabel }}</text>
                    <uni-icons type="bottom" size="14" color="#9ca3af"></uni-icons>
                </view>
            </picker>
            <view class="reset-filter-btn" @click="resetFilters">{{ t('functionCommon.reset') }}</view>
        </view>

        <scroll-view scroll-y class="list-scroll" :scroll-top="scrollTop" @scroll="onScroll" @scrolltolower="loadMore"
            :lower-threshold="80">
            <view class="list-wrap">
                <view v-for="item in list" :key="item.id" class="task-card" @click="openDetail(item)">
                    <view class="card-header">
                        <view class="header-main">
                            <view class="header-left">
                                <text
                                    :class="['task-type-tag', String(item.planType) === '1' ? 'tag-inspect' : 'tag-maintain']">{{
                                    taskTypeText(item.planType) }}</text>
                                <text class="task-name">{{ textValue(item.planNo) }}</text>
                            </view>
                            <view class="header-tags">
                                <text :class="['record-tag', jobStatusClass(item.jobStatus)]">{{
                                    jobStatusText(item.jobStatus) }}</text>
                                <text :class="['record-tag', jobResultClass(item.jobResult)]">{{
                                    jobResultText(item.jobResult) }}</text>
                            </view>
                        </view>
                    </view>
                    <view class="card-body">
                        <view class="row">
                            <text class="label">{{ t('moldMaintain.moldName') }}</text>
                            <text class="value">{{ textValue(item.moldName) }}</text>
                        </view>
                        <view class="row">
                            <text class="label">{{ t('moldMaintain.template') }}</text>
                            <text class="value">{{ textValue(item.configName) }}</text>
                        </view>
                        <view class="row">
                            <text class="label">{{ t('moldMaintain.operator') }}</text>
                            <text class="value">{{ textValue(item.operatorName) }}</text>
                        </view>
                        <view class="row">
                            <text class="label">{{ t('moldMaintain.taskTime') }}</text>
                            <text class="value">{{ formatDateTime(item.taskTime) }}</text>
                        </view>
                    </view>

                </view>

                <view v-if="loading && pageNo === 1" class="hint">{{ t('functionCommon.loading') }}</view>
                <view v-else-if="!list.length" class="hint">{{ t('moldMaintain.empty') }}</view>
                <view v-else-if="loadingMore" class="hint">{{ t('functionCommon.loadingMore') }}</view>
                <view v-else-if="finished" class="hint">{{ t('functionCommon.noMoreData') }}</view>
            </view>
        </scroll-view>

        <view v-if="showGoTop" class="go-top-btn" @click="goTop">
            <uni-icons type="arrow-up" size="20" color="#1a3a5c"></uni-icons>
        </view>

        <view class="add-btn" @click="goAdd">
            <text class="add-icon">+</text>
        </view>
    </view>
</template>

<script setup>
import { computed, nextTick, ref } from 'vue'
import { onLoad, onReachBottom, onShow, onUnload } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import NavBar from '@/components/common/NavBar.vue'
import { getMoldCheckPage } from '@/api/mes/moldCheck'
import { DICT_TYPE, getDictLabel, initAllDict, useDict } from '@/utils/dict'

const { t } = useI18n()

const searchKeyword = ref('')
const selectedJobStatus = ref('0')
const list = ref([])
const loading = ref(false)
const loadingMore = ref(false)
const finished = ref(false)
const pageNo = ref(1)
const pageSize = ref(10)
const scrollTop = ref(0)
const showGoTop = ref(false)
const keywordFocus = ref(false)

let searchTimer = null

// 浠庡瓧鍏歌幏鍙栦綔涓氱姸鎬侀€夐」
const { job_status: jobStatusDictOptions } = useDict(DICT_TYPE.JOB_STATUS)

const jobStatusOptions = computed(() => {
    const dictList = jobStatusDictOptions.value || []
    return [
        { label: t('functionCommon.all'), value: '' },
        ...dictList.map((item) => ({ label: item.label, value: item.value }))
    ]
})

const jobStatusLabels = computed(() => jobStatusOptions.value.map((item) => item.label))
const jobStatusIndex = computed(() => {
    const index = jobStatusOptions.value.findIndex((item) => item.value === selectedJobStatus.value)
    return index >= 0 ? index : 0
})
const currentJobStatusLabel = computed(() => {
    const current = jobStatusOptions.value.find((item) => item.value === selectedJobStatus.value)
    return current ? current.label : t('functionCommon.all')
})

onLoad(async () => {
    await initAllDict()
    await fetchList(true)
})

onShow(() => {
    activateKeywordFocus()
    if (uni.getStorageSync('moldMaintainListNeedRefresh') === '1') {
        uni.removeStorageSync('moldMaintainListNeedRefresh')
        fetchList(true)
    }
})

onUnload(() => {
    clearSearchTimer()
})

function normalizePageData(res) {
    const root = res && res.data !== undefined ? res.data : res
    const candidateList = root?.list || root?.rows || root?.records || root?.data?.list || root?.data?.rows || root?.data?.records || []
    const candidateTotal = root?.total ?? root?.data?.total ?? (Array.isArray(candidateList) ? candidateList.length : 0)
    return {
        list: Array.isArray(candidateList) ? candidateList : [],
        total: Number(candidateTotal || 0)
    }
}

onReachBottom(() => {
    loadMore()
})

async function fetchList(reset) {
    if (reset) {
        pageNo.value = 1
        finished.value = false
    }

    if (pageNo.value === 1) {
        loading.value = true
    } else {
        loadingMore.value = true
    }

    try {
        const params = {
            pageNo: pageNo.value,
            pageSize: pageSize.value,
            planNo: searchKeyword.value.trim() || undefined,
            planType: '2',
            jobStatus: selectedJobStatus.value || undefined
        }
        const res = await getMoldCheckPage(params)
        const page = normalizePageData(res)
        list.value = reset ? page.list : [...list.value, ...page.list]
        finished.value = list.value.length >= page.total || page.list.length < pageSize.value
    } catch (error) {
        if (!reset) pageNo.value = Math.max(1, pageNo.value - 1)
        uni.showToast({ title: t('functionCommon.loadFailed'), icon: 'none' })
    } finally {
        loading.value = false
        loadingMore.value = false
    }
}

function handleSearch() {
    clearSearchTimer()
    uni.hideKeyboard()
    fetchList(true)
}

function handleKeywordInput() {
    clearSearchTimer()
    searchTimer = setTimeout(() => {
        fetchList(true)
    }, 300)
}

async function resetFilters() {
    clearSearchTimer()
    searchKeyword.value = ''
    selectedJobStatus.value = '0'
    activateKeywordFocus()
    await nextTick()
    await fetchList(true)
}

function onJobStatusChange(event) {
    const index = Number(event?.detail?.value || 0)
    selectedJobStatus.value = jobStatusOptions.value[index]?.value ?? ''
    fetchList(true)
}

async function loadMore() {
    if (loading.value || loadingMore.value || finished.value) return
    pageNo.value += 1
    await fetchList(false)
}

function openDetail(item) {
    if (!item?.id) {
        uni.showToast({ title: t('functionCommon.noIdView'), icon: 'none' })
        return
    }
    uni.setStorageSync('moldMaintainDetail', JSON.stringify(item))
    uni.navigateTo({
        url: `/pages_function/pages/moldMaintain/detail?id=${encodeURIComponent(String(item.id))}`
    })
}

function goAdd() {
  uni.navigateTo({
    url: '/pages_function/pages/moldMaintain/add'
  })
}

function onScroll(event) {
    showGoTop.value = (event?.detail?.scrollTop || 0) > 600
}

function goTop() {
    scrollTop.value = 0
}

function activateKeywordFocus() {
    keywordFocus.value = false
    nextTick(() => {
        keywordFocus.value = true
    })
}

function clearSearchTimer() {
    if (searchTimer) {
        clearTimeout(searchTimer)
        searchTimer = null
    }
}

function taskTypeText(value) {
    const normalized = String(value)
    if (normalized === '1') return t('moldMaintain.taskTypeInspect')
    if (normalized === '2') return t('moldMaintain.taskTypeMaintain')
    return textValue(value)
}

function jobStatusText(value) {
    return getDictLabel(DICT_TYPE.JOB_STATUS, value, textValue(value))
}

function jobStatusClass(value) {
    const normalized = String(value)
    if (normalized === '2') return 'text-primary'
    if (normalized === '1') return 'text-success'
    if (normalized === '3') return 'text-danger'
    if (normalized === '4') return 'text-muted'
    return 'text-warning'
}

function jobResultText(value) {
    const normalized = String(value).trim().toUpperCase()
    if (normalized === '1' || normalized === 'OK') return t('moldMaintain.jobResultOk')
    if (normalized === '2' || normalized === 'NG') return t('moldMaintain.jobResultNg')
    if (!normalized || normalized === '0') return '-'
    return textValue(value)
}

function jobResultClass(value) {
    const normalized = String(value).trim().toUpperCase()
    if (normalized === '1' || normalized === 'OK') return 'text-success'
    if (normalized === '2' || normalized === 'NG') return 'text-danger'
    return ''
}

function textValue(value) {
    if (value === 0) return '0'
    if (value === null || value === undefined) return '-'
    const text = String(value).trim()
    return text || '-'
}

function formatDateTime(value) {
    if (!value) return '-'
    if (Array.isArray(value) && value.length >= 3) {
        const [year, month, day, hour = 0, minute = 0, second = 0] = value
        const pad = (num) => String(num).padStart(2, '0')
        return `${year}-${pad(month)}-${pad(day)} ${pad(hour)}:${pad(minute)}:${pad(second)}`
    }
    const date = new Date(Number(value))
    if (Number.isNaN(date.getTime())) return textValue(value)
    const pad = (num) => String(num).padStart(2, '0')
    return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
}
</script>

<style lang="scss" scoped>
.page-container {
    min-height: 100vh;
    background: #f4f5f7;
}

.filter-bar {
    display: flex;
    align-items: center;
    gap: 12rpx;
    padding: 18rpx 4rpx 0rpx;
}

.keyword-box,
.status-box,
.reset-filter-btn {
    min-width:100rpx;
    height: 66rpx;
    background: #ffffff;
    border: 1rpx solid #d9dde5;
    box-sizing: border-box;
    display: flex;
    align-items: center;
}

.keyword-box {
    flex: 1;
    min-width: 0;
    padding: 0 28rpx;
}

.keyword-input {
    width: 100%;
    font-size: 24rpx;
    color: #374151;
}

.status-box {
    flex-shrink: 0;
    justify-content: space-between;
    padding: 0 28rpx;
    min-width: 160rpx;
}

.status-box-text {
    font-size: 24rpx;
    color: #374151;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.reset-filter-btn {
    justify-content: center;
    font-size: 24rpx;
    color: #4b5563;
}

.list-scroll {
    height: calc(100vh - 194rpx);
}

.list-wrap {
    padding: 0 4rpx 140rpx;
}

.task-card {
    position: relative;
    margin-top: 20rpx;
    padding: 28rpx;
    background: #fff;
    border-radius: 22rpx;
    box-shadow: 0 8rpx 28rpx rgba(15, 23, 42, 0.06);
}

.card-header {
    margin-bottom: 18rpx;
}

.header-main {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16rpx;
}

.header-left {
    min-width: 0;
    flex: 1;
}

.header-tags {
    display: flex;
    align-items: center;
    gap: 12rpx;
    flex-shrink: 0;
}

.task-name {
    flex: 1;
    font-size: 32rpx;
    font-weight: 700;
    color: #0f172a;
    margin-left: 12rpx
}

.task-type-tag {
    padding: 8rpx 18rpx;
    border-radius: 8rpx;
    font-size: 22rpx;
}

.record-tag {
    padding: 8rpx 18rpx;
    border-radius: 999rpx;
    font-size: 22rpx;
    line-height: 1;
    background: #e2e8f0;
    color: #64748b;
}

.tag-inspect {
    color: #1d4ed8;
    background: #dbeafe;
}

.tag-maintain {
    color: #15803d;
    background: #dcfce7;
}

.card-body .row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 20rpx;
}

.label {
    width: 180rpx;
    font-size: 25rpx;
    color: #94a3b8;
}

.value {
    flex: 1;
    text-align: right;
    font-size: 27rpx;
    color: #334155;
    line-height: 1.5;
}

.text-success {
    color: #16a34a;
}

.text-danger {
    color: #dc2626;
}

.text-warning {
    color: #f59e0b;
}

.text-primary {
    color: #2563eb;
}

.text-muted {
    color: #94a3b8;
}

.record-tag.text-success {
    color: #15803d;
    background: #dcfce7;
}

.record-tag.text-danger {
    color: #dc2626;
    background: #fee2e2;
}

.record-tag.text-warning {
    color: #d97706;
    background: #fef3c7;
}

.record-tag.text-primary {
    color: #1d4ed8;
    background: #dbeafe;
}

.record-tag.text-muted {
    color: #64748b;
    background: #e2e8f0;
}

.hint {
    padding: 36rpx 0;
    text-align: center;
    color: #94a3b8;
    font-size: 26rpx;
}

.go-top-btn {
    position: fixed;
    right: 28rpx;
    bottom: calc(140rpx + env(safe-area-inset-bottom));
    width: 88rpx;
    height: 88rpx;
    border-radius: 44rpx;
    background: rgba(255, 255, 255, 0.96);
    box-shadow: 0 8rpx 24rpx rgba(15, 23, 42, 0.12);
    display: flex;
    align-items: center;
    justify-content: center;
}

.add-btn,
.go-top-btn {
    position: fixed;
    right: 32rpx;
    width: 92rpx;
    height: 92rpx;
    border-radius: 46rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 14rpx 30rpx rgba(24, 63, 108, 0.24);
}

.add-btn {
    right: 28rpx;
    bottom: calc(56rpx + env(safe-area-inset-bottom));
    background: #1f4b79;
}

.add-icon {
    color: #ffffff;
    font-size: 64rpx;
    line-height: 1;
    margin-top: -4rpx;
}
</style>
