<template>
  <!-- 通用列表页 -->
  <view 
    :class="[
      'common-list-page d-flex flex-column', 
      hasBg ? 'bg-base p-3' : ''
    ]"
  >
    <view v-if="showTab && tabs" class="top-tab bg-base">
      <Tabs
        :tabs="tabs" 
        :width="700"
        v-model:currentIndex="tabCurrentIndex"
        :autoScroll="false"
        :defaultItemWidth="180"
        :autoItemWidth="tabsScrollable ? false : true"
        @click="handleTabClick"
      />
    </view>
    <!-- 搜索 -->
    <view v-if="showSearch" class="d-flex flex-col">
      <SearchBar
        v-model="searchValue"
        :placeholder="`输入关键词搜索${title}`" 
        @search="doSearch"
        @cancel="doSearch"
      />
    </view>
    <!-- 下拉框 -->
    <view 
      v-if="dropDownNames.length > 0" 
      class="d-flex flex-row justify-between align-center mt-2"
      :class="[
        dropDownVisibleCount >= 3 ? 'justify-around' : ('justify-between')
      ]"
    >
      <template v-for="(drop, k) in dropDownNames" :key="k" >
        <SimpleDropDownPicker 
          v-if="!drop.activeTab || drop.activeTab.includes(tabCurrentIndex)"
          :modelValue="dropDownValues[k]"
          :columns="drop.options"
          :style="{maxWidth: `${100/dropDownNames.length}%`}"
          @update:modelValue="(v) => handleChangeDropDownValue(k, v)"
        />
      </template>
      <view 
        v-if="(showTotal && dropDownVisibleCount < 3 && dropDownVisibleCount != 0)" 
        class="d-flex flex-row align-center mt-3 size-s color-primary text-bold"
      >
        <text>总共有 {{ listLoader.total }} 个</text>
      </view>
    </view>
    <view 
      v-if="showTotal && (dropDownVisibleCount >= 3 || dropDownVisibleCount == 0)" 
      class="d-flex flex-row justify-center align-center mt-3 size-s color-primary text-bold"
    >
      <text>总共有 {{ listLoader.total }} 个</text>
    </view>
    
    <!-- 列表 -->
    <view class="position-relative d-flex flex-row flex-wrap justify-between align-stretch mt-3">
      <slot name="list" />
      <view
        v-for="(item, i) in listLoader.list.value"
        :key="item.id"
        :class="[
          'position-relative d-flex flex-grow-1',
          itemType.endsWith('-2') ? 'width-1-2' : 'w-100'
        ]"
      >
        <Box2LineLargeImageUserShadow 
          v-if="itemType.startsWith('image-large')"
          class="w-100"
          titleColor="title-text"
          :classNames="getItemClass(i)"
          :image="getImage(item)"
          :titleBox="item.titleBox"
          :titlePrefix="item.titlePrefix"
          :title="item.title"
          :desc="item.desc"
          :tags="item.bottomTags"
          :badge="item.badge"
          @click="goDetails(item, item.id)"
        />
        <Box2LineImageRightShadow 
          v-else-if="itemType.startsWith('article-common')"
          class="w-100"
          titleColor="title-text"
          :titleBox="item.titleBox"
          :titlePrefix="item.titlePrefix"
          :classNames="getItemClass(i)"
          :image="getImage(item)"
          :title="item.title"
          :desc="item.desc"
          :tags="item.bottomTags"
          :badge="item.badge"
          :wideImage="true"
          @click="goDetails(item, item.id)"
        />
        <Box2LineImageRightShadow 
          v-else-if="itemType.startsWith('article-character')"
          class="w-100"
          :classNames="getItemClass(i)"
          :image="getImage(item)"
          titleColor="title-text"
          :title="item.title"
          :titlePrefix="item.titlePrefix"
          :titleBox="item.titleBox"
          :tags="item.bottomTags || item.keywords"
          :desc="item.desc"
          :badge="item.badge"
          @click="goDetails(item, item.id)"
        />

      </view>
      <view v-if="itemType.endsWith('-2') && listLoader.list.value.length % 2 != 0" class="width-1-2" />
    </view>
    <SimplePageListLoader :loader="listLoader" />
  </view>
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, ref, watch, type PropType } from 'vue';
import { useSimplePageListLoader } from '@/common/composeabe/SimplePageListLoader';
import { navTo } from '@/components/utils/PageAction';
import SimplePageListLoader from '@/common/components/SimplePageListLoader.vue';
import Box2LineLargeImageUserShadow from '@/pages/parts/Box2LineLargeImageUserShadow.vue';
import Box2LineImageRightShadow from '@/pages/parts/Box2LineImageRightShadow.vue';
import SimpleDropDownPicker, { type SimpleDropDownPickerItem } from '@/common/components/SimpleDropDownPicker.vue';
import AppCofig from '@/common/config/AppCofig';
import Tabs from '@/components/nav/Tabs.vue';
import SearchBar from '@/components/form/SearchBar.vue';

function getImage(item: any) {
  return item.thumbnail || item.image || AppCofig.defaultImage
}
function getItemClass(index: number) {
  return props.itemType.endsWith('-2') ? (index % 2 != 0 ? 'ml-1' : 'mr-1') : ''
}

