<template>
    <div class="text-viewer" :class="{ 'full-screen': isFullscreen }">
        <!-- 在顶部添加控制按钮 -->
        <div class="controls">
            <!-- 在controls区块添加 -->
            <button @click="saveChanges" style="margin-right: 8px;">
                保存修改
            </button>
            <button @click="toggleFullscreen">
                {{ isFullscreen ? '退出全屏' : '全屏' }}
            </button>

        </div>
        <div v-if="error" class="error">{{ error }}</div>
        <div v-else>
            <div v-if="isLoading" class="loading">加载进度：{{ loadedPercent }}%</div>

            <div class="scroll-container" ref="scrollContainer" @scroll="handleScroll"
                :style="{ height: containerHeight + 'px' }">
                <div class="phantom" :style="{ height: totalHeight + 'px' }">
                    <div v-for="row in visibleRows" :key="row.index" class="row" :style="row.style">
                        <div v-for="(cell, i) in row.data" :key="i" class="cell">
                            <input :value="rawData[row.index][i]" @blur="(e) => handleEdit(row.index, i, e)"
                                class="edit-input">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script setup>
import { ref, reactive, computed, watch, onMounted, onBeforeUnmount } from 'vue';
import { apicontent, batchModify } from "@/api/datamanagement";
import { ElMessage } from "element-plus";
const props = defineProps({
    fileUrl: {
        type: String,
        required: true
    },
    rowId: {
        type: String,
        default: false
    },
});

// 配置项
const CHUNK_SIZE = 1024 * 1024; // 1MB分块处理
const ROW_HEIGHT = 40; // 行高
const VISIBLE_BUFFER = 200; // 可视区外缓冲行数

// 响应式状态
const isLoading = ref(false);
const error = ref(null);
const rawData = reactive([]); // 原始数据存储
const scrollTop = ref(0);
const totalRows = ref(0);
const reader = ref(null); // 保持reader引用
const loadedPercent = ref(0);
// 新增响应式状态
const isFullscreen = ref(false);

// 新增方法
const toggleFullscreen = () => {
    isFullscreen.value = !isFullscreen.value;

    // 可选：使用浏览器全屏API（根据需求选择其中一种方式）
    // if (isFullscreen.value && document.documentElement.requestFullscreen) {
    //   document.documentElement.requestFullscreen();
    // } else if (document.exitFullscreen) {
    //   document.exitFullscreen();
    // }
};

// 修改容器高度计算逻辑
const containerHeight = computed(() => {
    return isFullscreen.value ? window.innerHeight : window.innerHeight * 0.8;
});
const startIndex = computed(() =>
    Math.max(0, Math.floor(scrollTop.value / ROW_HEIGHT) - VISIBLE_BUFFER)
);
const endIndex = computed(() =>
    Math.min(totalRows.value, startIndex.value + Math.ceil(containerHeight.value / ROW_HEIGHT) + VISIBLE_BUFFER * 2)
);
const visibleRows = computed(() => {
    // console.log(rawData)
    return rawData.slice(startIndex.value, endIndex.value).map((row, index) => ({
        index: startIndex.value + index,
        data: row,
        style: {
            transform: `translateY(${(startIndex.value + index) * ROW_HEIGHT}px)`
        }
    }));
});
const totalHeight = computed(() => totalRows.value * ROW_HEIGHT);

// 方法
const handleScroll = (e) => {
    scrollTop.value = e.target.scrollTop;
};

const abortLoading = () => {
    if (reader.value) {
        reader.value.cancel();
        reader.value = null;
    }
};

const processChunk = (chunk, isFinal) => {
    const lines = chunk.split('\n');
    // const lines = chunk.split('\n').map(line => line.replace(/\t/g, ' ')); // 新增替换逻辑
    if (!isFinal) {
        // 保留未完成的行
        const lastLine = lines.pop() || '';
        rawData.push(...lines.filter(l => l).map(line => line.split('\t')));
        return lastLine;
    }
    rawData.push(...lines.filter(l => l).map(line => line.split('\t')));
    return '';
};

