<template>
  <div>
    <audio ref="audioRef" autoplay playsinline></audio>

    <!-- Desktop Overlay -->
    <Transition name="panel-slide">
      <div
        v-if="isRemoteDesktopActive && !isDesktopCollapsed"
        class="desktop-overlay"
      >
        <div class="overlay-header">
          <div class="header-left">
            <svg
              width="18"
              height="18"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
            >
              <rect x="2" y="3" width="20" height="14" rx="2" />
              <line x1="8" y1="21" x2="16" y2="21" />
              <line x1="12" y1="17" x2="12" y2="21" />
            </svg>
            <span>远程桌面</span>
            <span class="duration-text" v-if="desktopStream">{{
              callDurationStr
            }}</span>
          </div>
          <div class="header-right">
            <button
              v-if="desktopStream"
              class="header-btn"
              @click="toggleFullscreen"
              :title="isFullscreen ? '退出全屏' : '全屏'"
            >
              <svg
                v-if="!isFullscreen"
                width="16"
                height="16"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <polyline points="15 3 21 3 21 9" />
                <polyline points="9 21 3 21 3 15" />
                <line x1="21" y1="3" x2="14" y2="10" />
                <line x1="3" y1="21" x2="10" y2="14" />
              </svg>
              <svg
                v-else
                width="16"
                height="16"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <polyline points="4 14 10 14 10 20" />
                <polyline points="20 10 14 10 14 4" />
                <line x1="14" y1="10" x2="21" y2="3" />
                <line x1="3" y1="21" x2="10" y2="14" />
              </svg>
              <span>{{ isFullscreen ? "退出" : "全屏" }}</span>
            </button>
            <button class="header-btn danger" @click="endDesktop">
              <svg
                width="16"
                height="16"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <line x1="18" y1="6" x2="6" y2="18" />
                <line x1="6" y1="6" x2="18" y2="18" />
              </svg>
              <span>结束共享</span>
            </button>
          </div>
        </div>
        <div class="overlay-body" ref="videoContainer">
          <div v-if="desktopStream" class="video-wrapper">
            <video ref="videoRef" autoplay playsinline></video>
          </div>
          <div v-else class="loading-state">
            <svg
              width="48"
              height="48"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="1.5"
              class="spin-icon"
            >
              <circle
                cx="12"
                cy="12"
                r="10"
                stroke-dasharray="31.4 31.4"
                stroke-linecap="round"
              />
            </svg>
            <span>等待桌面共享...</span>
          </div>
        </div>
        <button
          class="desktop-side-toggle"
          @click="toggleDesktopCollapse"
          title="收起桌面"
          aria-label="收起桌面"
        >
          <svg
            width="18"
            height="18"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
          >
            <polyline points="9 18 15 12 9 6" />
          </svg>
        </button>
      </div>
    </Transition>

    <!-- Desktop Collapsed Tab (right side) -->
    <Transition name="tab-slide">
      <div
        v-if="isRemoteDesktopActive && isDesktopCollapsed"
        class="desktop-collapsed-tab"
        :class="{ 'is-stacked': isCallActive && !isCallCollapsed }"
        @click="toggleDesktopCollapse"
        title="展开桌面"
        aria-label="展开桌面"
      >
        <span class="sharing-status-dot"></span>
        <svg
          width="20"
          height="20"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
        >
          <rect x="3" y="4" width="18" height="12" rx="2" />
          <path d="M8 20h8" />
          <path d="M12 16v4" />
        </svg>
      </div>
    </Transition>

    <!-- Local Desktop Sharing Indicator -->
    <Transition name="panel-slide">
      <div
        v-if="isDesktopLocalSharing && !isDesktopShareCollapsed"
        class="desktop-sharing-panel"
      >
        <div class="sharing-panel-header">
          <div class="sharing-panel-title">
            <svg
              width="18"
              height="18"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
            >
              <rect x="3" y="4" width="18" height="12" rx="2" />
              <path d="M8 20h8" />
              <path d="M12 16v4" />
            </svg>
            <span>桌面正在被预览</span>
          </div>
          <div class="panel-header-actions">
            <button
              class="panel-icon-btn"
              @click="toggleDesktopShareCollapse"
              title="收起提示"
            >
              <svg
                width="14"
                height="14"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <polyline points="18 15 12 9 6 15" />
              </svg>
            </button>
            <button class="panel-icon-btn" @click="endDesktop" title="结束预览">
              <svg
                width="14"
                height="14"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <line x1="18" y1="6" x2="6" y2="18" />
                <line x1="6" y1="6" x2="18" y2="18" />
              </svg>
            </button>
          </div>
        </div>
        <div class="sharing-panel-body">
          <div class="sharing-status-dot"></div>
          <span>对方正在查看你的桌面</span>
        </div>
      </div>
    </Transition>

    <Transition name="tab-slide">
      <button
        v-if="isDesktopLocalSharing && isDesktopShareCollapsed"
        class="desktop-sharing-tab"
        :class="{ 'is-stacked': isCallActive && !isCallCollapsed }"
        @click="toggleDesktopShareCollapse"
        title="展开桌面预览提示"
        aria-label="展开桌面预览提示"
      >
        <span class="sharing-status-dot"></span>
        <svg
          width="20"
          height="20"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
        >
          <rect x="3" y="4" width="18" height="12" rx="2" />
          <path d="M8 20h8" />
          <path d="M12 16v4" />
        </svg>
      </button>
    </Transition>

    <!-- Incoming Call Request -->
    <Transition name="panel-slide">
      <div
        v-if="incomingCallRequest"
        class="call-floating-panel incoming-call-panel"
        :class="{ 'is-stacked': isDesktopLocalSharing }"
      >
        <div class="call-panel-header">
          <div class="panel-header-left">
            <span class="panel-header-icon">
              <svg
                width="18"
                height="18"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <path
                  d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
                />
              </svg>
            </span>
            <span>语音通话请求</span>
          </div>
        </div>
        <div class="call-panel-body">
          <div class="call-status-icon">
            <svg
              width="48"
              height="48"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="1.5"
            >
              <path
                d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
              />
            </svg>
          </div>
          <div class="call-status-text">对方请求语音通话</div>
        </div>
        <div class="incoming-call-actions">
          <button
            class="incoming-action-btn reject"
            :disabled="isIncomingCallHandling"
            @click="rejectIncomingCall"
          >
            拒绝
          </button>
          <button
            class="incoming-action-btn accept"
            :disabled="isIncomingCallHandling"
            @click="acceptIncomingCall"
          >
            接听
          </button>
        </div>
      </div>
    </Transition>

    <!-- Call-Only Floating Panel (expanded) -->
    <Transition name="panel-slide">
      <div
        v-if="isCallActive && !isCallCollapsed && !incomingCallRequest"
        class="call-floating-panel"
        :class="{ 'is-stacked': isDesktopLocalSharing }"
      >
        <div class="call-panel-header">
          <div class="panel-header-left">
            <span class="panel-header-icon">
              <svg
                width="18"
                height="18"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <path
                  d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
                />
              </svg>
            </span>
            <span>语音通话</span>
          </div>
          <div class="panel-header-actions">
            <button
              class="panel-icon-btn"
              @click="toggleCallCollapse"
              title="收起通话"
            >
              <svg
                width="14"
                height="14"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <polyline points="18 15 12 9 6 15" />
              </svg>
            </button>
            <button class="panel-icon-btn" @click="endCall" title="结束通话">
              <svg
                width="14"
                height="14"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <line x1="18" y1="6" x2="6" y2="18" />
                <line x1="6" y1="6" x2="18" y2="18" />
              </svg>
            </button>
          </div>
        </div>
        <div class="call-panel-body">
          <div class="call-status-icon">
            <svg
              width="48"
              height="48"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="1.5"
            >
              <path
                d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
              />
            </svg>
          </div>
          <div class="call-status-text">
            {{ callStream ? "通话中" : "正在建立连接..." }}
          </div>
          <div class="call-duration">{{ callDurationStr }}</div>
        </div>
        <div class="call-panel-footer">
          <button
            class="control-btn mute-btn"
            :class="{ 'is-muted': isCallMuted }"
            @click="toggleCallMuted"
            :title="isCallMuted ? '取消静音' : '静音'"
          >
            <svg
              v-if="!isCallMuted"
              width="22"
              height="22"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
            >
              <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" />
              <path d="M19 10v2a7 7 0 0 1-14 0v-2" />
              <line x1="12" y1="19" x2="12" y2="23" />
              <line x1="8" y1="23" x2="16" y2="23" />
            </svg>
            <svg
              v-else
              width="22"
              height="22"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
            >
              <line x1="1" y1="1" x2="23" y2="23" />
              <path d="M9 9v3a3 3 0 0 0 5.12 2.12" />
              <path d="M15 9.34V4a3 3 0 0 0-5.94-.6" />
              <path d="M19 10v2a7 7 0 0 1-8.93 6.69" />
              <path d="M12 19v4" />
              <line x1="8" y1="23" x2="16" y2="23" />
            </svg>
          </button>
          <button
            class="control-btn end-call-btn"
            @click="endCall"
            title="结束通话"
          >
            <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor">
              <path
                d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
              />
            </svg>
          </button>
        </div>
      </div>
    </Transition>

    <!-- Call-Only Collapsed Button (right side) -->
    <Transition name="tab-slide">
      <div
        v-if="isCallCollapsed && isCallActive"
        class="call-collapsed-btn"
        :class="{ 'is-stacked': isDesktopLocalSharing && !isDesktopShareCollapsed }"
        @click="toggleCallCollapse"
        title="展开通话"
      >
        <div class="call-collapsed-pulse"></div>
        <svg
          width="20"
          height="20"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
        >
          <path
            d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
          />
        </svg>
      </div>
    </Transition>
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, ref, onMounted, onUnmounted } from "vue";
import { peer } from "../utils/peer";
import { message } from "ant-design-vue";