export interface DropDownNames {
  options: SimpleDropDownPickerItem[],
  defaultSelectedValue: number|string,
  activeTab?: number[],
}
export interface CommonListItem extends Record<string, any>  {
  id: number,
  image: string,
  title: string,
}

const props = defineProps({
  /** 
   * 标题
   */
  title: {
    type: String,
    default: '',
  },
  /**
   * 分组标签
   */
  tabs: {
    type: Array as PropType<{ 
      id: number, 
      text: string,
      onlyJump?: boolean,
      jump?: () => void,
      width?: number,
    }[]>,
    default: null,
  },
  tabsScrollable: {
    type: Boolean,
    default: false, 
  },
  /**
   * 是否显示搜索框
   */
  showSearch: {
    type: Boolean,
    default: true,
  },
  /**
   * 是否显示Tab
   */
  showTab: {
    type: Boolean,
    default: true,
  },
  /**
   * 显示总数
   */
  showTotal: {
    type: Boolean,
    default: false,
  },
  /**
   * 下拉框选项控制
   */
  dropDownNames: {
    type: Object as PropType<DropDownNames[]>,
    default: () => ([]),
  },
  /**
   * 列表项类型
   */
  itemType: {
    type: String as PropType<'image-large-2'|'image-large'|'article-common'|'article-character'>,
    default: 'article-common',
  },
  /**
   * 分页大小
   */
  pageSize: {
    type: Number,
    default: 8,
  },
  /**
   * 加载数据函数
   * @param page 页码，从1开始
   * @param pageSize 分页大小
   * @param searchText 搜索文本
   * @param dropDownValues 下拉框值
   */
  load: {
    type: Function as PropType<(
      page: number, 
      pageSize: number,
      searchText: string,
      dropDownValues: number[],
      tabSelect: number,
    ) => Promise<{ list: CommonListItem[], total: number }>>,
    required: true,
  },
  /**
   * 点击详情跳转页面路径
   */
  detailsPage: {
    type: [String,Object],
    default: '/pages/article/details'
  },
  /**
   * 详情跳转页面参数
   */
  detailsParams: {
    type: Object as PropType<Record<string, any>>,
    default: () => ({})
  },
  hasBg: {
    type: Boolean,
    default: true,
  },
  startTabIndex: {
    type: Number,
    default: undefined, 
  },
  loadMounted: {
    type: Boolean,
    default: true,
  },
})

const emit = defineEmits([ 'goCustomDetails' ])

const dropDownVisibleCount = computed(() => {
  let c = 0;
  for (const element of props.dropDownNames) {
    if (!element.activeTab || element.activeTab.includes(tabCurrentIndex.value))
      c++;
  }
  return c;
})
const dropDownValues = ref<any>([]);
const searchValue = ref('');
const listLoader = useSimplePageListLoader(props.pageSize, async (page, pageSize) => {
  return await props.load(
    page, pageSize, 
    searchValue.value,
    dropDownValues.value,
    props.tabs?.[tabCurrentIndex.value]?.id ?? tabCurrentIndex.value,
  )
});
const tabCurrentIndex = ref(0)

function handleChangeDropDownValue(index: number, value: number) {
  dropDownValues.value[index] = value;
  listLoader.loadData(undefined, true);
}
function handleTabClick(e: any) {
  nextTick(() => {
    if (e.jump) {
      e.jump?.();
      tabCurrentIndex.value = 0;
      return;
    }
    listLoader.loadData(undefined, true);
  })
}
function doSearch() {
  listLoader.loadData(undefined, true);
}
function goDetails(item: any, id: number) {
  if (props.detailsPage == 'disabled') 
    return;
  if (props.detailsPage == 'custom') {
    emit('goCustomDetails', item, id)
    return;
  }
  if (typeof props.detailsPage === 'object' && typeof props.detailsPage[0] === 'string') {
    navTo(props.detailsPage[tabCurrentIndex.value], { 
      ...props.detailsParams, 
      id 
    })
    return; 
  }
  if (typeof props.detailsPage == 'object' && typeof props.detailsPage[0] === 'object') {
    const item = props.detailsPage[tabCurrentIndex.value];
    navTo(item.page, { 
      ...item.params, 
      id 
    })
    return; 
  }
  navTo(props.detailsPage as string, { 
    ...props.detailsParams,
    id
  })
}

function loadDropDownValues() {
  dropDownValues.value = [];
  for (const element of props.dropDownNames) {
    dropDownValues.value.push(element.defaultSelectedValue);
  }
}

watch(tabCurrentIndex, () => {
  listLoader.loadData(undefined, true);
});
watch(() => props.startTabIndex, () => {
  if (props.startTabIndex) {
    tabCurrentIndex.value = props.startTabIndex;
  }
});
watch(() => props.dropDownNames.length, () => {
  loadDropDownValues();
  listLoader.loadData(undefined, true);
});

defineExpose({
  load: () => {
    listLoader.loadData(undefined, true);
  },
})

onMounted(() => {
  if (props.startTabIndex)
    tabCurrentIndex.value = props.startTabIndex;
  if (props.title)
    uni.setNavigationBarTitle({ title: props.title, })
  loadDropDownValues();
  if (props.loadMounted)
    listLoader.loadData(undefined, true);
});
</script>

<style lang="scss">
.common-list-page {
  min-height: 100vh; 
}
</style>