const loadStream = async () => {
    // debugger
    try {
        isLoading.value = true;
        error.value = null;
        rawData.length = 0;
        totalRows.value = 0;

        const response = await fetch(props.fileUrl);
        if (!response.body) throw new Error('不支持流式读取');

        const contentLength = response.headers.get('content-length');
        let receivedLength = 0;
        let leftover = '';

        reader.value = response.body.getReader();
        const decoder = new TextDecoder();

        while (true) {
            const { done, value } = await reader.value.read();
            if (done) break;

            receivedLength += value.length;
            if (contentLength) {
                loadedPercent.value = Math.round((receivedLength / contentLength) * 100);
            }

            const chunk = decoder.decode(value, { stream: true });
            // debugger
            leftover = processChunk(leftover + chunk, false);
        }

        // 处理剩余数据
        if (leftover) processChunk(leftover, true);
        totalRows.value = rawData.length;
    } catch (err) {
        if (err.name !== 'AbortError') {
            error.value = `加载失败：${err.message}`;
        }
    } finally {
        isLoading.value = false;
        reader.value = null;
    }
};

// 监听URL变化
watch(() => props.fileUrl, (newVal) => {
    if (newVal) {
        abortLoading();
        loadStream();
    }
});

// 生命周期
onBeforeUnmount(() => {
    abortLoading();
});

// 初始化加载
onMounted(() => {
    if (props.fileUrl) loadStream();
});
const tabledata = ref([])
// 修改后的处理方法
const handleEdit = (rowIndex, colIndex, event) => {
    const oldValue = rawData[rowIndex][colIndex];
    const newValue1 = event.target.value.trim();

    if (newValue1 !== oldValue) {
        console.log(`修改了第${rowIndex + 1}行第${colIndex + 1}列`,`旧值: ${oldValue} => 新值: ${newValue1}`);
        rawData[rowIndex][colIndex] = newValue1; // 手动更新保证数据同步
        tabledata.value.push({lineNum:rowIndex + 1,colNum:colIndex + 1,newValue:newValue1})
        // debugger
    }
};
// 在script中添加
const saveChanges = () => {
    // 构造表格数据（示例使用\t分隔）
    // const csvData = rawData.map(row => row.join('\t')).join('\n');
    batchModify({ id: props.rowId, modifications: tabledata.value }).then((res) => {
        ElMessage.success('保存成功')
        if (props.fileUrl) {
            abortLoading();
            loadStream()
            tabledata.value.length = 0
        }
    })

};
</script>

<style>
.text-viewer {
    width: 100%;
    /* max-width: 1200px; */
    margin: 0 auto;

    .edit-input {
        width: 100%;
        height: 100%;
        border: none;
        outline: none;
        padding: 0 12px;
        background: transparent;
        text-align: center;
    }

    .edit-input:focus {
        background: #f0f9ff;
        box-shadow: 0 0 0 1px #409eff inset;
    }

    .scroll-container {
        position: relative;
        overflow: auto;
        border: 1px solid #ddd;
    }

    .phantom {
        position: relative;
    }

    .row {
        position: absolute;
        min-width: 100%;
        /* 保证最小宽度与容器一致 */
        height: v-bind(ROW_HEIGHT + 'px');
        display: flex;
        align-items: center;
        border-bottom: 1px solid #eee;
        border-right: 1px solid #eee;
        box-sizing: border-box;
    }

    .cell {
        flex: 1 0 auto;
        /* 允许单元格根据内容扩展 */
        min-width: 160px;
        /* 设置最小宽度防止挤压 */
        padding: 0 12px;
        white-space: nowrap;
        overflow: visible;
        /* 显示完整内容 */
        position: relative;
        text-align: center;
    }

    .cell+.cell {
        border-left: 1px solid #f0f0f0;
    }

    .scroll-container::-webkit-scrollbar {
        width: 8px;
        height: 8px;
    }

    .scroll-container::-webkit-scrollbar-thumb {
        background-color: #c1c1c1;
        border-radius: 4px;
    }

    .loading {
        padding: 10px;
        background: #f5f5f5;
        text-align: center;
    }

    .error {
        color: #ff4444;
        padding: 20px;
        text-align: center;
    }
}

/* 添加全屏样式 */
.text-viewer.full-screen {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 9999;
    background: white;
    width: 100vw;
    height: 100vh;
}

.controls {
    position: absolute;
    bottom: 0px;
    right: 0px;
    z-index: 10000;
}

button {
    padding: 8px 16px;
    background: #409eff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}
</style>