<template>
    <div class="fulfill-path-page">
        <div class="page-header">
            <div class="header-content">
                <div class="header-title">服务进度</div>
            </div>
            <div class="order-info" v-if="orderCode">
                <span class="order-no-label">订单号</span>
                <span class="order-no-value">{{ orderCode }}</span>
            </div>
        </div>

        <div class="page-body" v-loading="loading">
            <div v-if="!loading && progressSteps.length === 0" class="empty-state">
                <div class="empty-icon">
                    <el-icon :size="48" color="#c0c4cc">
                        <Clock />
                    </el-icon>
                </div>
                <div class="empty-title">暂无服务进度</div>
                <div class="empty-desc">履约者接单后将在此记录服务进度</div>
            </div>

            <div class="timeline-wrapper" v-else>
                <div class="timeline">
                    <div v-for="(step, index) in progressSteps" :key="index" class="timeline-item"
                        :class="{ 'is-last': index === progressSteps.length - 1 }">
                        <div class="timeline-dot-wrapper">
                            <div class="timeline-dot" :style="{ borderColor: step.color }">
                                <el-icon v-if="step.done" :size="14" :color="step.color">
                                    <CircleCheck />
                                </el-icon>
                                <span v-else class="dot-inner" :style="{ background: step.color }"></span>
                            </div>
                            <div v-if="index < progressSteps.length - 1" class="timeline-line"></div>
                        </div>

                        <div class="timeline-content">
                            <div class="step-time">{{ step.time }}</div>
                            <div class="step-card">
                                <h4 class="step-title">{{ step.title }}</h4>
                                <p class="step-desc" v-if="step.desc">{{ step.desc }}</p>
                                <div class="step-media" v-if="step.media && step.media.length">
                                    <div v-for="(item, i) in step.media" :key="i" class="media-item">
                                        <el-image v-if="item.type === 'image'" :src="item.url"
                                            :preview-src-list="step.media.filter(m => m.type === 'image').map(m => m.url)"
                                            fit="cover" class="media-img" :preview-teleported="true" />
                                        <div v-else-if="item.type === 'video'" class="media-video"
                                            @click="openVideo(item.url)">
                                            <video :src="item.url" preload="metadata" class="media-img"></video>
                                            <div class="video-play-icon">
                                                <el-icon :size="28" color="#fff">
                                                    <VideoPlay />
                                                </el-icon>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <el-dialog v-model="videoVisible" title="视频播放" :close-on-click-modal="false" append-to-body
            @closed="videoUrl = ''">
            <div class="video-preview-box">
                <video v-if="videoUrl" :src="videoUrl" controls autoplay style="width: 100%; max-height: 60vh;"></video>
            </div>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch } from 'vue';
import { useRoute } from 'vue-router';
import { Clock, CircleCheck, VideoPlay } from '@element-plus/icons-vue';
import { listSubOrderLog } from '@/api/order/subOrderLog/index';
import { getSubOrderInfo } from '@/api/order/subOrder/index';

const route = useRoute();

const loading = ref(false);
const orderCode = ref('');
const videoVisible = ref(false);
const videoUrl = ref('');

interface MediaItem {
    type: 'image' | 'video';
    url: string;
}

interface ProgressStep {
    title: string;
    time: string;
    desc: string;
    color: string;
    done: boolean;
    media: MediaItem[];
}

const progressSteps = ref<ProgressStep[]>([]);

const videoExts = ['.mp4', '.mov', '.avi', '.wmv', '.webm', '.ogg'];

const isVideo = (url: string): boolean => {
    if (!url) return false;
    return videoExts.some(ext => String(url).toLowerCase().trim().endsWith(ext));
};

const openVideo = (url: string) => {
    videoUrl.value = url;
    videoVisible.value = true;
};

