<template>
  <view class="page">
    <scroll-view
      scroll-y
      class="page-scroll"
      :scroll-top="pageScrollTop"
      :scroll-with-animation="true"
      :lower-threshold="80"
      @scrolltolower="onScrollToLower"
    >
      <view class="card">
      <view class="header">
        <view class="header-main">
          <view class="name-row">
            <text class="name">{{ archive.name || '-' }}</text>
            <text v-if="sexOrAge" class="meta">{{ sexOrAge }}</text>
          </view>

          <view v-if="idRows.length" class="id-rows">
            <view v-for="row in idRows" :key="row.label" class="id-row">
              <text class="id-label">{{ row.label }}：</text>
              <text class="id-value">{{ row.value }}</text>
            </view>
          </view>

          <view v-if="createText" class="create-row">
            <text class="create-text">{{ createText }}</text>
          </view>
        </view>

        <view class="header-right" @click="goEdit">
          <uni-icons type="right" size="18" color="#bbb" />
        </view>
      </view>

      <view class="cells">
        <!-- 联系电话 -->
        <view class="info-row border-bottom">
          <text class="input-label">联系电话</text>
          <view class="info-right">
            <template v-if="archive.mobile">
              <view class="phone-area" @click="makeCall">
                <uni-icons type="phone-filled" size="18" color="#0877F1" class="mr-4" />
                <text class="phone-text">{{ archive.mobile }}</text>
              </view>
              <view class="edit-icon" @click.stop="openContact">
                <uni-icons type="compose" size="20" color="#0877F1" />
              </view>
            </template>
            <view v-else class="empty-click" @click="openContact">
              <text class="placeholder">添加联系电话</text>
            </view>
          </view>
        </view>

        <!-- 备注 -->
        <view class="info-block border-bottom">
          <view class="block-header">
            <text class="input-label">备注</text>
            <view class="edit-icon" @click.stop="openNotes">
              <uni-icons type="compose" size="20" color="#0877F1" />
            </view>
          </view>
          <view class="block-content">
            <text v-if="archive.notes" class="note-content">{{ archive.notes }}</text>
            <view v-else class="empty-click" @click="openNotes">
              <text class="placeholder">添加备注</text>
            </view>
          </view>
        </view>

        <!-- 分组 -->
        <view class="info-block">
          <view class="block-header">
            <text class="input-label">分组</text>
            <view class="edit-icon" @click.stop="openGroups">
              <uni-icons type="compose" size="20" color="#0877F1" />
            </view>
          </view>
          <view class="block-content">
            <view v-if="archiveGroupNames.length" class="tags-wrap">
              <view v-for="tag in archiveGroupNames" :key="tag" class="tag-item">
                {{ tag }}
              </view>
            </view>
            <view v-else class="empty-click" @click="openGroups">
              <text class="placeholder">添加分组</text>
            </view>
          </view>
        </view>
      </view>
      </view>

      <view id="tabs-anchor" class="tabs-anchor"></view>
      <view class="tabs">
      <view
        v-for="t in tabs"
        :key="t.key"
        class="tab"
        :class="{ active: currentTab === t.key }"
        @click="switchTab(t.key)"
      >
        {{ t.title }}
      </view>
      </view>

      <view class="content">
      <HealthProfileTab
        v-if="currentTab === 'visitRecord'"
        :data="archive"
        :archiveId="archiveId"
        :floatingBottom="floatingBottom"
      />
      <ServiceInfoTab
        v-else-if="currentTab === 'serviceRecord'"
        :data="archive"
        :archiveId="archiveId"
        :reachBottomTime="reachBottomTime"
        :floatingBottom="floatingBottom"
      />
      <FollowUpManageTab
        v-else
        :data="archive"
        :archiveId="archiveId"
        :reachBottomTime="reachBottomTime"
        :floatingBottom="floatingBottom"
        :fromChat="fromChat"
      />
      </view>

      <view class="scroll-spacer" />
    </scroll-view>

    <view v-if="showGoChat" class="footer">
      <button class="bind-btn" @click="goChat">
        <uni-icons type="chat-filled" size="18" color="#fff" />
        <text class="bind-text">去聊天</text>
      </button>
    </view>

    <!-- 修改联系电话（居中弹窗） -->
    <uni-popup ref="contactPopup" type="center">
      <view class="modal">
        <view class="modal-title">修改联系电话</view>
        <view class="modal-body">
          <input class="modal-input" v-model="contactInput" type="number" placeholder="请输入联系电话" />
        </view>
        <view class="modal-actions">
          <view class="modal-btn cancel" @click="closeContact">取消</view>
          <view class="modal-btn save" @click="saveContact">保存</view>
        </view>
      </view>
    </uni-popup>

    <!-- 修改备注（底部弹层） -->
    <uni-popup ref="notesPopup" type="bottom">
      <view class="sheet">
        <view class="sheet-header">
          <view class="sheet-header-left" />
          <view class="sheet-title">修改备注</view>
          <view class="sheet-close" @click="closeNotes">
            <uni-icons type="closeempty" size="18" color="#333" />
          </view>
        </view>

        <view class="sheet-body">
          <textarea
            v-model="notesInput"
            class="notes-textarea"
            placeholder="请输入备注"
            :maxlength="100"
          />
          <view class="counter">{{ notesInput.length }}/100</view>
        </view>

        <view class="sheet-footer">
          <button class="primary-btn" @click="saveNotes">保存</button>
        </view>
      </view>
    </uni-popup>

    <!-- 选择分组（底部弹层） -->
    <uni-popup ref="groupPopup" type="bottom">
      <view class="sheet">
        <view class="sheet-header">
          <view class="sheet-close" @click="closeGroups">
            <uni-icons type="closeempty" size="18" color="#333" />
          </view>
          <view class="sheet-title">选择分组</view>
          <view class="sheet-link" @click="openAddGroup">添加分组</view>
        </view>

        <view class="group-list">
          <view v-for="g in teamGroups" :key="g._id" class="group-item" @click="toggleGroup(String(g._id))">
            <uni-icons
              :type="selectedGroupMap[String(g._id)] ? 'checkbox-filled' : 'checkbox'"
              size="20"
              :color="selectedGroupMap[String(g._id)] ? '#0877F1' : '#c7c7c7'"
            />
            <text class="group-name">{{ g.groupName }}</text>
          </view>
        </view>

        <view class="sheet-footer">
          <button class="primary-btn" @click="saveGroups">保存</button>
        </view>
      </view>
    </uni-popup>

    <!-- 添加新分组（居中弹窗） -->
    <uni-popup ref="addGroupPopup" type="center">
      <view class="modal">
        <view class="modal-title">添加新分组</view>
        <view class="modal-body">
          <input class="modal-input" v-model="newGroupName" placeholder="请输入分组名称" />
        </view>
        <view class="modal-actions">
          <view class="modal-btn cancel" @click="closeAddGroup">取消</view>
          <view class="modal-btn save" @click="saveAddGroup">保存</view>
        </view>
      </view>
    </uni-popup>
  </view>
