<template>
  <v-app-bar>
    <template #prepend>
      <div class="post-topic-top" v-if="topicInfo">
        <TMiImg :src="topicInfo.topic.cover" alt="cover" :ori="true" />
        <div class="post-topic-info">
          <span>{{ topicInfo.topic.name }}({{ curTopic }})</span>
          <span :title="topicInfo.topic.desc">{{ topicInfo.topic.desc }}</span>
        </div>
      </div>
    </template>
    <template #extension>
      <TGameNav :model-value="curGid" v-if="curGid !== 0" />
    </template>
    <div class="post-topic-switch">
      <v-select
        v-model="curGame"
        class="post-switch-item"
        :items="getGameList(topicInfo?.game_info_list)"
        item-title="name"
        :item-value="(item) => item"
        variant="outlined"
        label="分区"
      >
        <template #selection="{ item }">
          <div class="select-item main">
            <img
              v-if="item.raw.icon"
              :src="item.raw.icon"
              :alt="item.raw.name"
              :title="item.raw.name"
              class="icon"
            />
            <span>{{ item.raw.name }}</span>
          </div>
        </template>
        <template #item="{ props, item }">
          <div v-bind="props" class="select-item sub" :class="{ selected: item.raw.id === curGid }">
            <img
              v-if="item.raw.icon"
              :src="item.raw.icon"
              :alt="item.raw.name"
              :title="item.raw.name"
              class="icon"
            />
            <span>{{ item.raw.name }}</span>
          </div>
        </template>
      </v-select>
      <v-select
        v-model="curSortType"
        class="post-switch-item"
        :items="sortList"
        item-title="text"
        item-value="value"
        variant="outlined"
        label="排序"
      />
      <v-text-field
        v-model="search"
        class="post-switch-item"
        append-inner-icon="mdi-magnify"
        label="请输入帖子 ID 或搜索词"
        variant="outlined"
        :single-line="true"
        :hide-details="true"
        @click:append="searchPost"
        @keyup.enter="searchPost"
      />
      <v-btn class="post-topic-btn" @click="firstLoad()" prepend-icon="mdi-refresh">刷新</v-btn>
    </div>
  </v-app-bar>
  <div class="post-topic-grid">
    <div v-for="post in posts" :key="post.post.post_id">
      <TPostCard :model-value="post" v-if="post" />
    </div>
  </div>
  <div class="load-more">
    <v-btn class="post-topic-btn" @click="freshPostData()">
      已加载：{{ posts.length }}，
      {{ postRaw.isLast ? "已加载完毕" : "加载更多" }}
    </v-btn>
  </div>
  <VpOverlaySearch :gid="curGid.toString()" v-model="showSearch" :keyword="search" />
</template>
<script lang="ts" setup>
import TGameNav from "@comp/app/t-gameNav.vue";
import TMiImg from "@comp/app/t-mi-img.vue";
import TPostCard from "@comp/app/t-postcard.vue";
import showLoading from "@comp/func/loading.js";
import showSnackbar from "@comp/func/snackbar.js";
import VpOverlaySearch from "@comp/viewPost/vp-overlay-search.vue";
import { computed, onMounted, ref, shallowRef, watch } from "vue";
import { useRoute, useRouter } from "vue-router";

import { createPost } from "@/utils/TGWindow.js";
import apiHubReq from "@/web/request/apiHubReq.js";
import postReq from "@/web/request/postReq.js";
import topicReq from "@/web/request/topicReq.js";

type SortSelect = { text: string; value: number };
type PostMiniData = { isLast: boolean; lastId: string; total: number };
type GameList = TGApp.BBS.Topic.GameInfo & { icon?: string };

const route = useRoute();
const router = useRouter();
const showSearch = ref<boolean>(false);
const curGid = ref<number>(0);
const curSortType = ref<0 | 1 | 2>(0);
const search = ref<string>("");
const curTopic = ref<string>("");
const allGames = shallowRef<Array<TGApp.BBS.Game.Item>>([]);
const postRaw = shallowRef<PostMiniData>({ isLast: false, lastId: "", total: 0 });
const topicInfo = shallowRef<TGApp.BBS.Topic.InfoRes>();
const posts = shallowRef<Array<TGApp.Plugins.Mys.Post.FullData>>([]);
const curGame = shallowRef<GameList>();
const sortList = computed<Array<SortSelect>>(() => {
  if (!topicInfo.value) return [];
  if (!topicInfo.value.good_post_exist) {
    return [
      { text: "最新", value: 0 },
      { text: "热门", value: 2 },
    ];
  }
  return [
    { text: "最新", value: 0 },
    { text: "热门", value: 2 },
    { text: "精选", value: 1 },
  ];
});

