<template>
  <div class="h-[calc(100vh-56px)] flex flex-col lg:flex-row">
    <!-- 窄屏：顶部栏显示房间号与退出 -->
    <div
      class="lg:hidden flex items-center justify-between px-4 py-2 border-b border-slate-200 bg-white shrink-0"
    >
      <span class="font-mono font-semibold text-slate-900">房间 {{ roomCode }}</span>
      <BaseButton size="sm" variant="danger" @click="handleLeave">
        退出
      </BaseButton>
    </div>

    <!-- 左侧 RoomPanel：房间号、在线用户、退出/清空/导出 -->
    <div class="hidden lg:flex lg:w-80 lg:shrink-0">
      <RoomPanel
        :room-code="roomCode"
        :user-list="wsStore.userList"
        :connection-status="wsStore.status"
        :my-user-id="wsStore.myUserId"
        @leave="handleLeave"
        @clear-history="handleClearHistory"
        @export-json="handleExportJson"
        @export-text="handleExportText"
      />
    </div>

    <!-- 右侧消息与输入区域 -->
    <section class="flex-1 flex flex-col bg-slate-100/80 min-w-0">
      <div ref="messageListRef" class="flex-1 overflow-auto px-4 sm:px-6 py-4">
        <div class="max-w-2xl mx-auto space-y-4">
          <template v-for="(msg, index) in wsStore.roomMessages" :key="messageKey(msg, index)">
            <SystemMessage
              v-if="msg.type === 'SYSTEM' && getSystemMessageText(msg)"
              :message="getSystemMessageText(msg)!"
            />
            <MessageItem
              v-else-if="msg.type === 'TEXT'"
              :content="msg.content ?? ''"
              :sender-name="msg.senderName ?? resolveSenderName(msg.senderId)"
              :sender-id="msg.senderId"
              :timestamp="msg.timestamp"
              :is-me="msg.senderId === wsStore.myUserId"
            />
            <!-- 图片消息（IMAGE 类型或 FILE 类型但 mimeType 为图片） -->
            <ImageMessage
              v-else-if="isImageMessage(msg)"
              :image-src="getImageSrc(msg)"
              :file-name="msg.fileName"
              :sender-name="msg.senderName ?? resolveSenderName(msg.senderId)"
              :sender-id="msg.senderId"
              :timestamp="msg.timestamp"
              :is-me="msg.senderId === wsStore.myUserId"
              :status="getFileStatus(msg)"
              :progress="wsStore.getFileProgress(msg.fileId ?? '')"
              @download="handleImageDownload(msg)"
            />
            <!-- 普通文件消息 -->
            <FileMessage
              v-else-if="msg.type === 'FILE'"
              :file-name="msg.fileName ?? '未命名'"
              :file-size="msg.fileSize ?? 0"
              :sender-name="msg.senderName ?? resolveSenderName(msg.senderId)"
              :is-me="msg.senderId === wsStore.myUserId"
              :status="getFileStatus(msg)"
              :progress="wsStore.getFileProgress(msg.fileId ?? '')"
              @download="handleFileDownload(msg)"
            />
          </template>
        </div>
      </div>

      <MessageInput @send="handleSend" @file-selected="handleFileSelected" />

      <!-- 下载提示 Toast（无 URL 时说明原因） -->
      <Transition name="fade">
        <div
          v-if="downloadToast"
          class="fixed bottom-20 left-1/2 -translate-x-1/2 rounded-[var(--dt-radius-card)] border border-slate-200 bg-white px-4 py-2 text-sm text-slate-700 shadow-elevated"
          role="status"
        >
          {{ downloadToast }}
        </div>
      </Transition>
    </section>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import BaseButton from '@/components/ui/BaseButton.vue';