</template>

<script setup>
import { computed, getCurrentInstance, nextTick, ref } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import { storeToRefs } from 'pinia';
import dayjs from 'dayjs';

import HealthProfileTab from '@/pages/case/components/archive-detail/health-profile-tab.vue';
import ServiceInfoTab from '@/pages/case/components/archive-detail/service-info-tab.vue';
import FollowUpManageTab from '@/pages/case/components/archive-detail/follow-up-manage-tab.vue';
import api from '@/utils/api';
import useAccountStore from '@/store/account';
import { hideLoading, loading, toast } from '@/utils/widget';

const STORAGE_KEY = 'ykt_case_archive_detail';
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
const NEED_RELOAD_STORAGE_KEY = 'ykt_case_need_reload';

const tabs = [
  { key: 'visitRecord', title: '病历记录' },
  { key: 'followUp', title: '回访任务' },
  { key: 'serviceRecord', title: '服务记录' }
];

const currentTab = ref('visitRecord');
const reachBottomTime = ref(0);
const archiveId = ref('');
const fromChat = ref(false);
const pageScrollTop = ref(0);
const instanceProxy = getCurrentInstance()?.proxy;

function scrollTabsToTop() {
  const q = instanceProxy ? uni.createSelectorQuery().in(instanceProxy) : uni.createSelectorQuery();
  q.select('.page-scroll').boundingClientRect();
  q.select('#tabs-anchor').boundingClientRect();
  q.select('.page-scroll').scrollOffset();
  q.exec((res) => {
    const scrollRect = res && res[0];
    const anchorRect = res && res[1];
    const viewport = res && res[2];
    if (!scrollRect || !anchorRect || !viewport) return;

    const delta = Number(anchorRect.top || 0) - Number(scrollRect.top || 0);
    const target = Number(viewport.scrollTop || 0) + delta;
    // scrollTop 值相同可能不会触发滚动，轻微抖动保证生效
    if (pageScrollTop.value === target) pageScrollTop.value = target + 1;
    pageScrollTop.value = target;
  });
}

function switchTab(key) {
  currentTab.value = key;
  // 切换 tab 后，将 tab 滚动到页面顶部（隐藏头部信息区域）
  nextTick(() => scrollTabsToTop());
}

const archive = ref({
  name: '',
  sex: '',
  age: '',
  avatar: '',
  mobile: '',
  outpatientNo: '',
  inpatientNo: '',
  medicalRecordNo: '',
  createTime: '',
  creator: '',
  createdByDoctor: true,
  hasBindWechat: false,
  chatGroupId: '',
  notes: '',
  groupIds: []
});

const accountStore = useAccountStore();
const { account, doctorInfo } = storeToRefs(accountStore);
const { getDoctorInfo } = accountStore;