const props = defineProps<{
  peerId: string;
}>();

interface StreamEvent extends CustomEvent {
  detail: {
    stream: MediaStream;
    type: "desktop" | "call";
    peerId: string;
  };
}

interface MediaEndedEvent extends CustomEvent {
  detail: {
    type: "desktop" | "call";
    peerId: string;
  };
}

interface MediaStartedEvent extends CustomEvent {
  detail: {
    peerId: string;
    role?: "viewer" | "sharer" | "caller";
  };
}

interface MediaRequestEvent extends CustomEvent {
  detail: {
    peerId: string;
    type: "desktop" | "call";
    accept: () => Promise<void> | void;
    reject: () => void;
  };
}

interface IncomingCallRequest {
  peerId: string;
  accept: () => Promise<void> | void;
  reject: () => void;
}

const videoRef = ref<HTMLVideoElement | null>(null);
const audioRef = ref<HTMLAudioElement | null>(null);
const videoContainer = ref<HTMLElement | null>(null);
const activeMediaPeerId = ref("");
const incomingCallRequest = ref<IncomingCallRequest | null>(null);
const desktopStream = ref<MediaStream | null>(null);
const callStream = ref<MediaStream | null>(null);
const isDesktopActive = ref(false);
const isDesktopLocalSharing = ref(false);
const isCallActive = ref(false);
const isFullscreen = ref(false);
const isCallMuted = ref(false);
const isDesktopCollapsed = ref(false);
const isDesktopShareCollapsed = ref(false);
const isCallCollapsed = ref(false);
const isIncomingCallHandling = ref(false);
const callDuration = ref(0);
let durationTimer: number | null = null;

