<template>
  <view class="pdf-viewer" ref="pdfContainerRef" >
	      <!-- 横屏提示组件 -->
	      <LandscapeTip
				:debug="false"
		      :auto-show="pdfInfo.landscapeFlag ? pdfInfo.landscapeFlag : false"
		      :show-delay="1000"
		      :check-wide-content="false"
	      />
	    <!-- 添加一个滚动容器 -->
	      <scroll-view 
	        class="pdf-scroll-view"
	        scroll-y 
	        :show-scrollbar="false"
	        @scroll="handleScroll"
	        :scroll-top="scrollTop"
	      >
    <!-- PDF文档信息 -->
    <view class="pdf-info" v-if="pdfInfo.title">
      <text class="pdf-title">{{ pdfInfo.title }}</text>
      <text class="pdf-page-count" v-if="pdfPageCount > 0">共 {{ pdfPageCount }} 页</text>
    </view>

    <!-- 页面列表 -->
    <view 
      v-for="pageIndex in pdfPageCount" 
      :key="pageIndex"
      class="page-container"
      :id="`page-${pageIndex}`"
	   
    >
    <view class="page-header" v-if="loadingStatus">
       <text class="page-number">第 {{ pageIndex }} 页</text>
        <text class="page-status" v-if="isPageLoading(pageIndex)">加载中...</text>
        <text class="page-status error" v-else-if="isPageFailed(pageIndex)">加载失败</text>
        <text class="page-status success" v-else-if="getPageImage(pageIndex)">加载完成</text>
      </view>

      <view class="page-content">
        <view class="loadEffect" v-if="!getPageImage(pageIndex) || isPageLoading(pageIndex)"></view>
        <image 
          v-if="getPageImage(pageIndex)"
          :src="getPageImage(pageIndex)" 
          mode="widthFix" 
          class="pdf-image"
          @load="handlePageImageLoad(pageIndex)"
          @error="handlePageImageError(pageIndex)"
		  :show-menu-by-longpress="false"
        ></image>
        <view v-else-if="isPageFailed(pageIndex)" class="page-error" @click="retryLoadPage(pageIndex)">
          <text class="error-text">页面加载失败，点击重试</text>
          <text class="retry-count">已重试 {{ getPageRetryCount(pageIndex) }} 次</text>
        </view>
        <view v-else class="page-placeholder">
          <text>页面加载中...</text>
        </view>
      </view>
    </view>

    <!-- 加载状态 -->
    <view v-if="loading" class="loading-state">
      <view class="loading-spinner"></view>
      <text>文件较大，正在加载中...</text>
    </view>

    <!-- 错误状态 -->
    <view v-if="error" class="error-state">
      <text class="error-icon">❌</text>
      <text class="error-message">{{ errorMessage }}</text>
      <button class="retry-button" @click="initPdf">重试</button>
    </view>

    <!-- 加载进度 -->
    <view v-if="!loading && !error && pdfPageCount > 0" class="progress-info">
      <text>已加载 {{ loadedPages }}/{{ pdfPageCount }} 页</text>
      <view class="progress-bar">
        <view class="progress-inner" :style="{ width: `${(loadedPages / pdfPageCount) * 100}%` }"></view>
      </view>
    </view>
	</scroll-view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue';
// 导入本地安装的PDF.js
import * as pdfjsLib from 'pdfjs-dist';
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker?url';
import LandscapeTip from '@/components/LandscapeTip/LandscapeTip.vue';

// ========================== 类型定义 ==========================
interface PdfInfo {
  title?: string;
  url: string;
  landscapeFlag?:boolean;
}

interface Props {
  pdfInfo: PdfInfo;
  autoLoad?: boolean;
  lazyLoad?: boolean;
  maxRetryCount?: number;
  loadingStatus?:boolean;
}

// ========================== Props & Emits ==========================
const props = withDefaults(defineProps<Props>(), {
  autoLoad: true,
  lazyLoad: true,
  maxRetryCount: 3,
  loadingStatus:false,
  
});

const emit = defineEmits<{
  loadStart: [url: string];
  loadComplete: [url: string, pageCount: number];
  loadError: [url: string, error: Error];
  pageChange: [currentPage: number, totalPages: number];
}>();