import RoomPanel from '@/components/RoomPanel.vue';
import SystemMessage from '@/components/SystemMessage.vue';
import MessageItem from '@/components/MessageItem.vue';
import FileMessage from '@/components/FileMessage.vue';
import ImageMessage from '@/components/ImageMessage.vue';
import MessageInput from '@/components/MessageInput.vue';
import { getFileDownloadUrl, downloadWithProgress, getMyIp } from '@/api/room';
import { useWsStore } from '@/stores/wsStore';
import type { RoomMessagePayload } from '@/types/room';
import { isImageMimeType } from '@/types/room';

// 开发时用空字符串走同源，由 Vite 代理到后端，便于其它设备通过本机 IP:5173 访问
const API_BASE = import.meta.env.VITE_API_BASE ?? (import.meta.env.DEV ? '' : 'http://localhost:8080');

const route = useRoute();
const router = useRouter();
const roomCode = route.params.roomCode as string;

const messageListRef = ref<HTMLElement | null>(null);
const wsStore = useWsStore();
const downloadToast = ref('');
let downloadToastTimer: ReturnType<typeof setTimeout> | null = null;

function showDownloadToast(message: string) {
  downloadToast.value = message;
  if (downloadToastTimer) clearTimeout(downloadToastTimer);
  downloadToastTimer = setTimeout(() => {
    downloadToast.value = '';
    downloadToastTimer = null;
  }, 3000);
}

onMounted(() => {
  wsStore.init(API_BASE, '/ws');
  wsStore.connect();
});

watch(
  () => wsStore.status,
  async (status) => {
    if (status === 'connected' && roomCode) {
      try {
        const ip = await getMyIp(API_BASE);
        wsStore.joinRoom({ roomCode, nickname: ip?.trim() || '访客' });
      } catch {
        wsStore.joinRoom({ roomCode, nickname: '访客' });
      }
    }
  },
  { immediate: true },
);

function getSystemMessageText(msg: RoomMessagePayload): string | undefined {
  if (msg.type !== 'SYSTEM' || !msg.data) return undefined;
  const data = msg.data as { message?: string };
  return data.message;
}

function messageKey(msg: RoomMessagePayload, index: number): string {
  if ((msg.type === 'FILE' || msg.type === 'IMAGE') && msg.fileId)
    return `file-${msg.fileId}`;
  if (msg.timestamp && msg.senderId)
    return `${msg.type}-${msg.senderId}-${msg.timestamp}-${index}`;
  return `msg-${index}`;
}

function resolveSenderName(senderId?: string): string {
  if (!senderId) return '未知';
  if (senderId === wsStore.myUserId) return wsStore.myNickname;
  const user = wsStore.userList.find((u) => u.userId === senderId);
  return user?.nickname ?? senderId.slice(-8);
}

function getFileStatus(msg: RoomMessagePayload): 'sending' | 'receiving' | 'done' | 'error' {
  const fileId = msg.fileId ?? '';
  const progress = wsStore.getFileProgress(fileId);
  const isMe = msg.senderId === wsStore.myUserId;
  // 发送方：0～99 显示「发送中」
  if (isMe && progress >= 0 && progress < 100) return 'sending';
  // 接收方：仅当已点击下载（isDownloading）且 0～99 时显示「接收中」，否则显示「下载」按钮
  if (!isMe && progress >= 0 && progress < 100 && wsStore.isDownloading(fileId)) return 'receiving';
  return 'done';
}

/**
 * 判断消息是否为图片类型
 * - IMAGE 类型（小图直发）
 * - FILE 类型但 mimeType 为 image/*
 */
function isImageMessage(msg: RoomMessagePayload): boolean {
  if (msg.type === 'IMAGE') return true;
  if (msg.type === 'FILE' && isImageMimeType(msg.mimeType)) return true;
  return false;
}

/**
 * 获取图片消息的显示 URL
 */