const isRemoteDesktopActive = computed(
  () => isDesktopActive.value && !isDesktopLocalSharing.value,
);

const callDurationStr = computed(() => {
  const mins = Math.floor(callDuration.value / 60);
  const secs = callDuration.value % 60;
  return `${String(mins).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
});

const startDurationTimer = () => {
  if (durationTimer !== null) return;
  callDuration.value = 0;
  durationTimer = window.setInterval(() => {
    callDuration.value++;
  }, 1000);
};

const stopDurationTimer = () => {
  if (durationTimer !== null) {
    clearInterval(durationTimer);
    durationTimer = null;
  }
  callDuration.value = 0;
};

const isCurrentPeer = (peerId: string) => {
  if (peerId === props.peerId || peerId === activeMediaPeerId.value) {
    activeMediaPeerId.value = peerId;
    return true;
  }
  if (!activeMediaPeerId.value) {
    activeMediaPeerId.value = peerId;
    return true;
  }
  return false;
};

const getMediaPeerId = () => activeMediaPeerId.value || props.peerId;

const resetPeerWhenIdle = () => {
  if (
    !isDesktopActive.value &&
    !isDesktopLocalSharing.value &&
    !isCallActive.value
  ) {
    activeMediaPeerId.value = "";
  }
};

const bindDesktopVideo = async () => {
  await nextTick();
  if (!videoRef.value || !desktopStream.value) return;
  if (videoRef.value.srcObject !== desktopStream.value) {
    videoRef.value.srcObject = desktopStream.value;
  }
  videoRef.value.muted = true;
  videoRef.value.play().catch(() => {
    message.warning("浏览器阻止了自动播放，请点击桌面画面恢复播放");
  });
};

const toggleDesktopCollapse = async () => {
  isDesktopCollapsed.value = !isDesktopCollapsed.value;
  if (!isDesktopCollapsed.value) {
    await bindDesktopVideo();
  }
};

const toggleDesktopShareCollapse = () => {
  isDesktopShareCollapsed.value = !isDesktopShareCollapsed.value;
};

const toggleCallCollapse = () => {
  isCallCollapsed.value = !isCallCollapsed.value;
};

const handleMediaRequest = (event: MediaRequestEvent) => {
  const { peerId, type, accept, reject } = event.detail;
  if (type !== "call" || !isCurrentPeer(peerId)) return;
  incomingCallRequest.value = {
    peerId,
    accept,
    reject,
  };
  isCallCollapsed.value = false;
};

const acceptIncomingCall = async () => {
  if (!incomingCallRequest.value || isIncomingCallHandling.value) return;
  isIncomingCallHandling.value = true;
  try {
    await incomingCallRequest.value.accept();
    incomingCallRequest.value = null;
  } finally {
    isIncomingCallHandling.value = false;
  }
};

const rejectIncomingCall = () => {
  if (!incomingCallRequest.value || isIncomingCallHandling.value) return;
  incomingCallRequest.value.reject();
  incomingCallRequest.value = null;
  resetPeerWhenIdle();
};

const handleStream = async (event: StreamEvent) => {
  const { stream: remoteStream, type } = event.detail;
  if (!isCurrentPeer(event.detail.peerId)) return;
  if (type === "desktop") {
    isDesktopActive.value = true;
    isDesktopLocalSharing.value = false;
    desktopStream.value = remoteStream;
    isDesktopCollapsed.value = false;
    await bindDesktopVideo();
  } else if (type === "call") {
    isCallActive.value = true;
    callStream.value = remoteStream;
    startDurationTimer();
    await nextTick();
    if (audioRef.value) {
      audioRef.value.srcObject = remoteStream;
    }
  }
};

const handleDesktopStarted = (event: MediaStartedEvent) => {
  if (!isCurrentPeer(event.detail.peerId)) return;
  if (event.detail.role === "sharer") {
    isDesktopActive.value = true;
    isDesktopLocalSharing.value = true;
    isDesktopShareCollapsed.value = false;
    return;
  }
  isDesktopActive.value = true;
  isDesktopLocalSharing.value = false;
  isDesktopCollapsed.value = false;
};

const handleCallStarted = (event: MediaStartedEvent) => {
  if (!isCurrentPeer(event.detail.peerId)) return;
  isCallActive.value = true;
  isCallCollapsed.value = false;
  incomingCallRequest.value = null;
  startDurationTimer();
};

const handleMediaEnded = (event: MediaEndedEvent) => {
  const { type } = event.detail;
  if (!isCurrentPeer(event.detail.peerId)) return;
  if (type === "desktop") {
    isDesktopActive.value = false;
    isDesktopLocalSharing.value = false;
    desktopStream.value = null;
    isDesktopCollapsed.value = false;
    isDesktopShareCollapsed.value = false;
    if (videoRef.value) {
      videoRef.value.srcObject = null;
    }
    message.info("远程桌面共享已结束");
    if (!isCallActive.value) {
      stopDurationTimer();
    }
  } else if (type === "call") {
    isCallActive.value = false;
    callStream.value = null;
    isCallCollapsed.value = false;
    incomingCallRequest.value = null;
    if (audioRef.value) {
      audioRef.value.srcObject = null;
    }
    stopDurationTimer();
    message.info("语音通话已结束");
  }
  resetPeerWhenIdle();
};

const endDesktop = () => {
  peer.endMedia(getMediaPeerId(), "desktop");
};

const endCall = () => {
  peer.endMedia(getMediaPeerId(), "call");
  stopDurationTimer();
};

const toggleCallMuted = () => {
  isCallMuted.value = !isCallMuted.value;
  if (audioRef.value) {
    audioRef.value.muted = isCallMuted.value;
  }
};

const toggleFullscreen = async () => {
  if (!videoContainer.value) return;
  try {
    if (!isFullscreen.value) {
      if (videoContainer.value.requestFullscreen) {
        await videoContainer.value.requestFullscreen();
      }
    } else {
      if (document.exitFullscreen) {
        await document.exitFullscreen();
      }
    }
  } catch {
    message.error("切换全屏失败");
  }
};

const handleFullscreenChange = () => {
  isFullscreen.value = !!document.fullscreenElement;
};

const streamListener: EventListener = (event) => {
  handleStream(event as StreamEvent);
};
const mediaEndedListener: EventListener = (event) => {
  handleMediaEnded(event as MediaEndedEvent);
};
const desktopStartedListener: EventListener = (event) => {
  handleDesktopStarted(event as MediaStartedEvent);
};
const callStartedListener: EventListener = (event) => {
  handleCallStarted(event as MediaStartedEvent);
};
const mediaRequestListener: EventListener = (event) => {
  handleMediaRequest(event as MediaRequestEvent);
};

onMounted(() => {
  peer.on("media-request", mediaRequestListener);
  peer.on("stream", streamListener);
  peer.on("desktop-started", desktopStartedListener);
  peer.on("call-started", callStartedListener);
  peer.on("media-ended", mediaEndedListener);
  document.addEventListener("fullscreenchange", handleFullscreenChange);
});

onUnmounted(() => {
  peer.off("media-request", mediaRequestListener);
  peer.off("stream", streamListener);
  peer.off("desktop-started", desktopStartedListener);
  peer.off("call-started", callStartedListener);
  peer.off("media-ended", mediaEndedListener);
  document.removeEventListener("fullscreenchange", handleFullscreenChange);
  stopDurationTimer();
  desktopStream.value?.getTracks().forEach((track) => track.stop());
  callStream.value?.getTracks().forEach((track) => track.stop());
});
</script>

<style scoped>
.panel-slide-enter-active,
.panel-slide-leave-active {
  transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
.panel-slide-enter-from,
.panel-slide-leave-to {
  transform: translateX(100%);
}

.tab-slide-enter-active,
.tab-slide-leave-active {
  transition:
    transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    opacity 0.3s ease;
}
.tab-slide-enter-from,
.tab-slide-leave-to {
  transform: translateX(100%);
  opacity: 0;
}

/* Desktop Overlay - Full Screen */
.desktop-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
  background: #0a0a0a;
  display: flex;
  flex-direction: column;
  color: #fff;
}

.overlay-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
  background: rgba(0, 0, 0, 0.9);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  flex-shrink: 0;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
  font-weight: 500;
  color: #e0e0e0;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.header-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  background: transparent;
  color: #ccc;
  font-size: 13px;
  cursor: pointer;
  transition: all 0.2s;
}
.header-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  border-color: rgba(255, 255, 255, 0.3);
}
.header-btn.danger:hover {
  background: rgba(245, 34, 45, 0.15);
  border-color: #f5222d;
  color: #f5222d;
}

.duration-text {
  font-size: 12px;
  color: #666;
  font-variant-numeric: tabular-nums;
}

.overlay-body {
  flex: 1;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.desktop-side-toggle {
  position: absolute;
  right: 0;
  top: 50%;
  z-index: 1001;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 56px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-right: none;
  border-radius: 10px 0 0 10px;
  background: rgba(0, 0, 0, 0.72);
  color: #d9d9d9;
  cursor: pointer;
  transform: translateY(-50%);
  transition: all 0.2s;
}
.desktop-side-toggle:hover {
  width: 38px;
  background: rgba(25, 25, 25, 0.92);
  color: #fff;
}

.video-wrapper {
  width: 100%;
  height: 100%;
}

video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  color: #888;
  font-size: 14px;
}

.spin-icon {
  animation: spin 1.5s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* Desktop Call Bar */
.desktop-call-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 20px;
  background: rgba(0, 0, 0, 0.85);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  flex-shrink: 0;
}

.call-bar-info {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: #aaa;
}

.call-duration-text {
  color: #666;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.call-bar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.bar-action-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  background: transparent;
  color: #ccc;
  font-size: 12px;
  cursor: pointer;
  transition: all 0.2s;
}
.bar-action-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
}
.bar-action-btn.is-muted {
  background: rgba(250, 173, 20, 0.15);
  border-color: #faad14;
  color: #faad14;
}
.bar-action-btn.danger:hover {
  background: rgba(245, 34, 45, 0.15);
  border-color: #f5222d;
  color: #f5222d;
}

.desktop-collapsed-tab {
  position: fixed;
  right: 16px;
  bottom: 84px;
  z-index: 1002;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  background: linear-gradient(145deg, #1b2332, #121821);
  border: none;
  border-radius: 50%;
  color: #40a9ff;
  cursor: pointer;
  box-shadow:
    0 4px 16px rgba(0, 0, 0, 0.4),
    0 0 0 1px rgba(255, 255, 255, 0.08);
  transition: all 0.25s;
}
.desktop-collapsed-tab:hover {
  transform: scale(1.08);
}

.desktop-collapsed-tab.is-stacked {
  bottom: 372px;
}

.desktop-collapsed-tab .sharing-status-dot {
  position: absolute;
  right: 7px;
  top: 7px;
  width: 7px;
  height: 7px;
}

.desktop-sharing-panel {
  position: fixed;
  right: 24px;
  bottom: 24px;
  width: 300px;
  z-index: 1002;
  overflow: hidden;
  color: #fff;
  background: linear-gradient(145deg, #1b2332, #121821);
  border-radius: 14px;
  box-shadow:
    0 8px 28px rgba(0, 0, 0, 0.42),
    0 0 0 1px rgba(255, 255, 255, 0.08);
}

.sharing-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 13px 14px;
  background: rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.sharing-panel-title {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 14px;
  font-weight: 500;
  color: #e8e8e8;
}

.sharing-panel-title svg {
  color: #40a9ff;
}

.sharing-panel-body {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 14px;
  font-size: 13px;
  color: #cfcfcf;
}

.sharing-status-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #52c41a;
  box-shadow: 0 0 0 5px rgba(82, 196, 26, 0.14);
  flex-shrink: 0;
}

.desktop-sharing-tab {
  position: fixed;
  right: 16px;
  bottom: 84px;
  z-index: 1002;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border: none;
  border-radius: 50%;
  background: linear-gradient(145deg, #1b2332, #121821);
  color: #40a9ff;
  cursor: pointer;
  box-shadow:
    0 4px 16px rgba(0, 0, 0, 0.4),
    0 0 0 1px rgba(255, 255, 255, 0.08);
  transition: all 0.25s;
}

.desktop-sharing-tab:hover {
  transform: scale(1.08);
}

.desktop-sharing-tab.is-stacked {
  bottom: 372px;
}

.desktop-sharing-tab .sharing-status-dot {
  position: absolute;
  right: 7px;
  top: 7px;
  width: 7px;
  height: 7px;
}

/* Call-Only Floating Panel (expanded) */
.call-floating-panel {
  position: fixed;
  right: 24px;
  bottom: 24px;
  width: 320px;
  z-index: 1002;
  background: linear-gradient(145deg, #1a1a2e, #16213e);
  border-radius: 16px;
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.5),
    0 0 0 1px rgba(255, 255, 255, 0.06);
  overflow: hidden;
  color: #fff;
}

.call-floating-panel.is-stacked {
  bottom: 148px;
}

.incoming-call-panel .call-panel-body {
  padding-bottom: 20px;
}

.incoming-call-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  padding: 0 24px 22px;
}

.incoming-action-btn {
  height: 42px;
  border: none;
  border-radius: 8px;
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
}

.incoming-action-btn:disabled {
  cursor: not-allowed;
  opacity: 0.65;
}

.incoming-action-btn.reject {
  background: rgba(255, 255, 255, 0.1);
  color: #d9d9d9;
}

.incoming-action-btn.reject:hover:not(:disabled) {
  background: rgba(245, 34, 45, 0.2);
  color: #ff7875;
}

.incoming-action-btn.accept {
  background: #52c41a;
}

.incoming-action-btn.accept:hover:not(:disabled) {
  background: #73d13d;
}

.call-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  background: rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.panel-header-left {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 500;
}

.panel-header-icon {
  display: flex;
  color: #52c41a;
}

.panel-header-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}

.panel-icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.06);
  color: #888;
  cursor: pointer;
  transition: all 0.2s;
}
.panel-icon-btn:hover {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}
.panel-icon-btn:last-child:hover {
  background: rgba(245, 34, 45, 0.2);
  color: #f5222d;
}

.call-panel-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 32px 24px 24px;
  gap: 8px;
}

.call-status-icon {
  width: 72px;
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(82, 196, 26, 0.1);
  border-radius: 50%;
  color: #52c41a;
  animation: pulse 2s ease-in-out infinite;
}

@keyframes pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(82, 196, 26, 0.3);
  }
  50% {
    box-shadow: 0 0 0 12px rgba(82, 196, 26, 0);
  }
}

.call-status-text {
  font-size: 15px;
  color: #ddd;
  margin-top: 8px;
}

.call-duration {
  font-size: 32px;
  font-weight: 300;
  font-variant-numeric: tabular-nums;
  color: #fff;
  letter-spacing: 2px;
  margin-top: 4px;
}

.call-panel-footer {
  display: flex;
  justify-content: center;
  gap: 24px;
  padding: 16px 24px 20px;
}

.control-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  transition: all 0.25s;
}

.mute-btn {
  background: rgba(255, 255, 255, 0.08);
  color: #ccc;
}
.mute-btn:hover {
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
}
.mute-btn.is-muted {
  background: rgba(250, 173, 20, 0.2);
  color: #faad14;
}
.mute-btn.is-muted:hover {
  background: rgba(250, 173, 20, 0.3);
}

.end-call-btn {
  background: #f5222d;
  color: #fff;
  transform: rotate(135deg);
}
.end-call-btn:hover {
  background: #ff4d4f;
  transform: rotate(135deg) scale(1.05);
}

/* Call Collapsed Button (right edge, bottom) */
.call-collapsed-btn {
  position: fixed;
  right: 16px;
  bottom: 24px;
  z-index: 1002;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border: none;
  border-radius: 50%;
  background: linear-gradient(135deg, #1a1a2e, #16213e);
  color: #52c41a;
  cursor: pointer;
  box-shadow:
    0 4px 16px rgba(0, 0, 0, 0.4),
    0 0 0 1px rgba(255, 255, 255, 0.08);
  transition: all 0.25s;
}
.call-collapsed-btn:hover {
  transform: scale(1.08);
  box-shadow:
    0 6px 24px rgba(0, 0, 0, 0.5),
    0 0 0 1px rgba(255, 255, 255, 0.12);
}

.call-collapsed-btn.is-stacked {
  bottom: 148px;
}

.call-collapsed-pulse {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: 50%;
  background: rgba(82, 196, 26, 0.15);
  animation: callPulse 2s ease-in-out infinite;
  pointer-events: none;
}

@keyframes callPulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.6;
  }
  50% {
    transform: scale(1.3);
    opacity: 0;
  }
}

@media screen and (max-width: 768px) {
  .call-floating-panel {
    right: 12px;
    bottom: 12px;
    width: 280px;
  }
  .call-panel-body {
    padding: 24px 20px 20px;
  }
  .call-duration {
    font-size: 26px;
  }
  .control-btn {
    width: 46px;
    height: 46px;
  }
  .overlay-header {
    padding: 10px 14px;
  }
  .header-btn span {
    display: none;
  }
  .desktop-call-bar {
    flex-direction: column;
    gap: 8px;
    padding: 10px 14px;
  }
  .desktop-collapsed-tab {
    width: 48px;
    height: 44px;
    padding: 0;
  }
  .call-collapsed-btn {
    right: 12px;
    bottom: 16px;
    width: 42px;
    height: 42px;
  }
}
</style>
