<template>
  <div class="map-wrapper" ref="wrapper">
    <div class="konva-container" ref="konvaContainer"></div>

    <div class="corner-videos-overlay" v-if="hasAnyVideo" :style="{ width: stageWidth + 'px', height: stageHeight + 'px' }">
      
      <div v-if="videoUrls.nw" class="video-corner top-left">
        <template v-if="activeVideos.nw">
          <XgVideoPlayer :src="videoUrls.nw" :autoplay="true" />
          <div class="close-btn" title="关闭视频" @click="closeVideo('nw')">✕</div>
        </template>
        <div v-else class="empty-state" @click="openVideo('nw')" title="点击关联视频">
          <span class="empty-tag">关联视频</span>
          <img :src="require('@/assets/images/camera.png')" alt="camera" class="camera-image" />
        </div>
      </div>

      <div v-if="videoUrls.ne" class="video-corner top-right">
        <template v-if="activeVideos.ne">
          <XgVideoPlayer :src="videoUrls.ne" :autoplay="true" />
          <div class="close-btn" title="关闭视频" @click="closeVideo('ne')">✕</div>
        </template>
        <div v-else class="empty-state" @click="openVideo('ne')" title="点击关联视频">
          <span class="empty-tag">关联视频</span>
          <img :src="require('@/assets/images/camera.png')" alt="camera" class="camera-image" />
        </div>
      </div>

      <div v-if="videoUrls.sw" class="video-corner bottom-left">
        <template v-if="activeVideos.sw">
          <XgVideoPlayer :src="videoUrls.sw" :autoplay="true" />
          <div class="close-btn" title="关闭视频" @click="closeVideo('sw')">✕</div>
        </template>
        <div v-else class="empty-state" @click="openVideo('sw')" title="点击关联视频">
          <span class="empty-tag">关联视频</span>
          <img :src="require('@/assets/images/camera.png')" alt="camera" class="camera-image" />
        </div>
      </div>

      <div v-if="videoUrls.se" class="video-corner bottom-right">
        <template v-if="activeVideos.se">
          <XgVideoPlayer :src="videoUrls.se" :autoplay="true" />
          <div class="close-btn" title="关闭视频" @click="closeVideo('se')">✕</div>
        </template>
        <div v-else class="empty-state" @click="openVideo('se')" title="点击关联视频">
          <span class="empty-tag">关联视频</span>
          <img :src="require('@/assets/images/camera.png')" alt="camera" class="camera-image" />
        </div>
      </div>

    </div>
  </div>
</template>

<script>
import Konva from 'konva';
import XgVideoPlayer from '@/components/ui/XgVideoPlayer.vue';

// 方向箭头 SVG 路径映射
// 所有方向臂共用同一套图标（以N方向/向下驶入为基准），由 createRoadArm 的 rotation 自动旋转
// R（右转）用左转图标水平翻转
const arrowSvgMap = {
  S: require('@/assets/images/svg/icon_straight_down.svg'),
  L: require('@/assets/images/svg/icon_turn_down_left.svg'),
  U: require('@/assets/images/svg/icon_turn_down_left_uturn.svg'),
  R: require('@/assets/images/svg/icon_turn_down_left.svg'),  // 右转用左转图标，渲染时水平翻转
};

// SVG 原始文本映射（内联，避免 webpack loader 问题）
const svgRawCache = {};

// 首次加载时通过 Image → Canvas 获取不到 SVG 内容，所以直接用内联方式
// 从 require 得到的 URL（可能是 base64 或路径）加载图片
const imgCache = {};

function loadSvgImage(svgUrl, fillColor) {
  const cacheKey = svgUrl + '|' + fillColor;
  if (imgCache[cacheKey]) return Promise.resolve(imgCache[cacheKey]);

  // 如果是 base64 data URL，解码后替换颜色
  if (svgUrl.startsWith('data:image/svg+xml;base64,')) {
    const base64 = svgUrl.split(',')[1];
    let svgText = atob(base64);
    svgText = svgText.replace(/fill="#[0-9a-fA-F]{3,8}"/g, `fill="${fillColor}"`);
    const encoded = btoa(svgText);
    const dataUrl = 'data:image/svg+xml;base64,' + encoded;
    return new Promise(resolve => {
      const img = new Image();
      img.onload = () => { imgCache[cacheKey] = img; resolve(img); };
      img.src = dataUrl;
    });
  }

  // 普通 URL，fetch 后替换颜色
  return fetch(svgUrl)
    .then(r => r.text())
    .then(svgText => {
      const colored = svgText.replace(/fill="#[0-9a-fA-F]{3,8}"/g, `fill="${fillColor}"`);
      const blob = new Blob([colored], { type: 'image/svg+xml' });
      const url = URL.createObjectURL(blob);
      return new Promise(resolve => {
        const img = new Image();
        img.onload = () => { imgCache[cacheKey] = img; resolve(img); };
        img.src = url;
      });
    });
}

