<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';

import { listBadgePictureBySysOrigin } from '#/api/legacy/badge';
import { listGiftBySysOrigin } from '#/api/legacy/gift';
import {
  listNotFamilyBySysOriginType,
  pagePropsSource,
} from '#/api/legacy/props';

import {
  Button,
  Drawer,
  Empty,
  Input,
  Pagination,
  Select,
  Space,
  Spin,
} from 'antdv-next';

defineOptions({ name: 'ResidentActivityResourceSelectDrawer' });

type ResourceItem = {
  amount?: number | string;
  cover: string;
  id: number | string;
  name: string;
  sourceUrl: string;
  type: string;
};

const props = withDefaults(
  defineProps<{
    defaultType?: string;
    fixedType?: boolean;
    open: boolean;
    sysOrigin: string;
    title?: string;
  }>(),
  {
    defaultType: 'ALL_PROPS',
    fixedType: false,
    title: '选择资源',
  },
);

const emit = defineEmits<{
  close: [];
  select: [item: ResourceItem];
}>();

const typeOptions = [
  { label: '全部资源', value: 'ALL_PROPS' },
  { label: '自定义', value: 'CUSTOMIZE' },
  { label: '头像框', value: 'AVATAR_FRAME' },
  { label: '座驾', value: 'RIDE' },
  { label: '聊天气泡', value: 'CHAT_BUBBLE' },
  { label: '贵族 VIP', value: 'NOBLE_VIP' },
  { label: '主题背景', value: 'THEME' },
  { label: '飘窗', value: 'FLOAT_PICTURE' },
  { label: '礼物', value: 'GIFT' },
  { label: '徽章', value: 'BADGE' },
].map((item) => ({ ...item, value: item.value as any }));

const listOnlyTypes = new Set(['BADGE', 'GIFT', 'NOBLE_VIP']);

const loading = ref(false);
const list = ref<ResourceItem[]>([]);
const total = ref(0);

const query = reactive({
  cursor: 1,
  keyword: '',
  limit: 24,
  type: 'ALL_PROPS',
});

const localRows = ref<ResourceItem[]>([]);

const filteredLocalRows = computed(() => {
  const keyword = query.keyword.trim().toLowerCase();
  if (!keyword) {
    return localRows.value;
  }
  return localRows.value.filter(
    (item) =>
      String(item.id).toLowerCase().includes(keyword) ||
      item.name.toLowerCase().includes(keyword),
  );
});

function firstPresent(record: Record<string, any>, keys: string[]) {
  for (const key of keys) {
    const value = record?.[key];
    if (value !== undefined && value !== null && String(value).trim() !== '') {
      return value;
    }
  }
  return '';
}

function normalizeResource(
  item: Record<string, any>,
  type: string,
  options: {
    coverKeys?: string[];
    idKeys?: string[];
    nameKeys?: string[];
    sourceUrlKeys?: string[];
  } = {},
): ResourceItem {
  const id = firstPresent(
    item,
    options.idKeys || ['id', 'resourceId', 'sourceId', 'propsId'],
  );
  return {
    amount: firstPresent(item, ['amount', 'giftCandy', 'price']),
    cover: String(
      firstPresent(
        item,
        options.coverKeys || [
          'cover',
          'coverUrl',
          'resourceCover',
          'resourceCoverUrl',
          'giftPhoto',
          'selectUrl',
          'icon',
        ],
      ),
    ),
    id: id as number | string,
    name: String(
      firstPresent(
        item,
        options.nameKeys || [
          'name',
          'resourceName',
          'sourceName',
          'giftName',
          'badgeName',
          'title',
          'remark',
        ],
      ) || (id ? `资源 ${id}` : ''),
    ),
    sourceUrl: String(
      firstPresent(
        item,
        options.sourceUrlKeys || [
          'sourceUrl',
          'resourceUrl',
          'url',
          'giftSourceUrl',
          'animationUrl',
        ],
      ),
    ),
    type,
  };
}

function applyLocalPage() {
  const rows = filteredLocalRows.value;
  total.value = rows.length;
  const start = (query.cursor - 1) * query.limit;
  list.value = rows.slice(start, start + query.limit);
}

async function loadListType(type: string) {
  if (type === 'GIFT') {
    const result = await listGiftBySysOrigin(props.sysOrigin);
    localRows.value = (result || []).map((item) =>
      normalizeResource(item, type, {
        coverKeys: ['giftPhoto', 'cover'],
        idKeys: ['id', 'giftId'],
        nameKeys: ['giftName', 'name'],
        sourceUrlKeys: ['giftSourceUrl', 'sourceUrl'],
      }),
    );
    applyLocalPage();
    return;
  }
  if (type === 'BADGE') {
    const result = await listBadgePictureBySysOrigin(props.sysOrigin, 'ACTIVITY');
    localRows.value = (result || []).map((item) =>
      normalizeResource(item, type, {
        coverKeys: ['selectUrl', 'cover'],
        idKeys: ['badgeConfigId', 'id'],
        nameKeys: ['badgeName', 'name'],
        sourceUrlKeys: ['animationUrl', 'sourceUrl'],
      }),
    );
    applyLocalPage();
    return;
  }
  if (type === 'NOBLE_VIP') {
    const result = await listNotFamilyBySysOriginType(props.sysOrigin, type);
    localRows.value = (result || []).map((item) =>
      normalizeResource(item, type),
    );
    applyLocalPage();
  }
}