function getUserId() {
  const d = doctorInfo.value || {};
  const a = account.value || {};
  return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || '') || '';
}

function getCorpId() {
  const d = doctorInfo.value || {};
  const a = account.value || {};
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  return String(d.corpId || a.corpId || team.corpId || '') || '';
}

function getCurrentTeamId() {
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  return String(team?.teamId || team?._id || team?.id || '') || '';
}

function normalizeGroupId(v) {
  const s = String(v || '').trim();
  if (!s) return '';
  return s.startsWith('GROUP') ? s.slice(5) : s;
}

function normalizeArchiveFromApi(raw) {
  const r = raw && typeof raw === 'object' ? raw : {};
  const next = {
    _id: r._id || archiveId.value,
    name: r.name || '',
    sex: r.sex || r.gender || '',
    age: r.age ?? '',
    avatar: r.avatar || r.avatarUrl || r.headImgUrl || r.headimgurl || r.headImageUrl || r.profilePhoto || r.photoUrl || r.photo || '',
    mobile: r.mobile || r.phone1 || r.phone || '',
    outpatientNo: r.outpatientNo || '',
    inpatientNo: r.inpatientNo || '',
    medicalRecordNo: r.medicalRecordNo || '',
    customerNumber: r.customerNumber || '',
    customerProfileNo2: r.customerProfileNo2 || '',
    customerProfileNo3: r.customerProfileNo3 || '',
    createTime: r.createTime || '',
    creator: r.creator || '',
    notes: r.notes || r.remark || '',
    groupIds: Array.isArray(r.groupIds) ? r.groupIds : [],
    chatGroupId: normalizeGroupId(r.chatGroupId || r.groupId || r.groupID || r.imGroupId || r.imGroupID || r.consultGroupId || ''),
  };
  return next;
}

async function ensureDoctor() {
  if (doctorInfo.value) return;
  if (!account.value?.openid) return;
  try {
    await getDoctorInfo();
  } catch (e) {
    // ignore
  }
}

async function fetchArchive() {
  if (!archiveId.value) return;
  await ensureDoctor();
  loading('加载中...');
  try {
    const prevLocalChatGroupId = normalizeGroupId(chatGroupId.value || archive.value.chatGroupId || '');
    const res = await api('getCustomerByCustomerId', { customerId: archiveId.value });
    if (!res?.success) {
      toast(res?.message || '获取档案失败');
      return;
    }

    const normalized = normalizeArchiveFromApi(res.data);
    // 后端经常不返回 chatGroupId（或为空），但本地已探测出可用群聊时不能被覆盖掉，否则返回页面会导致“去聊天”按钮短暂/持续消失
    if (!normalized.chatGroupId && prevLocalChatGroupId) {
      normalized.chatGroupId = prevLocalChatGroupId;
    }

    archive.value = { ...archive.value, ...normalized };
    saveToStorage();
    loadTeamMembers();
    await fetchTeamGroups(true);
    chatGroupId.value = normalizeGroupId(archive.value.chatGroupId || '');
    if (!chatGroupId.value) {
      await refreshChatRoom({ force: true });
    } else {
      const meta = await getChatRoomMeta(chatGroupId.value);
      const ok = isChatRoomForArchive(meta, archiveId.value);
      const currentTeamId = getCurrentTeamId();
      const metaTeamId = String(meta?.teamId || meta?.team?.teamId || meta?.team?._id || '');
      if (!ok || (currentTeamId && metaTeamId && metaTeamId !== currentTeamId)) {
        chatGroupId.value = '';
        archive.value.chatGroupId = '';
        await refreshChatRoom({ force: true });
      } else {
        archive.value.chatGroupId = chatGroupId.value;
      }
    }
    saveToStorage();
  } catch (e) {
    toast('获取档案失败');
  } finally {
    hideLoading();
  }
}

const userNameMap = ref({});
async function loadTeamMembers() {
  const corpId = getCorpId();
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  const teamId = team?.teamId ? String(team.teamId) : '';
  if (!corpId || !teamId) return;
  if (Object.keys(userNameMap.value || {}).length > 0) return;

  const res = await api('getTeamData', { corpId, teamId });
  if (!res?.success) return;
  const t = res?.data && typeof res.data === 'object' ? res.data : {};
  const members = Array.isArray(t.memberList) ? t.memberList : [];
  userNameMap.value = members.reduce((acc, m) => {
    const uid = String(m?.userid || '');
    if (!uid) return acc;
    acc[uid] = String(m?.anotherName || m?.name || m?.userid || '') || uid;
    return acc;
  }, {});
}

function resolveUserName(userId) {
  const id = String(userId || '');
  if (!id) return '';
  const map = userNameMap.value || {};
  return String(map[id] || '') || '';
}