// ========================== 响应式数据 ==========================
const pdfImages = ref<string[]>([]);
const imgLoading = ref<boolean[]>([]);
const pdfPageCount = ref(0);
const currentLoading = ref(0);
const pdfDoc = ref<any>(null);
const failedPages = ref<Record<number, number>>({});
const loadingQueue = ref<number[]>([]);
const isProcessingQueue = ref(false);
const loading = ref(false);
const error = ref(false);
const errorMessage = ref('');
const currentPage = ref(1);
const lastScrollTime = ref(0);
const scrollThrottle = ref(300);
const loadedPageSet = ref<Set<number>>(new Set()); // 记录已加载的页面
// 添加 scrollTop 用于控制滚动位置
const scrollTop = ref(0);
// ========================== 初始化PDF.js ==========================
// 设置worker
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;

// ========================== 横屏提示处理 ==========================
const autoLandscapeTipRef = ref();

/**
 * 提示关闭回调
 */
const onTipClose = () => {
  console.log('横屏提示已关闭');
};

/**
 * 提示显示回调
 */
const onTipShow = () => {
  console.log('横屏提示已显示');
};

/**
 * 方向变化回调
 */
const onOrientationChange = (orientation: 'portrait' | 'landscape') => {
  console.log('屏幕方向变为:', orientation);
};


// ========================== 计算属性 ==========================
const loadedPages = computed(() => {
  return loadedPageSet.value.size;
});

const hasMoreToLoad = computed(() => {
  return loadedPages.value < pdfPageCount.value;
});

// ========================== 生命周期 ==========================
onMounted(() => {
  if (props.autoLoad) {
    initPdf();
  }
 
});


onUnmounted(() => {
  cleanup();
  
});

// ========================== 监听器 ==========================
watch(() => props.pdfInfo.url, (newUrl, oldUrl) => {
  if (newUrl && newUrl !== oldUrl) {
    resetState();
    initPdf();
  }
});

// ========================== 公共方法 ==========================
/**
 * 初始化PDF
 */
const initPdf = async () => {
  if (!props.pdfInfo.url) {
    setError('PDF URL不能为空');
    return;
  }

  try {
    resetState();
    loading.value = true;
    error.value = false;
    
    emit('loadStart', props.pdfInfo.url);
    
    await loadPdfDocument();
    
    // 初始加载前3页
    const initialPages = Math.min(3, pdfPageCount.value);
    console.log(`初始加载前 ${initialPages} 页`);
    for (let i = 1; i <= initialPages; i++) {
      addToLoadingQueue(i);
    }
    
    processLoadingQueue();
    
    // 延迟检查其他可见页面
    nextTick(() => {
      setTimeout(() => {
        checkVisiblePages();
      }, 800);
    });
    
  } catch (err: any) {
	  setError('文件读取失败')
    // setError(`PDF初始化失败: ${err.message}`);
    emit('loadError', props.pdfInfo.url, err);
  } finally {
    loading.value = false;
  }
};

/**
 * 重新加载PDF
 */
const reload = () => {
  initPdf();
};



// ========================== 内部方法 ==========================
/**
 * 重置状态
 */
const resetState = () => {
  pdfImages.value = [];
  imgLoading.value = [];
  pdfPageCount.value = 0;
  currentLoading.value = 0;
  failedPages.value = {};
  loadingQueue.value = [];
  isProcessingQueue.value = false;
  error.value = false;
  errorMessage.value = '';
  currentPage.value = 1;
  loadedPageSet.value.clear();
  
  if (pdfDoc.value) {
    pdfDoc.value.destroy();
    pdfDoc.value = null;
  }
};

/**
 * 清理资源
 */
const cleanup = () => {
  if (pdfDoc.value) {
    pdfDoc.value.destroy();
    pdfDoc.value = null;
  }
};

/**
 * 设置错误状态
 */
const setError = (message: string) => {
  error.value = true;
  errorMessage.value = message;
  loading.value = false;
};

/**
 * 加载PDF文档
 */
const loadPdfDocument = async (): Promise<number> => {
  try {
    const loadingTask = pdfjsLib.getDocument({
      url: props.pdfInfo.url,
      cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.11.338/cmaps/',
      cMapPacked: true,
      disableFontFace: true,
      useSystemFonts: true,
      isEvalSupported: false,
    });
    
    pdfDoc.value = await loadingTask.promise;
    pdfPageCount.value = pdfDoc.value.numPages;
    
    // 初始化数组
    pdfImages.value = new Array(pdfPageCount.value).fill('');
    imgLoading.value = new Array(pdfPageCount.value).fill(false);
    
    emit('loadComplete', props.pdfInfo.url, pdfPageCount.value);
    
    console.log(`PDF文档加载完成: ${props.pdfInfo.url}, 共 ${pdfPageCount.value} 页`);
    return pdfPageCount.value;
    
  } catch (err: any) {
    console.error('PDF文档加载失败:', err);
    throw new Error(`文档加载失败: ${err.message}`);
  }
};