function getImageSrc(msg: RoomMessagePayload): string | undefined {
  const fileId = msg.fileId ?? '';
  // 优先从 store 获取（包含接收完成的 blob URL 和小图直发的 data URL）
  const storeUrl = wsStore.getImageUrl(fileId);
  if (storeUrl) return storeUrl;
  // 如果是 IMAGE 类型且有 imageData，直接构造 data URL
  if (msg.type === 'IMAGE' && msg.imageData) {
    const mimeType = msg.mimeType ?? 'image/png';
    return msg.imageData.startsWith('data:')
      ? msg.imageData
      : `data:${mimeType};base64,${msg.imageData}`;
  }
  return undefined;
}

async function handleFileSelected(files: File[]) {
  for (const file of files) {
    const result = await wsStore.sendFile(roomCode, file);
    if (!result.ok && result.error) {
      showDownloadToast(result.error);
    }
  }
}

/**
 * 下载图片
 */
function handleImageDownload(msg: RoomMessagePayload) {
  const fileId = msg.fileId ?? '';
  const fileName = msg.fileName ?? 'image.png';
  const imageSrc = getImageSrc(msg);

  if (!imageSrc) {
    const isMe = msg.senderId === wsStore.myUserId;
    showDownloadToast(
      isMe
        ? '您发送的图片请从本机获取'
        : '无法下载：图片未就绪或来自历史记录',
    );
    return;
  }

  // 创建下载链接
  const a = document.createElement('a');
  a.href = imageSrc;
  a.download = fileName;
  a.style.display = 'none';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}

async function handleFileDownload(msg: RoomMessagePayload) {
  const fileId = msg.fileId ?? '';
  if (!fileId) {
    showDownloadToast('无法下载：文件信息不完整');
    return;
  }
  const fileName = msg.fileName ?? 'download';

  // 服务器存储文件：走 HTTP 下载，带进度
  if (wsStore.isServerFile(msg)) {
    const url = getFileDownloadUrl(roomCode, fileId);
    wsStore.setDownloading(fileId, true);
    wsStore.setFileProgress(fileId, 0);
    try {
      const blob = await downloadWithProgress(url, (percent) => {
        wsStore.setFileProgress(fileId, percent);
      });
      wsStore.setFileProgress(fileId, 100);
      const blobUrl = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = blobUrl;
      a.download = fileName;
      a.style.display = 'none';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      setTimeout(() => URL.revokeObjectURL(blobUrl), 500);
    } catch {
      wsStore.setFileProgress(fileId, 100);
      showDownloadToast('下载失败，请重试');
    } finally {
      wsStore.setDownloading(fileId, false);
    }
    return;
  }

  // 兼容：历史或 CHUNK 流文件，从 blob URL 下载
  const url = wsStore.getFileBlobUrl(fileId);
  if (!url) {
    const isMe = msg.senderId === wsStore.myUserId;
    showDownloadToast(
      isMe
        ? '您发送的文件请从本机获取，此处不提供下载'
        : '无法下载：文件未就绪或来自历史记录（需在当前会话内接收完成）',
    );
    return;
  }
  const a = document.createElement('a');
  a.href = url;
  a.download = fileName;
  a.style.display = 'none';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  setTimeout(() => wsStore.revokeFileBlobUrl(fileId), 500);
}

function handleSend(content: string) {
  if (!content.trim()) return;
  wsStore.sendRoomMessage(roomCode, content);
}

function handleLeave() {
  wsStore.leaveRoom(roomCode);
  wsStore.disconnect();
  router.push({ name: 'home' });
}

function handleClearHistory() {
  if (!confirm('确定清空当前房间的本地历史记录吗？')) return;
  wsStore.clearRoomHistory(roomCode);
}

function handleExportJson() {
  const url = wsStore.exportRoomHistory(roomCode);
  const a = document.createElement('a');
  a.href = url;
  a.download = `DataTool-${roomCode}-${Date.now()}.json`;
  a.click();
  URL.revokeObjectURL(url);
}

function handleExportText() {
  const url = wsStore.exportRoomHistoryAsText(roomCode);
  const a = document.createElement('a');
  a.href = url;
  a.download = `DataTool-${roomCode}-${Date.now()}.txt`;
  a.click();
  URL.revokeObjectURL(url);
}
</script>