function formatCreateTime(v) {
  if (v === null || v === undefined) return '';
  const raw = typeof v === 'number' ? v : typeof v === 'string' ? v.trim() : '';
  const ms =
    typeof raw === 'number'
      ? raw
      : raw && /^\d{10,13}$/.test(raw)
        ? Number(raw.length === 10 ? `${raw}000` : raw)
        : null;
  const d = ms !== null ? dayjs(ms) : dayjs(raw);
  return d.isValid() ? d.format('YYYY-MM-DD HH:mm') : '';
}

const teamGroups = ref([]);
const groupNameMap = computed(() => {
  const map = new Map();
  (Array.isArray(teamGroups.value) ? teamGroups.value : []).forEach((g) => {
    if (g && g._id && g.groupName) map.set(String(g._id), String(g.groupName));
  });
  return map;
});

const archiveGroupNames = computed(() => {
  const ids = Array.isArray(archive.value.groupIds) ? archive.value.groupIds : [];
  const map = groupNameMap.value;
  return ids.map((id) => map.get(String(id))).filter(Boolean);
});

function sortGroupList(list) {
  const { orderList, corpList, restList } = (Array.isArray(list) ? list : []).reduce(
    (p, c) => {
      if (typeof c?.sortOrder === 'number') p.orderList.push(c);
      else if (c?.parentGroupId) p.corpList.push(c);
      else p.restList.push(c);
      return p;
    },
    { orderList: [], corpList: [], restList: [] }
  );
  orderList.sort((a, b) => a.sortOrder - b.sortOrder);
  return [...orderList, ...corpList, ...restList];
}

async function fetchTeamGroups(silent = false) {
  const corpId = getCorpId();
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  const teamId = team?.teamId ? String(team.teamId) : '';
  if (!corpId || !teamId) return;
  try {
    const projection = { _id: 1, groupName: 1, parentGroupId: 1, sortOrder: 1 };
    const res = await api('getGroups', { corpId, teamId, page: 1, pageSize: 1000, projection, countGroupMember: false });
    if (!res?.success) {
      if (!silent) toast(res?.message || '获取分组失败');
      teamGroups.value = [];
      return;
    }
    const list = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.data) ? res.data.data : [];
    teamGroups.value = sortGroupList(list);
  } catch (e) {
    if (!silent) toast('获取分组失败');
    teamGroups.value = [];
  }
}

async function updateArchive(patch) {
  const id = String(archiveId.value || '');
  if (!id) return false;
  await ensureDoctor();
  const userId = getUserId();
  const corpId = getCorpId();
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  const createTeamId = team?.teamId ? String(team.teamId) : '';
  const createTeamName = team?.name ? String(team.name) : '';
  if (!userId || !corpId) {
    return false;
  }

  loading('保存中...');
  try {
    const res = await api('updateCustomer', {
      id,
      params: patch,
      userId,
      corpId,
      createTeamId,
      createTeamName,
    });
    if (!res?.success) {
      toast(res?.message || '保存失败');
      return false;
    }
    uni.setStorageSync(NEED_RELOAD_STORAGE_KEY, 1);
    await fetchArchive();
    return true;
  } catch (e) {
    toast('保存失败');
    return false;
  } finally {
    hideLoading();
  }
}

onLoad((options) => {
  archiveId.value = options?.id ? String(options.id) : String(archive.value.medicalRecordNo || archive.value.outpatientNo || archive.value.inpatientNo || '');
  fromChat.value = options?.fromChat === 'true' || options?.fromChat === true;

  const cached = uni.getStorageSync(STORAGE_KEY);
  const cachedObj = cached && typeof cached === 'object' ? cached : null;
  const cachedId = cachedObj ? String(cachedObj._id || cachedObj.id || '') : '';
  const canUseCached = Boolean(cachedObj && (!cachedId || !archiveId.value || cachedId === archiveId.value));
  if (canUseCached) {
    archive.value = {
      ...archive.value,
      ...cached,
      groupIds: Array.isArray(cached.groupIds) ? cached.groupIds : archive.value.groupIds
    };
    chatGroupId.value = normalizeGroupId(archive.value.chatGroupId || '');
  }

  if (!archive.value.mobile) {
    const mobiles = canUseCached && cachedObj && Array.isArray(cachedObj.mobiles) ? cachedObj.mobiles : [];
    if (mobiles.length) archive.value.mobile = String(mobiles[0]);
  }

  if (!archiveId.value) {
    archiveId.value = String(archive.value.medicalRecordNo || archive.value.outpatientNo || archive.value.inpatientNo || `mock_${Date.now()}`);
  }

  // 接口兜底：优先用接口刷新档案详情
  fetchArchive();
});

onShow(() => {
  const cached = uni.getStorageSync(STORAGE_KEY);
  const cachedId = cached && typeof cached === 'object' ? String(cached._id || cached.id || '') : '';
  if (cached && typeof cached === 'object' && (!cachedId || !archiveId.value || cachedId === archiveId.value)) {
    archive.value = {
      ...archive.value,
      ...cached,
      groupIds: Array.isArray(cached.groupIds) ? cached.groupIds : archive.value.groupIds,
    };
    chatGroupId.value = normalizeGroupId(archive.value.chatGroupId || '');
  }
  fetchArchive();
});

