<template>
  <view class="container">
    <!-- 用于承载 PIXI 的 Canvas -->
    <!-- #ifdef H5 -->
    <view id="matchCanvas" class="match-canvas"></view>
    <!-- #endif -->
    <!-- #ifndef H5 -->
    <canvas type="webgl" id="matchCanvas" canvas-id="matchCanvas" class="match-canvas" />
    <!-- #endif -->
  </view>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from "vue";
import * as PIXI from "pixi.js";

const appRef = ref(null); // 存储 PIXI 应用实例

// 名称、颜色、大小、位置（角度、半径）
const mockTags = [
  {
    name: "医生",
    bgColor: 0x0069fe,
    fontColor: 0xffffff,
    size: 17,
    opacity: 1.0,
    angle: 0,
    radius: 0,
  },
  {
    name: "工程师",
    bgColor: 0x87e2ec,
    fontColor: 0xffffff,
    size: 14,
    opacity: 1,
    angle: -Math.PI / 2, // 12点方向
    radius: 68,
    tailRotation: Math.PI / 2, // 拖尾向下
  },
  {
    name: "建筑师",
    bgColor: 0xffebeb,
    fontColor: 0xff6969,
    size: 11.5,
    opacity: 1,
    angle: -Math.PI / 4.2, // 1点方向
    radius: 125,
    tailRotation: (3 * Math.PI) / 4, // 拖尾向左下
  },
  {
    name: "律师",
    bgColor: 0x21ea85,
    fontColor: 0xffffff,
    size: 15,
    opacity: 1,
    angle: -Math.PI / 10, // 2点方向
    radius: 130,
    tailRotation: (3 * Math.PI) / 4, // 拖尾向左下
  },
  {
    name: "记者",
    bgColor: 0xebf3ff,
    fontColor: 0x1d71ef,
    size: 12,
    opacity: 1,
    angle: Math.PI / 120, // 3点方向
    radius: 130,
    tailRotation: Math.PI, // 拖尾向左
  },
  {
    name: "程序员",
    bgColor: 0xffd4b6,
    fontColor: 0xffffff,
    size: 14.5,
    opacity: 1,
    angle: Math.PI / 9, // 4点方向
    radius: 120,
    tailRotation: (5 * Math.PI) / 4, // 拖尾向左上
  },
  {
    name: "摄影师",
    bgColor: 0xd8e5fe,
    fontColor: 0x1d71ef,
    size: 11,
    opacity: 1,
    angle: Math.PI / 3, // 5点方向
    radius: 75,
    tailRotation: (3 * Math.PI) / 2, // 拖尾向上
  },
  {
    name: "设计师",
    bgColor: 0xff9400,
    fontColor: 0xffffff,
    size: 14,
    opacity: 1,
    angle: (2 * Math.PI) / 3, // 7点方向
    radius: 92,
    tailRotation: (7 * Math.PI) / 4, // 拖尾向右上
  },
  {
    name: "心理咨询师",
    bgColor: 0xebf3ff,
    fontColor: 0x1d71ef,
    size: 10.5,
    opacity: 1,
    angle: (5.4 * Math.PI) / 6, // 8点方向
    radius: 110,
    tailRotation: 0, // 拖尾向右
  },
  {
    name: "护士",
    bgColor: 0xff6969,
    fontColor: 0xffffff,
    size: 15,
    opacity: 1,
    angle: (6.3 * Math.PI) / 5.9, // 10点方向
    radius: 110,
    tailRotation: Math.PI / 4, // 拖尾向右下
  },
  {
    name: "会计",
    bgColor: 0xfce9c9,
    fontColor: 0xfbc55f,
    size: 13,
    opacity: 1,
    angle: (7.2 * Math.PI) / 5.9, // 11点方向
    radius: 120,
    tailRotation: Math.PI / 4, // 拖尾向右下
  },
];

onMounted(async () => {
  if (appRef.value) return;
  // 初始化 PIXI 应用
  const canvas = document.getElementById("matchCanvas");
  const sw = canvas.clientWidth;
  const sh = canvas.clientHeight;
  const app = new PIXI.Application({
    backgroundAlpha: 0,
    antialias: true,
    autoDensity: true,
    width: sw,
    height: sh,
    backgroundColor: 0xf5f7fa,
  });
  appRef.value = app;

  canvas.appendChild(app.view);

  // 标签容器（
  const tagsContainer = new PIXI.Container();
  app.stage.addChild(tagsContainer);

  // 存储已放置标签的信息
  const placedTags = [];

  for (let i = 0; i < mockTags.length; i++) {
    const { angle, radius, tailRotation, ...tagData } = mockTags[i];
    const x = sw / 2 + radius * Math.cos(angle);
    const y = sh / 2 + radius * Math.sin(angle);
    const tag = createTag(tagData, x, y, placedTags, app, i);

    // 上下浮动动画
    const originalY = tag.y;
    let floatOffset = Math.random() * Math.PI * 2;
    let floatSpeed = 0.01 + Math.random() * 0.02;
    let floatRange = 2 + Math.random() * 2;

    // 拖尾效果
    if (radius > 0) {
      const tail = createCometTail(tagData.bgColor, tailRotation, tag);
      // 使用 addChildAt
      tag.addChildAt(tail, 0);
      // 拖尾动画
      app.ticker.add(() => {
        if (tail.updateTail) {
          tail.updateTail();
        }
      });
    }

    // 上下浮动动画
    app.ticker.add(() => {
      floatOffset += floatSpeed;
      tag.y = originalY + Math.sin(floatOffset) * floatRange;
    });

    tagsContainer.addChild(tag);
    placedTags.push({ ...tagData, bounds: tag.getBounds() });
  }
});

