<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import { RouterLink, useRoute } from "vue-router";
import { showToast } from "vant";

import {
  emptyListingPublishOptions,
  type ListingPublishOptions,
} from "@/api/listingOptions";
import { fetchListings, type Listing } from "@/api/listings";
import {
  defaultHomeAnnouncements,
  defaultHomeBanners,
  fetchMobileHomeConfig,
  type HomeBannerSlide,
} from "@/api/homeConfig";
import MobileHomeFilterSheet, {
  type FilterSection,
} from "./MobileHomeFilterSheet.vue";
import {
  assetRegions,
  formatHafCoinM,
  getCoinM,
  getCoinWan,
  getListingChips,
  getListingDisplayPrice,
  getListingSubtitle,
  getListingTitle,
  getLoginMethod,
  getResourceQuantity,
  getServerRegion,
  getSkinGroup,
  hasAcceleratedSaleRatio,
  hasGiftResources,
  readAssetNumber,
  readAssetString,
} from "@/utils/listingDisplay";

const route = useRoute();
const loading = ref(false);
const loadFailed = ref(false);
const listings = ref<Listing[]>([]);
const publishOptions = ref<ListingPublishOptions>(emptyListingPublishOptions);
const sortOpen = ref(false);
const activeSort = ref("comprehensive");
const filterOpen = ref(false);
const selectedFilters = ref<Record<string, string[]>>({});
const rangeFilters = ref<Record<string, { min: string; max: string }>>({});
const refreshing = ref(false);
const searchValue = ref("");
const announcements = ref<string[]>(defaultHomeAnnouncements);
const bannerSlides = ref<HomeBannerSlide[]>(defaultHomeBanners);

const sortOptions = [
  { key: "comprehensive", label: "综合排序" },
  { key: "published", label: "发布时间" },
  { key: "priceAsc", label: "价格最低" },
  { key: "priceDesc", label: "价格最高" },
];

const rangePresets: Record<string, Array<{ label: string; min: string; max: string }>> = {
  coin: [
    { label: "50-100", min: "50", max: "100" },
    { label: "100-200", min: "100", max: "200" },
    { label: "200-300", min: "200", max: "300" },
    { label: "300-500", min: "300", max: "500" },
    { label: "500以上", min: "500", max: "" },
  ],
  resource_awmAmmo: [
    { label: "0-20", min: "0", max: "20" },
    { label: "20-50", min: "20", max: "50" },
    { label: "50-100", min: "50", max: "100" },
    { label: "100-200", min: "100", max: "200" },
    { label: "200以上", min: "200", max: "" },
  ],
};

const activeSortLabel = computed(
  () =>
    sortOptions.find((option) => option.key === activeSort.value)?.label ||
    "综合排序"
);

const serverFilterOptions = computed(() =>
  uniqueOptions(
    publishOptions.value.server_options
      .map((item) => item.trim())
      .filter(Boolean)
  )
);

const loginMethodFilterOptions = computed(() =>
  uniqueOptions(
    publishOptions.value.login_method_options
      .map((item) => item.trim())
      .filter(Boolean)
  )
);

const filterSections = computed<FilterSection[]>(() => [
  { key: "price", title: "价格区间", type: "range", unit: "元", minPlaceholder: "最低价", maxPlaceholder: "最高价" },
  { key: "coin", title: "哈夫币数量", type: "range", unit: "M", minPlaceholder: "最低", maxPlaceholder: "最高" },
  { key: "server", title: "区服", type: "chips", options: serverFilterOptions.value },
  { key: "login", title: "上号方式", type: "chips", options: loginMethodFilterOptions.value },
  { key: "insurance", title: "保险", type: "chips", options: publishOptions.value.insurance_options },
  { key: "stamina", title: "体力", type: "chips", options: publishOptions.value.level_options },
  { key: "load", title: "负重", type: "chips", options: publishOptions.value.level_options },
  ...publishOptions.value.quantity_items.map((item) => ({
    key: `resource_${item.key}`,
    title: item.label,
    type: "range" as const,
    unit: parseQuantityUnit(item.price),
    minPlaceholder: "最低",
    maxPlaceholder: "最高",
  })),
  ...publishOptions.value.skin_groups.map((group) => ({
    key: group.key,
    title: group.title,
    type: "chips" as const,
    options: group.options,
  })),
  { key: "secretKd", title: "绝密KD", type: "range", minPlaceholder: "最低", maxPlaceholder: "最高" },
  { key: "rank", title: "段位", type: "chips", options: publishOptions.value.rank_options },
  { key: "deposit", title: "押金", type: "range", unit: "元", minPlaceholder: "最低", maxPlaceholder: "最高" },
]);