const fetchProgress = async (id: string) => {
    loading.value = true;
    try {
        const [logRes, orderRes] = await Promise.all([
            listSubOrderLog({ orderId: id }),
            getSubOrderInfo(id)
        ]);

        const list = logRes?.data?.data || logRes?.data || [];
        const arr = Array.isArray(list) ? list : [];
        const fLogs = arr.filter((i: any) => Number(i?.logType) === 1);

        progressSteps.value = fLogs.map((i: any) => {
            const urls = i?.photoUrls || [];
            const media: MediaItem[] = Array.isArray(urls)
                ? urls.map((u: string) => ({ type: isVideo(u) ? 'video' : 'image', url: u }))
                : [];
            const isCompleted = i.step === 4 || i.step === 99;
            return {
                title: i?.title || '--',
                time: i?.createTime || i?.time || '',
                desc: i?.content || '',
                color: isCompleted ? '#67c23a' : '#ff9900',
                done: isCompleted,
                media
            };
        });

        if (orderRes?.data) {
            orderCode.value = orderRes.data.code || '';
        }
    } catch {
        progressSteps.value = [];
    } finally {
        loading.value = false;
    }
};

watch(() => route.query.orderId, (val) => {
    if (val) {
        fetchProgress(String(val));
    }
}, { immediate: true });

onMounted(() => {
    const id = route.query.orderId;
    if (id) {
        fetchProgress(String(id));
    }
});
</script>

<style scoped>
.fulfill-path-page {
    min-height: 100vh;
    background: #f5f7fa;
    font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}

.page-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: #fff;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

.header-content {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px 16px;
}

.header-title {
    font-size: 17px;
    font-weight: 600;
    color: #303133;
}

.order-info {
    padding: 10px 16px 14px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.order-no-label {
    font-size: 13px;
    color: #909399;
}

.order-no-value {
    font-size: 15px;
    font-weight: 500;
    color: #303133;
    word-break: break-all;
}

.page-body {
    padding: 16px;
    min-height: calc(100vh - 120px);
}

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 60px 20px;
    text-align: center;
}

.empty-icon {
    margin-bottom: 16px;
}

.empty-title {
    font-size: 16px;
    font-weight: 500;
    color: #909399;
    margin-bottom: 8px;
}

.empty-desc {
    font-size: 14px;
    color: #c0c4cc;
}

.timeline-wrapper {
    padding: 4px 0;
}

.timeline {
    padding-left: 0;
}

.timeline-item {
    display: flex;
    position: relative;
}

.timeline-dot-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 32px;
    flex-shrink: 0;
}

.timeline-dot {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 3px solid #ff9900;
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    z-index: 1;
}

.dot-inner {
    width: 10px;
    height: 10px;
    border-radius: 50%;
}

.timeline-line {
    width: 2px;
    flex: 1;
    min-height: 24px;
    background: #e4e7ed;
    margin: 4px 0;
}

.timeline-content {
    flex: 1;
    padding-left: 14px;
    padding-bottom: 28px;
    min-width: 0;
}

.step-time {
    font-size: 13px;
    color: #909399;
    margin-bottom: 10px;
}

.step-card {
    background: #fff;
    border-radius: 10px;
    padding: 16px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
}

.step-title {
    margin: 0 0 10px;
    font-size: 16px;
    font-weight: 600;
    color: #303133;
    line-height: 1.4;
}

.step-desc {
    margin: 0 0 14px;
    font-size: 14px;
    color: #606266;
    line-height: 1.7;
    word-break: break-word;
}

.step-media {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.media-item {
    flex-shrink: 0;
}

.media-img {
    width: 100px;
    height: 100px;
    border-radius: 6px;
    object-fit: cover;
    display: block;
    border: 1px solid #ebeef5;
}

.media-video {
    position: relative;
    width: 100px;
    height: 100px;
    border-radius: 6px;
    overflow: hidden;
    cursor: pointer;
}

.media-video video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.video-play-icon {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.3);
}

.video-preview-box {
    display: flex;
    justify-content: center;
    background: #000;
    border-radius: 4px;
    overflow: hidden;
}
</style>