function onScrollToLower() {
  reachBottomTime.value = Date.now();
}

const sexOrAge = computed(() => {
  const sex = archive.value.sex ? String(archive.value.sex) : '';
  const age = archive.value.age || archive.value.age === 0 ? `${archive.value.age}岁` : '';
  if (sex && age) return `${sex} ${age}`;
  return sex || age;
});

const idRows = computed(() => {
  const rows = [];
  if (archive.value.customerNumber) rows.push({ label: '病案号1', value: String(archive.value.customerNumber) });
  if (archive.value.customerProfileNo2) rows.push({ label: '病案号2', value: String(archive.value.customerProfileNo2) });
  if (archive.value.customerProfileNo3) rows.push({ label: '病案号3', value: String(archive.value.customerProfileNo3) });
  return rows;
});

const createText = computed(() => {
  const time = formatCreateTime(archive.value.createTime);
  const rawCreator = archive.value.creator ? String(archive.value.creator) : '';
  const creatorId = ['-', '—', '--'].includes(rawCreator.trim()) ? '' : rawCreator.trim();
  const creatorName = creatorId ? resolveUserName(creatorId) : '';
  if (time && creatorName) return `${time}  ${creatorName}创建`;
  if (time && !rawCreator.trim()) return `${time}  患者创建`;
  if (time) return `${time} 创建`;
  if (!rawCreator.trim()) return '患者创建';
  return '';
});

const chatGroupId = ref('');
const currentChatGroupId = computed(() => normalizeGroupId(chatGroupId.value || ''));
const showGoChat = computed(() => Boolean(currentChatGroupId.value));
const floatingBottom = computed(() => (showGoChat.value ? 90 : 16));

// const contactTitle = computed(() => (archive.value.mobile ? '联系方式' : '添加联系电话'));
// const notesTitle = computed(() => (archive.value.notes ? '备注' : '添加备注'));
// const groupTitle = computed(() => (Array.isArray(archive.value.groups) && archive.value.groups.length ? '分组' : '添加分组'));

const saveToStorage = () => {
  uni.setStorageSync(STORAGE_KEY, { ...archive.value });
};

const goEdit = () => {
  uni.navigateTo({ url: `/pages/case/archive-edit?archiveId=${encodeURIComponent(archiveId.value || '')}` });
};

const goChat = async () => {
  let gid = normalizeGroupId(currentChatGroupId.value || '');
  if (!gid) {
    await refreshChatRoom({ force: true });
    gid = normalizeGroupId(currentChatGroupId.value || '');
  }
  if (!gid) {
    toast('暂无可进入的会话');
    return;
  }

  const meta = await getChatRoomMeta(gid);
  const ok = isChatRoomForArchive(meta, archiveId.value);
  const currentTeamId = getCurrentTeamId();
  const metaTeamId = String(meta?.teamId || meta?.team?.teamId || meta?.team?._id || '');
  if (!ok || (currentTeamId && metaTeamId && metaTeamId !== currentTeamId)) {
    chatGroupId.value = '';
    archive.value.chatGroupId = '';
    saveToStorage();
    await refreshChatRoom({ force: true });
    gid = normalizeGroupId(currentChatGroupId.value || '');
  }
  if (!gid) {
    toast('暂无可进入的会话');
    return;
  }

  const conversationID = `GROUP${gid}`;
  uni.navigateTo({
    url: `/pages/message/index?conversationID=${encodeURIComponent(conversationID)}&groupID=${encodeURIComponent(gid)}&fromCase=true`,
  });
};

const isRefreshingChatRoom = ref(false);
let lastRefreshChatRoomAt = 0;
let refreshChatRoomPromise = null;

function isChatRoomForArchive(meta, customerId) {
  const cid = String(meta?.customerId || '');
  const pid = String(meta?.patientId || '');
  const id = String(customerId || '');
  if (!meta || !id) return false;
  return (cid && cid === id) || (pid && pid === id);
}

async function getChatRoomMeta(groupId) {
  const gid = normalizeGroupId(groupId || '');
  if (!gid) return null;
  try {
    const res = await api('getGroupListByGroupId', { groupId: gid }, false);
    if (!res?.success || !res?.data) return null;
    return res.data;
  } catch (e) {
    return null;
  }
}

function parseAnyTimeMs(v) {
  if (v === null || v === undefined) return 0;
  if (typeof v === 'number') return v;
  const s = String(v).trim();
  if (!s) return 0;
  if (/^\d{10,13}$/.test(s)) return Number(s.length === 10 ? `${s}000` : s);
  const d = dayjs(s);
  return d.isValid() ? d.valueOf() : 0;
}