const activeFilterCount = computed(() => {
  const chipCount = Object.values(selectedFilters.value).reduce(
    (sum, values) => sum + values.length,
    0
  );
  const rangeCount = Object.values(rangeFilters.value).filter(
    (range) => range.min || range.max
  ).length;
  return chipCount + rangeCount;
});

const displayListings = computed(() => {
  const keyword = searchValue.value.trim().toLowerCase();
  const filtered = listings.value.filter((item) => {
    if (!matchesFilters(item)) return false;
    if (!keyword) return true;
    return searchText(item).includes(keyword);
  });
  return sortListings(filtered);
});

/** 判断当前底部导航是否激活 */
function isNavActive(path: string) {
  if (path === "/m") return route.path === "/m";
  return route.path.startsWith(path);
}

onMounted(() => {
  loadListings();
  loadHomeConfig();
});

async function loadListings() {
  loading.value = true;
  loadFailed.value = false;
  try {
    listings.value = await fetchListings();
  } catch {
    loadFailed.value = true;
  } finally {
    loading.value = false;
  }
}

async function loadHomeConfig() {
  try {
    const config = await fetchMobileHomeConfig();
    announcements.value = config.announcements;
    bannerSlides.value = config.banners;
    publishOptions.value = config.publish_options;
  } catch {
    announcements.value = defaultHomeAnnouncements;
    bannerSlides.value = defaultHomeBanners;
    publishOptions.value = emptyListingPublishOptions;
  }
}

async function onRefresh() {
  refreshing.value = true;
  try {
    const [nextListings, nextHomeConfig] = await Promise.all([
      fetchListings(),
      fetchMobileHomeConfig(),
    ]);
    listings.value = nextListings;
    announcements.value = nextHomeConfig.announcements;
    bannerSlides.value = nextHomeConfig.banners;
    publishOptions.value = nextHomeConfig.publish_options;
    showToast({ message: "刷新成功", icon: "passed" });
  } catch {
    // 静默处理
  } finally {
    refreshing.value = false;
  }
}

function openFilters() {
  sortOpen.value = false;
  filterOpen.value = true;
}

function toggleSortPanel() {
  sortOpen.value = !sortOpen.value;
}

function selectSort(sortKey: string) {
  activeSort.value = sortKey;
  sortOpen.value = false;
}

function clearFilters() {
  selectedFilters.value = {};
  rangeFilters.value = {};
  searchValue.value = "";
}

function sortListings(items: Listing[]) {
  const sorted = [...items];
  if (activeSort.value === "comprehensive") {
    return sorted;
  }
  if (activeSort.value === "priceAsc") {
    return sorted.sort(
      (a, b) => getListingDisplayPrice(a) - getListingDisplayPrice(b)
    );
  }
  if (activeSort.value === "priceDesc") {
    return sorted.sort(
      (a, b) => getListingDisplayPrice(b) - getListingDisplayPrice(a)
    );
  }
  return sorted.sort((a, b) => {
    const bTime = Date.parse(b.published_at || b.created_at || "") || 0;
    const aTime = Date.parse(a.published_at || a.created_at || "") || 0;
    return bTime - aTime || b.id - a.id;
  });
}

function matchesFilters(item: Listing) {
  const chipOk = Object.entries(selectedFilters.value).every(([key, values]) => {
    if (!values.length) return true;
    if (key === "server") return values.includes(getServerRegion(item));
    if (key === "login") return values.includes(getLoginMethod(item));
    if (key === "insurance") return values.includes(readAssetString(item, "season_insurance"));
    if (key === "stamina") return values.includes(readAssetString(item, "stamina_level"));
    if (key === "load") return values.includes(readAssetString(item, "load_level"));
    if (key === "rank") return values.includes(item.rank_level);
    if (isSkinGroupKey(key)) {
      return getSkinGroup(item, key).some((skin) => values.includes(skin));
    }
    return true;
  });
  if (!chipOk) return false;

  return Object.entries(rangeFilters.value).every(([key, range]) => {
    if (!range.min && !range.max) return true;
    let value = 0;
    if (key === "price") value = getListingDisplayPrice(item);
    if (key === "coin") value = getCoinM(item);
    if (key === "secretKd") value = readAssetNumber(item, "secret_kd");
    if (key === "deposit") value = Number(item.deposit_amount || 0);
    if (key.startsWith("resource_")) {
      value = getResourceQuantity(item, key.replace("resource_", ""));
    }
    return inRange(value, range);
  });
}