async function loadData(reset = false) {
  if (!props.open || !props.sysOrigin) {
    return;
  }
  if (reset) {
    query.cursor = 1;
  }
  loading.value = true;
  try {
    if (listOnlyTypes.has(query.type)) {
      await loadListType(query.type);
      return;
    }
    const keyword = query.keyword.trim();
    const params: Record<string, any> = {
      cursor: query.cursor,
      del: false,
      limit: query.limit,
      sysOrigin: props.sysOrigin,
    };
    if (query.type && query.type !== 'ALL_PROPS') {
      params.type = query.type;
    }
    if (keyword) {
      if (/^\d+$/.test(keyword)) {
        params.id = keyword;
      } else {
        params.name = keyword;
      }
    }
    const result = await pagePropsSource(params);
    list.value = (result.records || []).map((item) =>
      normalizeResource(item, String(item.type || query.type || '')),
    );
    total.value = result.total || 0;
  } finally {
    loading.value = false;
  }
}

function handleTypeChange(value: string) {
  query.type = value || 'ALL_PROPS';
  query.keyword = '';
  localRows.value = [];
  void loadData(true);
}

function handleSearch() {
  void loadData(true);
}

function handlePageChange(page: number, pageSize: number) {
  query.cursor = page;
  query.limit = pageSize;
  if (listOnlyTypes.has(query.type)) {
    applyLocalPage();
    return;
  }
  void loadData();
}

function handleSelect(item: ResourceItem) {
  emit('select', item);
}

watch(
  () => props.open,
  (open) => {
    if (!open) {
      return;
    }
    query.type = props.defaultType || 'ALL_PROPS';
    query.keyword = '';
    query.cursor = 1;
    localRows.value = [];
    void loadData(true);
  },
  { immediate: true },
);

watch(
  () => props.defaultType,
  (value) => {
    if (!props.open || !value) {
      return;
    }
    query.type = value;
    query.keyword = '';
    localRows.value = [];
    void loadData(true);
  },
);

watch(
  () => props.sysOrigin,
  () => {
    localRows.value = [];
    if (props.open) {
      void loadData(true);
    }
  },
);
</script>

<template>
  <Drawer
    :open="open"
    destroy-on-close
    :title="title"
    width="920"
    @close="emit('close')"
  >
    <Space class="toolbar" wrap>
      <Select
        v-if="!fixedType"
        v-model:value="query.type"
        :options="typeOptions"
        option-label-prop="label"
        style="width: 180px"
        @change="handleTypeChange"
      />
      <Input
        v-model:value="query.keyword"
        allow-clear
        placeholder="资源名称 / ID"
        style="width: 260px"
        @press-enter="handleSearch"
      />
      <Button :loading="loading" type="primary" @click="handleSearch">
        搜索
      </Button>
    </Space>

    <Spin :spinning="loading">
      <div v-if="list.length > 0" class="resource-grid">
        <button
          v-for="item in list"
          :key="`${item.type}-${item.id}`"
          class="resource-card"
          type="button"
          @click="handleSelect(item)"
        >
          <div class="resource-cover-wrap">
            <img
              :src="item.cover || 'https://dummyimage.com/88x88/e2e8f0/64748b&text=+'"
              alt=""
              class="resource-cover"
            />
          </div>
          <div class="resource-name">{{ item.name || '-' }}</div>
          <div class="resource-meta">ID {{ item.id }}</div>
          <div class="resource-type">{{ item.type || '-' }}</div>
        </button>
      </div>
      <Empty v-else description="暂无可选资源" />
    </Spin>

    <div class="pager">
      <Pagination
        :current="query.cursor"
        :page-size="query.limit"
        :total="total"
        show-size-changer
        @change="handlePageChange"
        @showSizeChange="handlePageChange"
      />
    </div>
  </Drawer>
</template>

<style scoped>
.toolbar {
  margin-bottom: 16px;
}

.resource-grid {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
}

.resource-card {
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  cursor: pointer;
  padding: 12px;
  text-align: center;
  transition:
    border-color 0.2s ease,
    box-shadow 0.2s ease,
    transform 0.2s ease;
}

.resource-card:hover {
  border-color: #2563eb;
  box-shadow: 0 12px 24px rgb(37 99 235 / 12%);
  transform: translateY(-2px);
}

.resource-cover-wrap {
  align-items: center;
  display: flex;
  height: 88px;
  justify-content: center;
  margin-bottom: 10px;
}

.resource-cover {
  border-radius: 8px;
  height: 88px;
  object-fit: cover;
  width: 88px;
}

.resource-name {
  font-weight: 600;
  line-height: 1.4;
  min-height: 40px;
  word-break: break-all;
}

.resource-meta,
.resource-type {
  color: #64748b;
  font-size: 12px;
  margin-top: 6px;
  word-break: break-all;
}

.pager {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}
</style>