async function refreshChatRoom(options = {}) {
  const force = Boolean(options?.force);
  const customerId = String(archiveId.value || '');
  if (!customerId) return;

  // 如果正在刷新，复用同一个 promise，确保调用方可以 await 到结果
  if (isRefreshingChatRoom.value && refreshChatRoomPromise) {
    await refreshChatRoomPromise;
    return;
  }

  const now = Date.now();
  if (!force && now - lastRefreshChatRoomAt < 5000) return;
  lastRefreshChatRoomAt = now;

  isRefreshingChatRoom.value = true;
  refreshChatRoomPromise = (async () => {
    try {
    const corpId = getCorpId();
    const teamId = getCurrentTeamId();

    const baseQuery = {
      corpId,
      customerId,
      page: 1,
      pageSize: 50,
    };

    const queryWithTeam = teamId ? { ...baseQuery, teamId } : baseQuery;
    let detailRes = await api('getGroupList', queryWithTeam, false);
    let details = Array.isArray(detailRes?.data?.list) ? detailRes.data.list : [];

    if (!details.length && teamId) {
      detailRes = await api('getGroupList', baseQuery, false);
      details = Array.isArray(detailRes?.data?.list) ? detailRes.data.list : [];
    }

    if (!detailRes?.success || !details.length) {
      chatGroupId.value = '';
      archive.value.chatGroupId = '';
      return;
    }

    const currentTeamId = getCurrentTeamId();
    const detailsForCurrentTeam = currentTeamId
      ? details.filter((g) => String(g?.teamId || g?.team?._id || g?.team?.teamId || '') === currentTeamId)
      : [];
    const candidates = detailsForCurrentTeam.length ? detailsForCurrentTeam : details;

    const statusRank = (s) => (s === 'processing' ? 3 : s === 'pending' ? 2 : 1);
    candidates.sort((a, b) => {
      const ra = statusRank(String(a?.orderStatus || ''));
      const rb = statusRank(String(b?.orderStatus || ''));
      if (rb !== ra) return rb - ra;
      const ta = parseAnyTimeMs(a?.updatedAt) || parseAnyTimeMs(a?.createdAt);
      const tb = parseAnyTimeMs(b?.updatedAt) || parseAnyTimeMs(b?.createdAt);
      return tb - ta;
    });

    const best = candidates[0] || {};
    const gid = normalizeGroupId(best.groupId || best.groupID || best.group_id || '');
    if (gid) {
      chatGroupId.value = String(gid);
      archive.value.chatGroupId = chatGroupId.value;
      saveToStorage();
    } else {
      chatGroupId.value = '';
      archive.value.chatGroupId = '';
    }
    } catch (e) {
    // ignore
    } finally {
    isRefreshingChatRoom.value = false;
      refreshChatRoomPromise = null;
    }
  })();

  await refreshChatRoomPromise;
}

const makeCall = () => {
  if (archive.value.mobile) {
    uni.makePhoneCall({ phoneNumber: archive.value.mobile });
  }
};

// ===== 联系电话 =====
const contactPopup = ref(null);
const contactInput = ref('');

const openContact = () => {
  contactInput.value = archive.value.mobile ? String(archive.value.mobile) : '';
  contactPopup.value?.open();
};

const closeContact = () => {
  contactPopup.value?.close();
};

const saveContact = () => {
  const v = String(contactInput.value || '').trim();
  if (!v) {
    uni.showToast({ title: '请输入联系电话', icon: 'none' });
    return;
  }
  updateArchive({ mobile: v }).then((ok) => ok && closeContact());
};

// ===== 备注 =====
const notesPopup = ref(null);
const notesInput = ref('');

const openNotes = () => {
  notesInput.value = archive.value.notes ? String(archive.value.notes) : '';
  notesPopup.value?.open();
};

const closeNotes = () => {
  notesPopup.value?.close();
};

const saveNotes = () => {
  const v = String(notesInput.value || '').trim();
  updateArchive({ notes: v }).then((ok) => ok && closeNotes());
};

// ===== 分组 =====
const groupPopup = ref(null);
const addGroupPopup = ref(null);

const selectedGroupMap = ref({});

const syncSelectedMapFromArchive = () => {
  const current = Array.isArray(archive.value.groupIds) ? archive.value.groupIds.map(String) : [];
  selectedGroupMap.value = current.reduce((acc, id) => {
    acc[String(id)] = true;
    return acc;
  }, {});
};

const openGroups = async () => {
  await fetchTeamGroups(false);
  syncSelectedMapFromArchive();
  groupPopup.value?.open();
};

const closeGroups = () => {
  groupPopup.value?.close();
};

const toggleGroup = (groupId) => {
  const key = String(groupId || '');
  if (!key) return;
  selectedGroupMap.value[key] = !selectedGroupMap.value[key];
};