function inRange(value: number, range: { min: string; max: string }) {
  const min = range.min === "" ? undefined : Number(range.min);
  const max = range.max === "" ? undefined : Number(range.max);
  if (min !== undefined && Number.isFinite(min) && value < min) return false;
  if (max !== undefined && Number.isFinite(max) && value > max) return false;
  return true;
}

function searchText(item: Listing) {
  return [
    item.title,
    item.description,
    getServerRegion(item),
    getLoginMethod(item),
    item.rank_level,
    readAssetString(item, "season_insurance"),
    readAssetString(item, "stamina_level"),
    readAssetString(item, "load_level"),
    formatHafCoinM(getCoinWan(item)),
    assetRegions(item).join(" "),
    ...publishOptions.value.skin_groups.map((group) =>
      getSkinGroup(item, group.key).join(" ")
    ),
  ]
    .join(" ")
    .toLowerCase();
}

function isSkinGroupKey(key: string) {
  return publishOptions.value.skin_groups.some((group) => group.key === key);
}

function parseQuantityUnit(price: string) {
  const unit = price.split("/")[1]?.trim();
  return unit || undefined;
}

function uniqueOptions(values: string[]) {
  return [...new Set(values.map((item) => item.trim()).filter(Boolean))];
}

</script>

<template>
  <main class="mobile-shell">
    <!-- ========== Hero 区域：顶部搜索与公告 ========== -->
    <section class="mobile-hero">
      <div class="mobile-topbar">
        <div class="mobile-brand">
          <span class="mobile-logo">锤</span>
          <div>
            <strong>大锤商行</strong>
            <small>哈夫币租号</small>
          </div>
        </div>
        <van-search
          v-model="searchValue"
          shape="round"
          placeholder="搜区服 / 段位"
          class="home-search"
        />
        <button class="mobile-service" type="button">客服</button>
      </div>

      <!-- 防骗提示卡片（不用 van-notice-bar） -->
      <div class="fraud-tip">
        <van-icon name="warning-o" :size="16" color="#b8860b" />
        <span class="fraud-dot"></span>
        <van-swipe
          class="announcement-swipe"
          vertical
          :autoplay="3200"
          :show-indicators="false"
          touchable
        >
          <van-swipe-item v-for="item in announcements" :key="item">
            <span>{{ item }}</span>
          </van-swipe-item>
        </van-swipe>
      </div>
    </section>

    <!-- ========== Content 区域 ========== -->
    <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
      <section class="mobile-content">
        <!-- Banner 轮播 -->
        <van-swipe class="banner-swipe" :autoplay="3600" lazy-render>
          <van-swipe-item
            v-for="slide in bannerSlides"
            :key="slide.title || slide.image_url"
          >
            <div
              class="mobile-banner"
              :class="[`tone-${slide.tone}`, { 'has-image': slide.image_url }]"
            >
              <img
                v-if="slide.image_url"
                class="banner-image"
                :src="slide.image_url"
                :alt="slide.title || slide.eyebrow || '首页轮播图'"
              />
              <div>
                <p v-if="slide.eyebrow">{{ slide.eyebrow }}</p>
                <h1 v-if="slide.title">{{ slide.title }}</h1>
                <span v-if="slide.pill">{{ slide.pill }}</span>
              </div>
              <div v-if="slide.badge" class="banner-badge">{{ slide.badge }}</div>
            </div>
          </van-swipe-item>
        </van-swipe>

        <div class="list-toolbar">
          <button type="button" class="sort-entry" @click="toggleSortPanel">
            <span>{{ activeSortLabel }}</span>
            <van-icon :name="sortOpen ? 'arrow-up' : 'arrow-down'" :size="14" />
          </button>
          <button type="button" class="filter-entry" @click="openFilters">
            <van-icon name="filter-o" :size="16" />
            <span>筛选</span>
            <em v-if="activeFilterCount">{{ activeFilterCount }}</em>
          </button>
        </div>
        <div v-if="sortOpen" class="sort-panel">
          <button
            v-for="option in sortOptions"
            :key="option.key"
            type="button"
            :class="{ active: activeSort === option.key }"
            @click="selectSort(option.key)"
          >
            <span>{{ option.label }}</span>
            <van-icon
              v-if="activeSort === option.key"
              name="success"
              :size="18"
            />
          </button>
        </div>
        <div class="result-count">
          <strong>{{ displayListings.length }}</strong>
          <span>个可租账号</span>
        </div>

        <!-- 加载/错误状态 -->
        <van-loading v-if="loading" class="state-loading" size="24px" vertical>
          正在加载优质账号...
        </van-loading>
        <van-notice-bar
          v-else-if="loadFailed"
          left-icon="info-o"
          color="#6b7a90"
          background="transparent"
          text="接口暂不可用，请稍后刷新。"
        />
        <van-empty
          v-else-if="displayListings.length === 0"
          image="search"
          description="没有符合条件的账号"
        >
          <van-button size="small" type="primary" @click="clearFilters">
            重置条件
          </van-button>
        </van-empty>

        <!-- 列表卡片：全宽上下布局 -->
        <div class="mobile-list">
          <RouterLink
            v-for="item in displayListings"
            :key="item.id"
            class="mobile-card"
            :to="`/m/listings/${item.id}`"
          >
            <div class="card-cover">
              <img
                v-if="item.cover_url"
                :src="item.cover_url"
                :alt="getListingTitle(item)"
              />
              <span v-else>图</span>
              <div
                v-if="hasGiftResources(item) || hasAcceleratedSaleRatio(item)"
                class="card-cover-labels"
              >
                <em v-if="hasGiftResources(item)">有赠送</em>
                <em v-if="hasAcceleratedSaleRatio(item)">特惠</em>
              </div>
            </div>
            <div class="card-main">
              <div class="card-title-row">
                <h2>{{ getListingTitle(item) }}</h2>
              </div>
              <p class="card-subtitle">{{ getListingSubtitle(item) }}</p>
              <div class="card-badges-row">
                <span class="trust-badge">押金秒退</span>
                <span class="server-badge">{{ getServerRegion(item) }}</span>
                <span v-if="getLoginMethod(item)" class="server-badge">
                  {{ getLoginMethod(item) }}
                </span>
              </div>
              <div class="card-footer">
                <div class="price-col">
                  <strong>¥{{ getListingDisplayPrice(item) }}</strong>
                  <span class="rent-sub">押金¥{{ item.deposit_amount }}</span>
                </div>
              </div>
            </div>
            <div class="card-chip-row">
              <span
                v-for="chip in getListingChips(item)"
                :key="`${item.id}-${chip.label}`"
              >
                {{ chip.label }}:{{ chip.value }}
              </span>
            </div>
          </RouterLink>
        </div>
      </section>
    </van-pull-refresh>

    <MobileHomeFilterSheet
      v-model:show="filterOpen"
      v-model:selected-filters="selectedFilters"
      v-model:range-filters="rangeFilters"
      :sections="filterSections"
      :range-presets="rangePresets"
      @reset="clearFilters"
    />

    <!-- ========== 底部导航：原生App风格，手写，不用 van-tabbar ========== -->
    <nav class="bottom-nav">
      <RouterLink
        to="/m"
        class="nav-item"
        :class="{ active: isNavActive('/m') }"
      >
        <van-icon name="home-o" :size="22" />
        <span>首页</span>
      </RouterLink>
      <RouterLink
        to="/m/messages"
        class="nav-item"
        :class="{ active: isNavActive('/m/messages') }"
      >
        <van-icon name="chat-o" :size="22" />
        <span>消息</span>
      </RouterLink>
      <RouterLink to="/m/seller/listings/create" class="nav-item nav-publish">
        <div class="publish-pill">+</div>
        <span>发布</span>
      </RouterLink>
      <RouterLink
        to="/m/orders"
        class="nav-item"
        :class="{ active: isNavActive('/m/orders') }"
      >
        <van-icon name="orders-o" :size="22" />
        <span>订单</span>
      </RouterLink>
      <RouterLink
        to="/m/profile"
        class="nav-item"
        :class="{ active: isNavActive('/m/profile') }"
      >
        <van-icon name="manager-o" :size="22" />
        <span>我的</span>
      </RouterLink>
    </nav>
  </main>
</template>

<style scoped src="./MobileHomeView.css"></style>