export default {
  name: 'IntersectionMapVideos',
  components: {
    XgVideoPlayer
  },
  props: {
    // 1. 路口数字孪生数据
    mapData: {
      type: Object,
      required: true
    },
    // 2. 【新增】：四路视频地址配置
    videoUrls: {
      type: Object,
      default: () => ({
        nw: '', ne: '', sw: '', se: ''
      })
    }
  },
  data() {
    return {
      stage: null,
      layer: null,
      armsNodes: {}, 
      panelNodes: {}, 
      resizeObserver: null, 
      C: {
        BG: '#212842', ROAD: '#3d3938', YELLOW: '#D9A73D', WHITE: '#E0E0E0',
        SIGNAL_RED: '#FF5252', SIGNAL_GREEN: '#8DF582',
        PANEL_BG: 'rgba(30, 30, 40, 0.85)', BLUE: '#448AFF'
      },
      sizeConfig: {
        stageSize: 900, 
        laneWidth: 40,
        halfRoad: 160,
        roadWidth: 320,
        armLength: 350
      },
      stageWidth: 900,  // 当前画布缩放后的真实宽度
      stageHeight: 900, // 当前画布缩放后的真实高度
      activeVideos: { nw: false, ne: false, sw: false, se: false },
    };
  },
  computed: {
    // 判断是否传入了至少一个视频，如果没有，直接不渲染遮罩层提升性能
    hasAnyVideo() {
      if (!this.videoUrls) return false;
      return ['nw', 'ne', 'sw', 'se'].some(corner => {
        const v = this.videoUrls[corner];
        return v && (typeof v === 'string' ? v : v.url);
      });
    }
  },
  mounted() {
    this.initKonvaStage();
    if (this.mapData && Object.keys(this.mapData).length > 0) {
      this.renderStaticConfig();
      this.updateDynamicSignals();
    }
    this.initResizeObserver();
  },
  beforeDestroy() {
    if (this.resizeObserver) this.resizeObserver.disconnect();
    if (this.stage) this.stage.destroy();
  },
  watch: {
    mapData: {
      handler(newData, oldData) {
        if (!newData) return;
        if (!oldData || JSON.stringify(newData.armsConfig) !== JSON.stringify(oldData.armsConfig)) {
          this.renderStaticConfig();
        }
        this.updateDynamicSignals();
      },
      deep: true
    }
  },
  methods: {
    openVideo(corner) {
      this.$set(this.activeVideos, corner, true);
    },
    closeVideo(corner) {
      this.$set(this.activeVideos, corner, false);
    },
    // ================= 以下为原有的 Konva 绘制逻辑，完全保持不变 =================
    initKonvaStage() {
      const { stageSize, halfRoad, roadWidth } = this.sizeConfig;
      const center = stageSize / 2;

      this.stage = new Konva.Stage({
        container: this.$refs.konvaContainer,
        width: stageSize,
        height: stageSize
      });
      this.layer = new Konva.Layer();
      this.stage.add(this.layer);

      this.layer.add(new Konva.Rect({ width: stageSize, height: stageSize, fill: this.C.BG }));
      this.layer.add(new Konva.Rect({ x: center - halfRoad, y: center - halfRoad, width: roadWidth, height: roadWidth, fill: this.C.ROAD }));

      this.armsNodes = {
        N: this.createRoadArm(center, center - halfRoad, 0),
        E: this.createRoadArm(center + halfRoad, center, 90),
        S: this.createRoadArm(center, center + halfRoad, 180),
        W: this.createRoadArm(center - halfRoad, center, 270)
      };
      Object.values(this.armsNodes).forEach(arm => this.layer.add(arm));

      this.createCenterPanel(center);
      this.layer.draw();
    },

    initResizeObserver() {
      this.resizeObserver = new ResizeObserver(() => {
        window.requestAnimationFrame(() => {
          this.handleResize();
        });
      });
      if (this.$refs.wrapper) {
        this.resizeObserver.observe(this.$refs.wrapper);
      }
    },

    handleResize() {
      if (!this.stage || !this.$refs.wrapper) return;
      const containerWidth = this.$refs.wrapper.clientWidth;
      const containerHeight = this.$refs.wrapper.clientHeight;
      if (containerWidth === 0 || containerHeight === 0) return;

      const scaleX = containerWidth / this.sizeConfig.stageSize;
      const scaleY = containerHeight / this.sizeConfig.stageSize;
      const scale = Math.min(scaleX, scaleY);

      // 【核心修改】：记录缩放后的实际物理尺寸，供视频遮罩层使用
      this.stageWidth = this.sizeConfig.stageSize * scale;
      this.stageHeight = this.sizeConfig.stageSize * scale;

      this.stage.width(this.stageWidth);
      this.stage.height(this.stageHeight);
      this.stage.scale({ x: scale, y: scale });
    },

    createRoadArm(x, y, rotation) {
      const { halfRoad, roadWidth, laneWidth } = this.sizeConfig;
      const group = new Konva.Group({ x, y, rotation });
      
      group.add(new Konva.Rect({ x: -halfRoad, y: -350, width: roadWidth, height: 350, fill: this.C.ROAD }));
      group.add(new Konva.Line({ points: [0, -350, 0, -35], stroke: this.C.YELLOW, strokeWidth: 3 }));
      group.add(new Konva.Path({ data: `M -160 -350 L -160 -30 Q -160 0 -180 0`, stroke: this.C.YELLOW, strokeWidth: 3 }));
      group.add(new Konva.Path({ data: `M 160 -350 L 160 -30 Q 160 0 180 0`, stroke: this.C.YELLOW, strokeWidth: 3 }));
      group.add(new Konva.Line({ points: [-160, -35, 0, -35], stroke: this.C.WHITE, strokeWidth: 4 }));
      
      for (let i = 1; i < 4; i++) {
        let ox = i * laneWidth;
        group.add(new Konva.Line({ points: [-ox, -35, -ox, -120], stroke: this.C.WHITE, strokeWidth: 2 }));
        group.add(new Konva.Line({ points: [-ox, -120, -ox, -350], stroke: this.C.WHITE, strokeWidth: 2, dash: [15, 15] }));
        group.add(new Konva.Line({ points: [ox, -35, ox, -350], stroke: this.C.WHITE, strokeWidth: 2, dash: [15, 15] }));
      }
      
      const lightGroup = new Konva.Group();
      const rectOpts = { y: -16, width: 8, height: 24, cornerRadius: 2, offsetX: 4, offsetY: 12 };
      for (let lx = -148; lx <= -20; lx += 16) lightGroup.add(new Konva.Rect({ x: lx, ...rectOpts }));
      for (let rx = 20; rx <= 148; rx += 16) lightGroup.add(new Konva.Rect({ x: rx, ...rectOpts }));
      group.add(lightGroup);
      group.lightGroup = lightGroup;

      group.arrowNodes = { 0: null, 1: null, 2: null, 3: null };
      group.cameraNode = null;

      return group;
    },

    createCenterPanel(center) {
      const panelGroup = new Konva.Group({ x: center - 80, y: center - 45 });
      panelGroup.add(new Konva.Rect({ width: 160, height: 90, fill: this.C.PANEL_BG, cornerRadius: 8 }));
      
      const labelFont = { fontSize: 18, fontFamily: 'monospace', fontStyle: 'bold', fill: this.C.WHITE }; 
      const valueFont = { fontSize: 28, fontFamily: 'monospace', fontStyle: 'bold' };              
      
      this.panelNodes.nsLabel = new Konva.Text({ ...labelFont, x: 15, y: 22, text: '相位-:' });
      this.panelNodes.nsVal = new Konva.Text({ ...valueFont, x: 90, y: 15, text: '--', fill: this.C.SIGNAL_GREEN });
      
      this.panelNodes.ewLabel = new Konva.Text({ ...labelFont, x: 15, y: 55, text: '相位-:' });
      this.panelNodes.ewVal = new Konva.Text({ ...valueFont, x: 90, y: 48, text: '--', fill: this.C.SIGNAL_GREEN });
      
      panelGroup.add(this.panelNodes.nsLabel, this.panelNodes.nsVal, this.panelNodes.ewLabel, this.panelNodes.ewVal);
      this.layer.add(panelGroup);
    },

    createArrowIcon(type, x, y, color = this.C.WHITE) {
      const maxH = 40; // 最大高度
      const group = new Konva.Group({ x, y });
      if (type === 'R') group.scaleX(-1);
      group._arrowMeta = { type };

      const svgUrl = arrowSvgMap[type];
      if (svgUrl) {
        loadSvgImage(svgUrl, color).then(imgObj => {
          // 按原始比例等比缩放，高度不超过 maxH
          const natW = imgObj.naturalWidth || imgObj.width;
          const natH = imgObj.naturalHeight || imgObj.height;
          const scale = Math.min(maxH / natH, 1);
          const w = Math.round(natW * scale);
          const h = Math.round(natH * scale);
          const konvaImg = new Konva.Image({
            image: imgObj,
            x: -w / 2,
            y: -h - 5,
            width: w,
            height: h,
            name: 'arrowImg'
          });
          group.add(konvaImg);
          if (this.layer) this.layer.draw();
        });
      }
      return group;
    },

    createCameraIcon(type, x, y) {
      const group = new Konva.Group({ x, y });
      if (type === 1) { 
        group.add(new Konva.Line({ points: [-16, -30, 16, -30], stroke: this.C.BLUE, strokeWidth: 2.5, lineCap: 'round' }));
        group.add(new Konva.Line({ points: [0, -30, 0, -10], stroke: this.C.BLUE, strokeWidth: 2.5 }));
        const body = new Konva.Group({ y: -10, rotation: 15 });
        body.add(new Konva.Rect({ x: -16, y: -8, width: 32, height: 16, stroke: this.C.BLUE, strokeWidth: 2.5, cornerRadius: 2 }));
        body.add(new Konva.Rect({ x: 16, y: -4, width: 6, height: 8, stroke: this.C.BLUE, strokeWidth: 2.5, cornerRadius: 1 }));
        group.add(body);
      } else if (type === 2) { 
        group.add(new Konva.Rect({ x: -14, y: -24, width: 28, height: 24, stroke: this.C.BLUE, strokeWidth: 2.5, cornerRadius: 6 }));
        group.add(new Konva.Circle({ x: 0, y: -12, radius: 5, stroke: this.C.BLUE, strokeWidth: 2.5 }));
        group.add(new Konva.Line({ points: [-10, 0, 10, 0], stroke: this.C.BLUE, strokeWidth: 2.5, lineCap: 'round' }));
        group.add(new Konva.Line({ points: [0, 0, 0, 6], stroke: this.C.BLUE, strokeWidth: 2.5 }));
      }
      return group;
    },

    renderStaticConfig() {
      const config = this.mapData.armsConfig;
      if (!config) return;

      Object.keys(config).forEach(dir => {
        const armData = config[dir];
        const armNode = this.armsNodes[dir];

        if (armNode.cameraNode) armNode.cameraNode.destroy();
        if (armData.cameraType > 0) {
          const cam = this.createCameraIcon(armData.cameraType, -80, -190);
          armNode.add(cam);
          armNode.cameraNode = cam;
        }

        armData.lanes.forEach((type, index) => {
          if (armNode.arrowNodes[index]) armNode.arrowNodes[index].destroy();
          if (type) {
            const lx = -20 - (index * this.sizeConfig.laneWidth);
            const arrow = this.createArrowIcon(type, lx, -80, this.C.WHITE);
            armNode.add(arrow);
            armNode.arrowNodes[index] = arrow;
          }
        });
      });
      this.layer.draw();
    },

    updateDynamicSignals() {
      const signals = this.mapData.signals;
      if (!signals) return;
      const config = this.mapData.armsConfig || {};

      const nsColor = signals.ns.isGreen ? this.C.SIGNAL_GREEN : this.C.SIGNAL_RED;
      const ewColor = signals.ew.isGreen ? this.C.SIGNAL_GREEN : this.C.SIGNAL_RED;
      const nsActiveTypes = signals.ns.activeArrowTypes || [];
      const ewActiveTypes = signals.ew.activeArrowTypes || [];

      const dyeArm = (dir, armNode, pedColor, vehicleColor, activeTypes) => {
        // 灯带颜色（人行道信号）
        armNode.lightGroup.getChildren().forEach(r => r.fill(pedColor));
        // 箭头按 lane type 用不同颜色的 SVG 替换
        const lanes = (config[dir] && config[dir].lanes) || [];
        Object.keys(armNode.arrowNodes).forEach(index => {
          const arr = armNode.arrowNodes[index];
          if (!arr) return;
          const laneType = lanes[index];
          const isActive = activeTypes.length > 0 && activeTypes.includes(laneType);
          const targetColor = isActive ? this.C.SIGNAL_GREEN : this.C.SIGNAL_RED;

          const meta = arr._arrowMeta;
          if (!meta) return;
          const svgUrl = arrowSvgMap[meta.type];
          if (!svgUrl) return;

          loadSvgImage(svgUrl, targetColor).then(imgObj => {
            const existing = arr.findOne('.arrowImg');
            if (existing) {
              existing.image(imgObj);
            } else {
              const maxH = 40;
              const natW = imgObj.naturalWidth || imgObj.width;
              const natH = imgObj.naturalHeight || imgObj.height;
              const scale = Math.min(maxH / natH, 1);
              const w = Math.round(natW * scale);
              const h = Math.round(natH * scale);
              arr.add(new Konva.Image({
                image: imgObj,
                x: -w / 2,
                y: -h - 5,
                width: w,
                height: h,
                name: 'arrowImg'
              }));
            }
            if (this.layer) this.layer.draw();
          });
        });
      };

      // 灯带代表人行道：P1/P3绿灯期间正常（车绿人红、车红人绿），其余时段人行道全红
      const pedAllRed = signals.pedAllRed || false;
      const nsPedColor = pedAllRed ? this.C.SIGNAL_RED : (signals.ns.isGreen ? this.C.SIGNAL_RED : this.C.SIGNAL_GREEN);
      const ewPedColor = pedAllRed ? this.C.SIGNAL_RED : (signals.ew.isGreen ? this.C.SIGNAL_RED : this.C.SIGNAL_GREEN);

      dyeArm('N', this.armsNodes.N, nsPedColor, nsColor, nsActiveTypes);
      dyeArm('S', this.armsNodes.S, nsPedColor, nsColor, nsActiveTypes);
      dyeArm('E', this.armsNodes.E, ewPedColor, ewColor, ewActiveTypes);
      dyeArm('W', this.armsNodes.W, ewPedColor, ewColor, ewActiveTypes);

      this.panelNodes.nsLabel.text(`${signals.ns.phaseName}:`);
      this.panelNodes.nsVal.text(signals.ns.time.toString().padStart(2, '0')).fill(nsColor);

      this.panelNodes.ewLabel.text(`${signals.ew.phaseName}:`);
      this.panelNodes.ewVal.text(signals.ew.time.toString().padStart(2, '0')).fill(ewColor);

      this.layer.draw();
    }
  }
};
</script>