async function applyGroupChange(nextIds) {
  const memberId = String(archiveId.value || '');
  if (!memberId) return false;
  const prevIds = Array.isArray(archive.value.groupIds) ? archive.value.groupIds.map(String) : [];
  const next = Array.isArray(nextIds) ? nextIds.map(String).filter(Boolean) : [];

  const toAdd = next.filter((id) => !prevIds.includes(id));
  const toRemove = prevIds.filter((id) => !next.includes(id));

  if (toAdd.length === 0 && toRemove.length === 0) return true;

  loading('保存中...');
  try {
    for (const id of toAdd) {
      const res = await api('addGroupIdForMember', { memberId, toGroupId: id });
      if (!res?.success) {
        toast(res?.message || '分组保存失败');
        return false;
      }
    }
    for (const id of toRemove) {
      const res = await api('addGroupIdForMember', { memberId, fromGroupId: id });
      if (!res?.success) {
        toast(res?.message || '分组保存失败');
        return false;
      }
    }
    uni.setStorageSync(NEED_RELOAD_STORAGE_KEY, 1);
    await fetchArchive();
    return true;
  } catch (e) {
    toast('分组保存失败');
    return false;
  } finally {
    hideLoading();
  }
}

const saveGroups = async () => {
  const nextIds = Object.keys(selectedGroupMap.value).filter((k) => selectedGroupMap.value[k]);
  const ok = await applyGroupChange(nextIds);
  if (ok) closeGroups();
};

// 添加新分组
const newGroupName = ref('');

const openAddGroup = () => {
  newGroupName.value = '';
  addGroupPopup.value?.open();
};

const closeAddGroup = () => {
  addGroupPopup.value?.close();
};

const saveAddGroup = async () => {
  const name = String(newGroupName.value || '').trim();
  if (!name) {
    uni.showToast({ title: '请输入分组名称', icon: 'none' });
    return;
  }
  const exists = (Array.isArray(teamGroups.value) ? teamGroups.value : []).some((g) => String(g?.groupName || '').trim() === name);
  if (exists) {
    uni.showToast({ title: '该分组已存在', icon: 'none' });
    return;
  }

  const corpId = getCorpId();
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  const teamId = team?.teamId ? String(team.teamId) : '';
  const creator = getUserId();
  if (!corpId || !teamId || !creator) {
    return;
  }

  loading('保存中...');
  try {
    const params = { groupName: name, teamId, groupType: 'team', creator };
    const res = await api('createGroup', { corpId, teamId, params });
    if (!res?.success) {
      toast(res?.message || '新增分组失败');
      return;
    }
    await fetchTeamGroups(true);
    // 自动选中新建分组（后续在“保存”时调用 addGroupIdForMember）
    const newId = res.data ? String(res.data) : '';
    if (newId) selectedGroupMap.value[newId] = true;
    uni.setStorageSync('ykt_case_groups_need_reload', 1);
    closeAddGroup();
  } catch (e) {
    toast('新增分组失败');
  } finally {
    hideLoading();
  }
};
</script>

<style lang="scss" scoped>
.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f5f6f8;
  overflow: hidden;
}

.page-scroll {
  flex: 1;
  min-height: 0;
}

.card {
  background: #fff;
  margin-bottom: 20rpx;
}

.header {
  display: flex;
  align-items: flex-start;
  padding: 28rpx 28rpx 20rpx;
  border-bottom: 2rpx solid #f2f2f2;
}

.header-main {
  flex: 1;
  min-width: 0;
  padding: 0 20rpx 0 0;
}

.name-row {
  display: flex;
  align-items: center;
  gap: 16rpx;
  padding-top: 4rpx;
}

.name {
  font-size: 38rpx;
  font-weight: 600;
  color: #1f1f1f;
  max-width: 440rpx;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.meta {
  font-size: 28rpx;
  color: #666;
}

.sub-line {
  margin-top: 12rpx;
  font-size: 26rpx;
  color: #666;
}

.id-rows {
  margin-top: 12rpx;
}

.id-row {
  display: flex;
  align-items: center;
  font-size: 26rpx;
  color: #666;
  line-height: 36rpx;
}

.id-label {
  flex-shrink: 0;
}

.id-value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.create-row {
  margin-top: 12rpx;
}

.create-text {
  font-size: 26rpx;
  color: #999;
}

.header-right {
  width: 56rpx;
  height: 56rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 12rpx;
}

.cells {
  background: #fff;
  padding: 0 28rpx;
}

.border-bottom {
  border-bottom: 2rpx solid #f2f2f2;
}

.info-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 32rpx 0;
  min-height: 48rpx;
}

.info-block {
  padding: 32rpx 0;
}

.block-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16rpx;
}

.block-content {
  min-height: 40rpx;
}

.input-label {
  font-size: 32rpx;
  color: #666;
}

.info-right {
  display: flex;
  align-items: center;
}

.phone-area {
  display: flex;
  align-items: center;
  margin-right: 24rpx;
}

.mr-4 {
  margin-right: 8rpx;
}

.phone-text {
  font-size: 34rpx;
  color: #0877F1;
  font-weight: 500;
}

.edit-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48rpx;
  height: 48rpx;
}

.placeholder {
  font-size: 30rpx;
  color: #999;
}