onMounted(async () => {
  let { gid, topic } = route.query;
  if (!gid) gid = route.params.gid;
  if (!topic) topic = route.params.topic;
  if (!gid || typeof gid !== "string") gid = "0";
  if (!topic || typeof topic !== "string") topic = "0";
  curGid.value = Number(gid);
  curTopic.value = topic;
  await showLoading.start(`正在加载话题${topic}信息`);
  allGames.value = await apiHubReq.game();
  const info = await topicReq.info(gid, topic);
  if ("retcode" in info) {
    await showLoading.end();
    showSnackbar.error(`[${info.retcode}] ${info.message}`);
    return;
  }
  topicInfo.value = info;
  let tmpGame: GameList | undefined;
  if (curGame.value === undefined) {
    tmpGame = info.game_info_list.find((i) => i.id === curGid.value);
  }
  if (tmpGame === undefined) tmpGame = info.game_info_list[0];
  const gameFind = allGames.value.find((i) => i.id === tmpGame?.id);
  curGame.value = { ...tmpGame, icon: gameFind?.app_icon };
  await firstLoad();
});

watch(
  () => curGame.value,
  async () => {
    if (curGame.value) curGid.value = curGame.value.id;
    await firstLoad();
  },
);
watch(
  () => curSortType.value,
  async () => await firstLoad(),
);

async function firstLoad(): Promise<void> {
  await showLoading.start(`正在加载话题${topicInfo.value?.topic.name}信息`);
  await router.push({
    name: "话题",
    params: route.params,
    query: { gid: curGid.value, topic: curTopic.value },
  });
  document.documentElement.scrollTo({ top: 0, behavior: "smooth" });
  const postList = await postReq.topic(curGid.value, curTopic.value, curSortType.value);
  if ("retcode" in postList) {
    await showLoading.end();
    showSnackbar.error(`[${postList.retcode}] ${postList.message}`);
    return;
  }
  await showLoading.update(`数量：${postList.posts.length}，是否最后一页：${postList.is_last}`);
  postRaw.value = {
    isLast: postList.is_last,
    lastId: postList.last_id,
    total: postList.posts.length,
  };
  posts.value = postList.posts;
  await showLoading.end();
  showSnackbar.success(`加载了 ${postList.posts.length} 条帖子`);
}

async function freshPostData(): Promise<void> {
  if (postRaw.value.isLast) {
    showSnackbar.warn("已经到底了");
    return;
  }
  await showLoading.start(`正在刷新${topicInfo.value?.topic.name}帖子列表`);
  const mod20 = postRaw.value.total % 20;
  const pageSize = mod20 === 0 ? 20 : 20 - mod20;
  const postList = await postReq.topic(
    curGid.value,
    curTopic.value,
    curSortType.value,
    postRaw.value.lastId,
    pageSize,
  );
  if ("retcode" in postList) {
    await showLoading.end();
    showSnackbar.error(`[${postList.retcode}] ${postList.message}`);
    return;
  }
  await showLoading.update(`数量：${postList.posts.length}，是否最后一页：${postList.is_last}`);
  postRaw.value = {
    isLast: postList.is_last,
    lastId: postList.last_id,
    total: postRaw.value.total + postList.posts.length,
  };
  posts.value = posts.value.concat(postList.posts);
  await showLoading.end();
  showSnackbar.success(`加载了 ${postList.posts.length} 条帖子`);
}

function searchPost(): void {
  if (search.value === "") {
    showSnackbar.warn("请输入搜索内容");
    return;
  }
  const numCheck = Number(search.value);
  if (isNaN(numCheck)) showSearch.value = true;
  else createPost(search.value);
}

function getGameList(gameList: Array<TGApp.BBS.Topic.GameInfo> | undefined): Array<GameList> {
  if (!gameList) return [];
  return gameList.map((item) => {
    const game = allGames.value.find((i) => i.id === item.id);
    return { ...item, icon: game?.app_icon };
  });
}
</script>
<style lang="css" scoped>
.post-topic-top {
  position: relative;
  display: flex;
  overflow: hidden;
  align-items: center;
  justify-content: center;
  padding-right: 5px;
  border-radius: 5px;
  background: var(--box-bg-2);
  gap: 5px;

  img {
    width: 64px;
    height: 64px;
  }

  .post-topic-info {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 5px;

    :first-child {
      color: var(--common-text-title);
      font-family: var(--font-title);
      font-size: 20px;
    }

    :last-child {
      overflow: hidden;
      height: 24px;
      max-lines: 1;
      text-overflow: ellipsis;
      word-break: break-all;
    }
  }
}

.post-topic-switch {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  margin: 0 10px;
  gap: 10px;
}

.post-switch-item {
  width: 250px;
  height: 50px;
}

.post-topic-btn {
  height: 40px;
  background: var(--btn-bg-1);
  color: var(--btn-text-1);
  font-family: var(--font-title);
}

.dark .post-topic-btn {
  border: 1px solid var(--common-shadow-2);
}

.post-topic-grid {
  display: grid;
  padding: 5px;
  font-family: var(--font-title);
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}

.load-more {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 10px;
  font-family: var(--font-title);
  transition: all 0.3s linear;
}

.select-item {
  position: relative;
  display: flex;
  align-items: center;
  column-gap: 4px;

  &.main {
    position: relative;
    height: 24px;
    font-family: var(--font-title);
    font-size: 16px;
  }

  &.sub {
    padding: 8px;
    font-family: var(--font-title);
    font-size: 16px;

    &:hover {
      background: var(--common-shadow-2);
    }

    &.selected:not(:hover) {
      background: var(--common-shadow-1);
    }
  }

  .icon {
    width: 28px;
    height: 28px;
  }
}
</style>