<style scoped>
/* ================= 地图外层 ================= */
.map-wrapper {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: #212842;
  position: relative; /* 核心：让子元素能在其内部绝对定位 */
}

.konva-container {
  position: absolute; 
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1; /* 图层垫底 */
}

/* ================= 视频遮罩与挂件 ================= */
.corner-videos-overlay {
  position: absolute;
  /* 【核心修改】：和 Canvas 一样，使用绝对居中对齐 */
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
  pointer-events: none; 
  border-radius: 2px;
  overflow: hidden;
}

.video-corner {
  position: absolute;
  /* (900-320)/2 / 900 = 32.222% */
  width: 32.222%;
  height: 32.222%;
  background: #000;
  pointer-events: auto;

  box-sizing: border-box;
  border: 1px solid rgba(68, 138, 255, 0.4);
  overflow: hidden;
  border-radius: 2px;
}

/* 四角贴死四个角 */
.top-left { top: -1px; left: -1px; }
.top-right { top: -1px; right: -1px; }
.bottom-left { bottom: -1px; left: -1px; }
.bottom-right { bottom: -1px; right: -1px; }

/* ================= 关联视频空状态 & 关闭按钮 ================= */
.close-btn {
  position: absolute;
  top: 4%;
  right: 4%;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  width: 8%;
  height: 8%;
  min-width: 14px;
  min-height: 14px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.3s;
  z-index: 10;
  font-size: clamp(8px, 4%, 14px);
}
.close-btn:hover { background: rgba(0, 0, 0, 1); }

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  cursor: pointer;
  transition: all 0.3s ease;
  background: #112445;
  border-radius: 2px;
  overflow: hidden;
}
.empty-state:hover {
  background: rgba(68, 138, 255, 0.1);
}
.empty-state:hover .empty-tag {
  background: rgba(68, 138, 255, 1);
  box-shadow: 0 0 10px rgba(68, 138, 255, 0.5);
}
.empty-state:hover .camera-image {
  transform: scale(1.05);
  transition: transform 0.3s ease;
}

.empty-tag {
  background: rgba(68, 138, 255, 0.8);
  color: #fff;
  padding: 2% 6%;
  border-radius: 4px;
  font-size: clamp(8px, 5%, 14px);
  margin-bottom: 6%;
  letter-spacing: 1px;
  transition: all 0.3s ease;
  white-space: nowrap;
}

.camera-image {
  width: 30%;
  max-width: 50px;
  height: auto;
  object-fit: contain;
  opacity: 0.8;
}

/* xgplayer 填满角落容器 */
.video-corner .xg-video-player {
  width: 100%;
  height: 100%;
}

.video-corner >>> .xgplayer {
  width: 100% !important;
  height: 100% !important;
}

.video-corner >>> .xgplayer video {
  object-fit: cover;
}
</style>