/**
 * 滚动处理 - 使用 scroll-view 的 scroll 事件
 */
const handleScroll = (e: any) => {
  if (!props.lazyLoad || loading.value) return;
  
  const now = Date.now();
  if (now - lastScrollTime.value < scrollThrottle.value) {
    return;
  }
  lastScrollTime.value = now;
  
  // 使用防抖
  clearTimeout((window as any).scrollTimer);
  (window as any).scrollTimer = setTimeout(() => {
    checkVisiblePages(e.detail.scrollTop);
  }, 100);
};

/**
 * 检查可见页面 - 修改为接收 scrollTop 参数
 */
const checkVisiblePages = (scrollTop: number) => {
  if (pdfPageCount.value === 0 || loadingQueue.value.length > 5) return;
  
  console.log('开始检查可见页面...', scrollTop);
  
  const windowHeight = uni.getSystemInfoSync().windowHeight;
  
  // 计算可见区域
  const visibleTop = scrollTop - 500; // 提前500px开始加载
  const visibleBottom = scrollTop + windowHeight + 1000; // 延后1000px加载
  
  // 检查每个页面是否在可见区域内
  for (let i = 1; i <= pdfPageCount.value; i++) {
    // 如果页面已经加载或正在加载，跳过
    if (loadedPageSet.value.has(i) || isPageLoading(i)) {
      continue;
    }
    
    // 检查页面位置
    uni.createSelectorQuery()
      .select(`#page-${i}`)
      .boundingClientRect((rect: any) => {
        if (rect) {
          const pageTop = scrollTop + rect.top;
          const pageBottom = scrollTop + rect.bottom;
          
          // 如果页面在可见区域内
          if (pageBottom > visibleTop && pageTop < visibleBottom) {
            console.log(`页面 ${i} 在可见区域内，准备加载`);
            addToLoadingQueue(i);
          }
          
          // 更新当前页
          if (rect.top < windowHeight / 2 && rect.bottom > windowHeight / 2) {
            if (currentPage.value !== i) {
              currentPage.value = i;
              emit('pageChange', i, pdfPageCount.value);
            }
          }
        }
      })
      .exec();
  }
  
  // 处理加载队列
  setTimeout(() => {
    processLoadingQueue();
  }, 50);
};
/**
 * 添加到加载队列
 */
const addToLoadingQueue = (pageNumber: number) => {
  if (!loadingQueue.value.includes(pageNumber) && 
      !loadedPageSet.value.has(pageNumber) && 
      !isPageLoading(pageNumber)) {
    console.log(`添加页面 ${pageNumber} 到加载队列`);
    loadingQueue.value.push(pageNumber);
    
    // 限制队列长度，避免一次性加载太多
    if (loadingQueue.value.length > 10) {
      loadingQueue.value = loadingQueue.value.slice(0, 10);
    }
  }
};

/**
 * 处理加载队列
 */
const processLoadingQueue = async () => {
  if (isProcessingQueue.value || loadingQueue.value.length === 0) return;

  isProcessingQueue.value = true;

  try {
    // 每次处理1页
    const pagesToLoad = loadingQueue.value.splice(0, 1);
    console.log(`处理加载队列: 加载页面 ${pagesToLoad[0]}`);
    
    for (const pageNumber of pagesToLoad) {
      await loadPdfPage(pageNumber);
    }
    
  } catch (err) {
    console.error('处理加载队列失败:', err);
  } finally {
    isProcessingQueue.value = false;

    // 如果队列中还有任务，继续处理
    if (loadingQueue.value.length > 0) {
      setTimeout(processLoadingQueue, 200);
    } else {
      // 队列处理完成后，再次检查可见页面
      setTimeout(() => {
        checkVisiblePages();
      }, 300);
    }
  }
};

/**
 * 加载PDF页面
 */