.note-content {
  font-size: 30rpx;
  color: #333;
  line-height: 1.5;
  word-break: break-all;
}

.tags-wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 16rpx;
}

.tag-item {
  height: 48rpx;
  line-height: 44rpx;
  padding: 0 20rpx;
  border: 2rpx solid #0877F1;
  border-radius: 24rpx;
  font-size: 26rpx;
  color: #0877F1;
  box-sizing: border-box;
}

.empty-click {
  /* To ensure empty area is clickable */
  display: inline-block;
}

.tabs {
  background: #fff;
  display: flex;
  border-top: 2rpx solid #f2f2f2;
  border-bottom: 2rpx solid #f2f2f2;
  position: sticky;
  top: 0;
  z-index: 30;
}

.tabs-anchor {
  height: 2rpx;
}

.tab {
  flex: 1;
  text-align: center;
  height: 88rpx;
  line-height: 88rpx;
  font-size: 32rpx;
  color: #333;
  position: relative;
}

.tab.active {
  color: #0877F1;
  font-weight: 600;
}

.tab.active::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 64rpx;
  height: 6rpx;
  background: #0877F1;
  transform: translateX(-50%);
  border-radius: 4rpx;
}

.content {
  padding: 0;
  flex: 1;
  min-height: 0;
}

.scroll-spacer {
  height: calc(180rpx + env(safe-area-inset-bottom));
}

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.empty-img {
  width: 320rpx;
  height: 320rpx;
  opacity: 0.9;
}

.empty-text {
  margin-top: 20rpx;
  font-size: 28rpx;
  color: #9aa0a6;
}

.footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: #fff;
  padding: 24rpx 28rpx calc(24rpx + env(safe-area-inset-bottom));
  box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
}

.bind-btn {
  width: 100%;
  height: 88rpx;
  background: #0877F1;
  color: #fff;
  border-radius: 12rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16rpx;
  font-size: 32rpx;
}

.bind-text {
  color: #fff;
}

/* ===== 弹窗样式（居中） ===== */
.modal {
  width: 640rpx;
  background: #fff;
  border-radius: 16rpx;
  overflow: hidden;
}

.modal-title {
  font-size: 34rpx;
  font-weight: 600;
  text-align: center;
  padding: 28rpx 24rpx;
  color: #333;
  border-bottom: 2rpx solid #f0f0f0;
}

.modal-body {
  padding: 28rpx 28rpx 16rpx;
}

.modal-input {
  width: 100%;
  height: 80rpx;
  border: 2rpx solid #e6e6e6;
  border-radius: 8rpx;
  padding: 0 20rpx;
  font-size: 30rpx;
  box-sizing: border-box;
}

.modal-actions {
  display: flex;
  gap: 24rpx;
  padding: 24rpx 28rpx 28rpx;
}

.modal-btn {
  flex: 1;
  height: 80rpx;
  line-height: 80rpx;
  text-align: center;
  border-radius: 8rpx;
  font-size: 30rpx;
}

.modal-btn.cancel {
  border: 2rpx solid #0877F1;
  color: #0877F1;
  background: #fff;
}

.modal-btn.save {
  background: #0877F1;
  color: #fff;
}

/* ===== 底部弹层样式 ===== */
.sheet {
  background: #fff;
  border-top-left-radius: 20rpx;
  border-top-right-radius: 20rpx;
  overflow: hidden;
}

.sheet-header {
  height: 96rpx;
  display: flex;
  align-items: center;
  padding: 0 28rpx;
  border-bottom: 2rpx solid #f0f0f0;
}

.sheet-title {
  flex: 1;
  text-align: center;
  font-size: 34rpx;
  font-weight: 600;
  color: #333;
}

.sheet-close {
  width: 48rpx;
  height: 48rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sheet-header-left {
  width: 48rpx;
}

.sheet-link {
  min-width: 120rpx;
  text-align: right;
  font-size: 30rpx;
  color: #0877F1;
}

.sheet-body {
  padding: 28rpx;
}

.notes-textarea {
  width: 100%;
  height: 280rpx;
  border: 2rpx solid #e6e6e6;
  border-radius: 8rpx;
  padding: 20rpx;
  font-size: 30rpx;
  box-sizing: border-box;
}

.counter {
  text-align: right;
  margin-top: 16rpx;
  font-size: 26rpx;
  color: #999;
}

.group-list {
  padding: 16rpx 28rpx 28rpx;
  max-height: 55vh;
  overflow: auto;
}

.group-item {
  display: flex;
  align-items: center;
  padding: 24rpx 0;
}

.group-name {
  margin-left: 20rpx;
  font-size: 30rpx;
  color: #333;
}

.sheet-footer {
  padding: 24rpx 28rpx calc(24rpx + env(safe-area-inset-bottom));
}

.primary-btn {
  width: 100%;
  height: 88rpx;
  background: #0877F1;
  color: #fff;
  border-radius: 8rpx;
  font-size: 32rpx;
  line-height: 88rpx;
}
</style>