// 创建拖尾
function createCometTail(bgColor, tailRotation, tag) {
  const tailGroup = new PIXI.Container();

  // 拖尾位置
  tailGroup.x = 0;
  tailGroup.y = 0;

  const tail = new PIXI.Graphics();
  tailGroup.addChild(tail);

  // 拖尾参数
  const baseLength = 45; // 基础长度
  const startWidth = tag.width * 0.9; // 起始宽度（长边）
  const endWidth = 35; // 末端宽度（短边）

  // 拖尾动画参数
  let breathPhase = Math.random() * Math.PI * 2;
  const breathSpeed = 0.04;

  // 更新拖尾呼吸动画
  tailGroup.updateTail = () => {
    breathPhase += breathSpeed;
    const breathScale = 0.85 + 0.15 * Math.sin(breathPhase);
    tail.clear();

    // 绘制梯形拖尾
    const currentLength = baseLength * breathScale;
    // 计算拖尾的四个顶点
    // 长边在标签中心  水平方向
    const startLeft = { x: -startWidth / 2, y: 0 };
    const startRight = { x: startWidth / 2, y: 0 };

    // 短边在拖尾方向 保持水平
    const endCenter = {
      x: Math.cos(tailRotation) * currentLength,
      y: Math.sin(tailRotation) * currentLength,
    };

    const endLeft = {
      x: endCenter.x - endWidth / 2,
      y: endCenter.y,
    };

    const endRight = {
      x: endCenter.x + endWidth / 2,
      y: endCenter.y,
    };

    // 使用分段绘制实现渐变
    const segments = 6;
    for (let i = 0; i < segments; i++) {
      const progress = i / segments;
      const nextProgress = (i + 1) / segments;

      // 计算分段的位置 - 保持长边水平
      const segmentStartLeft = {
        x: startLeft.x * (1 - progress) + endLeft.x * progress,
        y: startLeft.y * (1 - progress) + endLeft.y * progress,
      };
      const segmentStartRight = {
        x: startRight.x * (1 - progress) + endRight.x * progress,
        y: startRight.y * (1 - progress) + endRight.y * progress,
      };
      const segmentEndLeft = {
        x: startLeft.x * (1 - nextProgress) + endLeft.x * nextProgress,
        y: startLeft.y * (1 - nextProgress) + endLeft.y * nextProgress,
      };
      const segmentEndRight = {
        x: startRight.x * (1 - nextProgress) + endRight.x * nextProgress,
        y: startRight.y * (1 - nextProgress) + endRight.y * nextProgress,
      };

      // 透明度渐变
      const segmentAlpha = 0.4 * (1 - progress);

      tail.beginFill(bgColor, segmentAlpha);
      tail.moveTo(segmentStartLeft.x, segmentStartLeft.y);
      tail.lineTo(segmentEndLeft.x, segmentEndLeft.y);
      tail.lineTo(segmentEndRight.x, segmentEndRight.y);
      tail.lineTo(segmentStartRight.x, segmentStartRight.y);
      tail.lineTo(segmentStartLeft.x, segmentStartLeft.y);
      tail.endFill();
    }
  };

  // 绘制
  tailGroup.updateTail();

  return tailGroup;
}

// 创建标签
function createTag(tagData, x, y, placedTags, app, index) {
  const tagGroup = new PIXI.Container();
  tagGroup.x = x;
  tagGroup.y = y;

  // 创建文本测量宽度
  const text = new PIXI.Text(tagData.name, {
    fontFamily: "Arial",
    fontSize: tagData.size,
    fill: tagData.fontColor,
  });
  text.anchor.set(0.5);

  const padding = 10;
  const charWidth = tagData.size * 1.5;
  const charHeight = tagData.size * 1.3;
  const textWidth = tagData.name.length * charWidth;

  let width = textWidth + padding * 2;
  if (index == 0) width = tagData.size * 4.5 + 10;

  const height = charHeight + padding;

  // 背景
  const bg = new PIXI.Graphics();
  bg.beginFill(tagData.bgColor, tagData.opacity ?? 1);
  bg.drawRoundedRect(-width / 2, -height / 2, width, height, 20);
  bg.endFill();
  tagGroup.addChild(bg);

  // 添加文本
  tagGroup.addChild(text);

  return tagGroup;
}

onUnmounted(() => {
  if (appRef.value) {
    appRef.value.destroy(true, true);
    appRef.value = null;
  }
});
</script>

<style scoped>
.container {
  width: 100%;
}
.match-canvas {
  width: 100%;
  height: 350rpx; /* 可根据需求调整高度 */
}
</style>