const loadPdfPage = async (pageNumber: number) => {
  if (loadedPageSet.value.has(pageNumber)) return;
  
  const retryCount = getPageRetryCount(pageNumber);
  if (retryCount >= props.maxRetryCount) {
    console.warn(`页面 ${pageNumber} 已达到最大重试次数`);
    return;
  }
  
  try {
    imgLoading.value[pageNumber - 1] = true;
    currentLoading.value++;
    
    console.log(`开始加载页面 ${pageNumber}...`);
    
    if (!pdfDoc.value) {
      throw new Error('PDF文档未加载');
    }
    
    const page = await pdfDoc.value.getPage(pageNumber);
	// 根据设备像素比动态设置缩放
	const pixelRatio = window.devicePixelRatio || 1;
	const scale = Math.max(1.5, pixelRatio); // 至少 1.5 倍，高分屏自动更高
	
	const viewport = page.getViewport({ scale });
    // const viewport = page.getViewport({ scale: 1.8 });
    
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    if (!context) {
      throw new Error('无法获取Canvas上下文');
    }
    
    canvas.width = viewport.width;
    canvas.height = viewport.height;
    
    const renderContext = {
      canvasContext: context,
      viewport: viewport
    };
    
    await page.render(renderContext).promise;
    
    const imageData = canvas.toDataURL('image/jpeg', 0.85);
    pdfImages.value[pageNumber - 1] = imageData;
    loadedPageSet.value.add(pageNumber);
    
    console.log(`页面 ${pageNumber} 加载完成，当前已加载: ${Array.from(loadedPageSet.value).join(',')}`);
    
    // 清理
    canvas.width = 0;
    canvas.height = 0;
    
    // 清除失败记录
    if (failedPages.value[pageNumber]) {
      delete failedPages.value[pageNumber];
    }
    
  } catch (err: any) {
    console.error(`页面 ${pageNumber} 加载失败:`, err);
    
    // 记录失败次数
    if (!failedPages.value[pageNumber]) {
      failedPages.value[pageNumber] = 1;
    } else {
      failedPages.value[pageNumber]++;
    }
    
    // 对有问题的页面生成占位图
    if (err.message.includes('private field') || err.message.includes('TypeError')) {
      pdfImages.value[pageNumber - 1] = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjUwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjhmOWZhIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPuW3suino+eggTwvdGV4dD48L3N2Zz4=';
      loadedPageSet.value.add(pageNumber);
    }
    
  } finally {
    imgLoading.value[pageNumber - 1] = false;
    currentLoading.value--;
  }
};

/**
 * 手动加载下一页
 */
const loadNextPage = () => {
  if (pdfPageCount.value === 0) return;
  
  // 找到第一个未加载的页面
  for (let i = 1; i <= pdfPageCount.value; i++) {
    if (!loadedPageSet.value.has(i) && !isPageLoading(i)) {
      console.log(`手动加载页面 ${i}`);
      addToLoadingQueue(i);
      processLoadingQueue();
      break;
    }
  }
};

/**
 * 重试加载页面
 */
const retryLoadPage = (pageNumber: number) => {
  const retryCount = getPageRetryCount(pageNumber);
  if (retryCount >= props.maxRetryCount) {
    uni.showToast({
      title: '已达到最大重试次数',
      icon: 'none',
      duration: 2000
    });
    return;
  }
  
  if (failedPages.value[pageNumber]) {
    delete failedPages.value[pageNumber];
  }
  
  // 从已加载集合中移除
  loadedPageSet.value.delete(pageNumber);
  pdfImages.value[pageNumber - 1] = '';
  
  addToLoadingQueue(pageNumber);
  processLoadingQueue();
};

// ========================== 辅助方法 ==========================
const getPageImage = (pageIndex: number): string => {
  return pdfImages.value[pageIndex - 1] || '';
};

const isPageLoading = (pageIndex: number): boolean => {
  return imgLoading.value[pageIndex - 1] || false;
};

const isPageFailed = (pageIndex: number): boolean => {
  const retryCount = getPageRetryCount(pageIndex);
  return retryCount > 0 && retryCount <= props.maxRetryCount;
};

const getPageRetryCount = (pageIndex: number): number => {
  return failedPages.value[pageIndex] || 0;
};

const handlePageImageLoad = (pageIndex: number) => {
  console.log(`页面 ${pageIndex} 图片加载完成`);
};

const handlePageImageError = (pageIndex: number) => {
  console.error(`页面 ${pageIndex} 图片加载失败`);
};

// 暴露方法给父组件
defineExpose({
  initPdf,
  reload,
  loadNextPage, // 新增手动加载下一页方法
  getCurrentPage: () => currentPage.value,
  getTotalPages: () => pdfPageCount.value,
  getLoadedPages: () => Array.from(loadedPageSet.value),
    // 手动控制横屏提示
    showLandscapeTip: () => autoLandscapeTipRef.value?.show?.(),
    hideLandscapeTip: () => autoLandscapeTipRef.value?.hide?.(),
    resetLandscapeTip: () => autoLandscapeTipRef.value?.reset?.()
});
</script>

<style scoped lang="scss">
.pdf-viewer {
  width: 100%;
  height: 100vh;
  background: #ffffff;
  display: flex;
  flex-direction: column;
}

.pdf-scroll-view {
  flex: 1;
  height: 0; // 重要：让 scroll-view 正确计算高度
}


.pdf-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 24rpx;
  background: #f8f9fa;
  border-bottom: 1rpx solid #e8e8e8;
  
  .pdf-title {
    font-size: 32rpx;
    font-weight: 600;
    color: #333;
    flex: 1;
  }
  
  .pdf-page-count {
    font-size: 26rpx;
    color: #666;
    background: #e6f7ff;
    padding: 8rpx 16rpx;
    border-radius: 20rpx;
  }
}

.page-container {
  margin-bottom: 32rpx;
  border-bottom: 1rpx solid #f0f0f0;
  &:last-child {
    border-bottom: none;
  }
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20rpx 24rpx;
  background: #fafafa;
  
  .page-number {
    font-size: 28rpx;
    color: #333;
    font-weight: 500;
  }
  
  .page-status {
    font-size: 24rpx;
    
    &.success {
      color: #52c41a;
    }
    
    &.error {
      color: #ff4d4f;
    }
  }
}

.page-content {
  position: relative;
  min-height: 400rpx;
  
  .pdf-image {
		width: 100%;
      height: auto;
      display: block;
      // 禁用长按菜单
      -webkit-touch-callout: none;
      -webkit-user-select: none;
      user-select: none;
      // 禁止长按保存
      pointer-events: none;
  }
}

.loadEffect {
  width: 200rpx;
  height: 200rpx;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: url('../../static/range-fullloading/loading.gif') no-repeat center;
  background-size: contain;
  z-index: 10;
}

.page-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 400rpx;
  background: #fff2f2;
  border: 1rpx dashed #ff4d4f;
  border-radius: 8rpx;
  color: #ff4d4f;
  
  .error-text {
    font-size: 28rpx;
    margin-bottom: 16rpx;
  }
  
  .retry-count {
    font-size: 24rpx;
    color: #999;
  }
}

.page-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 400rpx;
  background: #f8f9fa;
  color: #666;
  font-size: 28rpx;
}

.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80rpx 0;
  
  .loading-spinner {
    width: 40rpx;
    height: 40rpx;
    border: 4rpx solid #e8e8e8;
    border-top: 4rpx solid #20269B;
    border-radius: 50%;
    animation: spin 1s linear infinite;
    margin-bottom: 24rpx;
  }
  
  text {
    color: #666;
    font-size: 28rpx;
  }
}

.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80rpx 0;
  text-align: center;
  
  .error-icon {
    font-size: 60rpx;
    margin-bottom: 24rpx;
  }
  
  .error-message {
    color: #ff4d4f;
    font-size: 28rpx;
    margin-bottom: 32rpx;
  }
  
  .retry-button {
    background: #20269B;
    color: white;
    border: none;
    padding: 16rpx 32rpx;
    border-radius: 8rpx;
    font-size: 28rpx;
  }
}

.progress-info {
  padding: 12rpx;
  background: #f8f9fa;
  text-align: center;
  
  text {
    display: block;
    color: #666;
    font-size: 26rpx;
    margin-bottom: 16rpx;
  }
}

.progress-bar {
  width: 100%;
  height: 8rpx;
  background: #e8e8e8;
  border-radius: 4rpx;
  overflow: hidden;
  
  .progress-inner {
    height: 100%;
    background: #20269B;
    transition: width 0.3s ease;
  }
}

.action-buttons {
  display: flex;
  justify-content: space-between;
  padding: 20rpx 16rpx;
  background: #f8f9fa;
  border-top: 1rpx solid #e8e8e8;
  
  .action-btn {
    flex: 1;
    margin: 0 8rpx;
    background: #20269B;
    color: white;
    border: none;
    padding: 16rpx;
    border-radius: 8rpx;
    font-size: 26rpx;
    
    &:disabled {
      background: #ccc;
      color: #999;
    }
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
</style>