<script setup lang="ts">
import {
  BankOutlined,
  DeleteOutlined,
  PlusOutlined,
  ReloadOutlined,
  SendOutlined,
} from '@ant-design/icons-vue'
import { useQuery } from '@tanstack/vue-query'
import { message } from 'ant-design-vue'
import { computed, ref, watch } from 'vue'
import { useRouter } from 'vue-router'

import { mediaSupplyApi } from '@/lib/api'
import { formatDateTime } from '@/lib/display'
import {
  loadMediaSupplyFavoriteGroups,
  mergeMediaSupplyFavoriteResourceSnapshots,
  removeMediaSupplyFavorite,
  saveMediaSupplyFavoriteGroups,
  type MediaSupplyFavoriteGroup,
  type MediaSupplyFavoriteResourceSnapshot,
} from '@/lib/media-supply-favorites'
import { saveMediaSupplySubmitSelection } from '@/lib/media-supply-submit-selection'
import { useAuthStore } from '@/stores/auth'

const MODEL_ID_AUTHORITY_NEWS = 1

const authStore = useAuthStore()
const router = useRouter()
const groups = ref<MediaSupplyFavoriteGroup[]>(loadMediaSupplyFavoriteGroups(authStore.user?.id))
const groupName = ref('')
const createGroupModalOpen = ref(false)
const activeGroupId = ref(groups.value[0]?.id || 'default')

const totalResources = computed(() =>
  groups.value.reduce((sum, group) => sum + group.resourceIds.length, 0),
)
const allResourceIds = computed(() => [
  ...new Set(groups.value.flatMap((group) => group.resourceIds)),
])
const activeGroup = computed(
  () => groups.value.find((group) => group.id === activeGroupId.value) || groups.value[0],
)
const resourcesById = computed(() => {
  const map = new Map<number, MediaSupplyFavoriteResourceSnapshot>()
  for (const group of groups.value) {
    for (const resource of group.resources) {
      map.set(resource.id, resource)
    }
  }
  return map
})
const activeResources = computed(() => {
  const group = activeGroup.value
  if (!group) {
    return []
  }
  return group.resourceIds.map((resourceId) => resourceForId(group, resourceId))
})

const resourceDetailsQuery = useQuery({
  queryKey: computed(() => ['media-supply', 'favorite-resources', allResourceIds.value.join(',')]),
  queryFn: () => mediaSupplyApi.listResourcesByIds(allResourceIds.value, MODEL_ID_AUTHORITY_NEWS),
  enabled: computed(() => allResourceIds.value.length > 0),
})

const walletQuery = useQuery({
  queryKey: ['media-supply', 'wallet'],
  queryFn: () => mediaSupplyApi.wallet(),
})

watch(
  () => authStore.user?.id,
  (userId) => {
    groups.value = loadMediaSupplyFavoriteGroups(userId)
    activeGroupId.value = groups.value[0]?.id || 'default'
  },
)

watch(
  () => resourceDetailsQuery.data.value?.items,
  (items) => {
    if (!items?.length) {
      return
    }
    groups.value = mergeMediaSupplyFavoriteResourceSnapshots(groups.value, items)
    persist()
  },
)

function refresh(): void {
  groups.value = loadMediaSupplyFavoriteGroups(authStore.user?.id)
  if (!groups.value.some((group) => group.id === activeGroupId.value)) {
    activeGroupId.value = groups.value[0]?.id || 'default'
  }
  void resourceDetailsQuery.refetch()
}

function persist(): void {
  saveMediaSupplyFavoriteGroups(authStore.user?.id, groups.value)
}

function openCreateGroup(): void {
  if (groupName.value.trim()) {
    createGroup()
    return
  }
  createGroupModalOpen.value = true
}

function createGroup(): void {
  const name = groupName.value.trim()
  if (!name) {
    message.warning('请输入分组名称')
    return
  }
  if (groups.value.some((group) => group.name.trim() === name)) {
    message.warning('分组名称已存在')
    return
  }
  const id = `group_${Date.now()}`
  groups.value = [
    ...groups.value,
    {
      id,
      name,
      resourceIds: [],
      resources: [],
      updatedAt: new Date().toISOString(),
    },
  ]
  activeGroupId.value = id
  groupName.value = ''
  createGroupModalOpen.value = false
  persist()
  message.success('常发分组已创建')
}

function removeGroup(groupId: string): void {
  groups.value = groups.value.filter((group) => group.id !== groupId)
  if (groups.value.length === 0) {
    groups.value = loadMediaSupplyFavoriteGroups(authStore.user?.id)
  }
  activeGroupId.value = groups.value[0]?.id || 'default'
  persist()
}

function removeResource(groupId: string, resourceId: number): void {
  groups.value = removeMediaSupplyFavoriteForGroup(groups.value, groupId, resourceId)
  persist()
  message.success('已移出常发分组')
}

async function goSubmitPage(resource: MediaSupplyFavoriteResourceSnapshot): Promise<void> {
  if (!resource.sell_price_cents && resource.sell_price_cents !== 0) {
    message.warning('媒体详情未同步，请刷新后再投稿')
    return
  }
  const refreshedWallet = await walletQuery.refetch()
  const latestBalance =
    refreshedWallet.data?.balance_cents ?? walletQuery.data.value?.balance_cents ?? 0
  if (latestBalance < resource.sell_price_cents) {
    message.warning('媒体投稿余额不足')
    return
  }
  saveMediaSupplySubmitSelection([
    {
      id: resource.id,
      supplier_resource_id: resource.supplier_resource_id || '',
      name: resource.name,
      sell_price_cents: resource.sell_price_cents,
      resource_url: resource.resource_url,
      baidu_weight: resource.baidu_weight,
      resource_remark: resource.resource_remark,
      channel_type: resource.channel_type,
      region: resource.region,
      inclusion_effect: resource.inclusion_effect,
      link_type: resource.link_type,
      publish_rate: resource.publish_rate,
      delivery_speed: resource.delivery_speed,
    },
  ])
  void router.push({ name: 'media-supply-submit' })
}

function removeMediaSupplyFavoriteForGroup(
  currentGroups: MediaSupplyFavoriteGroup[],
  groupId: string,
  resourceId: number,
): MediaSupplyFavoriteGroup[] {
  return currentGroups.map((group) =>
    group.id === groupId ? removeMediaSupplyFavorite([group], resourceId)[0] || group : group,
  )
}

function resourceForId(
  group: MediaSupplyFavoriteGroup,
  resourceId: number,
): MediaSupplyFavoriteResourceSnapshot {
  return (
    group.resources.find((resource) => resource.id === resourceId) ||
    resourcesById.value.get(resourceId) || {
      id: resourceId,
      name: `媒体 #${resourceId}`,
    }
  )
}

function formatMoney(cents?: number | null): string {
  if (typeof cents !== 'number' || !Number.isFinite(cents)) {
    return '--'
  }
  return `￥${(cents / 100).toFixed(2)}`
}

function formatSellPrice(cents?: number | null): string {
  if (typeof cents !== 'number' || !Number.isFinite(cents)) {
    return '--'
  }
  return `￥${Math.ceil(cents / 100)}`
}

function displayValue(value?: string | number | null): string {
  if (typeof value === 'number') {
    return String(value)
  }
  return value?.trim() || '--'
}

function isValidUrl(value?: string | null): boolean {
  if (!value) {
    return false
  }
  return /^https?:\/\//i.test(value.trim())
}
</script>

<template>
  <div class="frequent-page">
    <section class="frequent-toolbar">
      <div class="frequent-toolbar__summary">
        <div class="summary-metric-card">
          <span>分组</span>
          <strong>{{ groups.length }}</strong>
        </div>
        <div class="summary-metric-card">
          <span>常发媒体</span>
          <strong>{{ totalResources }}</strong>
        </div>
      </div>

      <div class="frequent-toolbar__actions">
        <a-input
          v-model:value="groupName"
          placeholder="新建常发分组名称"
          class="frequent-toolbar__input"
          @press-enter="createGroup"
        >
          <template #prefix><PlusOutlined style="color: #98a2b3" /></template>
        </a-input>
        <button type="button" class="toolbar-btn-ok" @click="openCreateGroup">新建分组</button>
        <button type="button" class="toolbar-btn-refresh" @click="refresh">
          <ReloadOutlined :class="{ 'refresh-spinning': resourceDetailsQuery.isFetching.value }" />
          刷新
        </button>
      </div>
    </section>

    <section class="frequent-layout">
      <aside class="group-list">
        <button
          v-for="group in groups"
          :key="group.id"
          type="button"
          class="group-item"
          :class="{ 'group-item--active': activeGroup?.id === group.id }"
          @click="activeGroupId = group.id"
        >
          <span>{{ group.name }}</span>
          <strong>{{ group.resourceIds.length }}</strong>
        </button>
      </aside>

      <section class="group-panel">
        <header v-if="activeGroup" class="group-panel__header">
          <div>
            <p>常发媒体分组</p>
            <h2>{{ activeGroup.name }}</h2>
            <span>
              {{ activeGroup.resourceIds.length }} 个媒体 ·
              {{ formatDateTime(activeGroup.updatedAt) }}
            </span>
          </div>
          <button
            v-if="activeGroup.id !== 'default'"
            type="button"
            class="delete-group-btn"
            @click="removeGroup(activeGroup.id)"
          >
            <DeleteOutlined />
            删除分组
          </button>
        </header>

        <div v-if="activeResources.length > 0" class="resource-list">
          <article v-for="resource in activeResources" :key="resource.id" class="resource-card">
            <div class="resource-card__main">
              <span class="resource-icon"><BankOutlined /></span>
              <div class="resource-card__content">
                <a
                  v-if="isValidUrl(resource.resource_url)"
                  :href="resource.resource_url || undefined"
                  target="_blank"
                  rel="noreferrer"
                  class="resource-name"
                >
                  {{ resource.name }}
                </a>
                <strong v-else class="resource-name">{{ resource.name }}</strong>
                <div class="resource-meta">
                  <span>{{ displayValue(resource.channel_type) }}</span>
                  <span>{{ displayValue(resource.region) }}</span>
                  <span
                    class="resource-meta--weight"
                    v-if="resource.baidu_weight !== null && resource.baidu_weight !== undefined"
                  >
                    百度 {{ displayValue(resource.baidu_weight) }}
                  </span>
                  <span>{{ displayValue(resource.delivery_speed) }}</span>
                </div>
                <p>{{ displayValue(resource.resource_remark) }}</p>
              </div>
            </div>

            <div class="resource-card__side">
              <strong>{{ formatSellPrice(resource.sell_price_cents) }}</strong>
              <span class="resource-id-text">
                ID: {{ resource.supplier_resource_id || `#${resource.id}` }}
              </span>
              <div>
                <button type="button" class="card-btn-submit" @click="goSubmitPage(resource)">
                  <SendOutlined />
                  投稿
                </button>
                <button
                  type="button"
                  class="card-btn-remove"
                  @click="activeGroup && removeResource(activeGroup.id, resource.id)"
                >
                  移出
                </button>
              </div>
            </div>
          </article>
        </div>
        <a-empty v-else description="还没有常发媒体" />
      </section>
    </section>

    <a-modal v-model:open="createGroupModalOpen" title="新建常发分组" width="400px">
      <div class="create-group-modal-body">
        <label class="create-group-modal-label">分组名称</label>
        <a-input
          v-model:value="groupName"
          placeholder="请输入分组名称"
          autofocus
          @press-enter="createGroup"
        />
      </div>
      <template #footer>
        <div class="favorite-modal-footer">
          <button type="button" class="modal-btn-cancel" @click="createGroupModalOpen = false">
            取消
          </button>
          <button type="button" class="modal-btn-ok" @click="createGroup">确认创建</button>
        </div>
      </template>
    </a-modal>
  </div>
</template>

<style scoped>
.frequent-page {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.frequent-toolbar,
.group-list,
.group-panel {
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
}

.frequent-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 20px;
}

.frequent-toolbar__summary {
  display: flex;
  align-items: center;
  gap: 12px;
}

.summary-metric-card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 130px;
  height: 60px;
  padding: 0 16px;
  background: linear-gradient(180deg, #fcfdff 0%, #f8fafc 100%);
  border: 1px solid #e2e8f0;
  border-left: 4px solid #ff1831;
  border-radius: 8px;
  position: relative;
  overflow: hidden;
}

.summary-metric-card span {
  color: #64748b;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.summary-metric-card strong {
  color: #0f172a;
  font-size: 20px;
  font-weight: 800;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}

.frequent-toolbar__actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.frequent-toolbar__input {
  width: 240px;
}

.frequent-toolbar__input :deep(.ant-input-affine-wrapper) {
  border-radius: 6px !important;
  border-color: #d0d5dd !important;
  height: 36px !important;
  padding: 4px 11px !important;
  transition: all 0.2s ease !important;
}

.frequent-toolbar__input :deep(.ant-input-affine-wrapper:hover),
.frequent-toolbar__input :deep(.ant-input-affine-wrapper-focused) {
  border-color: #ff1831 !important;
}

.frequent-toolbar__input :deep(.ant-input-affine-wrapper-focused) {
  box-shadow: 0 0 0 3px rgba(255, 24, 49, 0.12) !important;
}

.toolbar-btn-ok {
  height: 36px;
  padding: 0 16px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: linear-gradient(135deg, #ff1831, #ff5c6e);
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: 0 1px 2px rgba(255, 24, 49, 0.05);
}

.toolbar-btn-ok:hover {
  background: linear-gradient(135deg, #e5152b, #e55256);
  transform: translateY(-0.5px);
  box-shadow: 0 4px 8px rgba(255, 24, 49, 0.15);
}

.toolbar-btn-ok:active {
  transform: translateY(0);
}

.toolbar-btn-refresh {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  font-size: 13px;
  font-weight: 500;
  color: #475467;
  background: #fff;
  border: 1px solid #d0d5dd;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.toolbar-btn-refresh:hover {
  background: #f9fafb;
  color: #1d2939;
  border-color: #98a2b3;
}

.refresh-spinning {
  animation: spin 1s linear infinite;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.frequent-layout {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: 16px;
}

.group-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px;
  align-self: start;
}

.group-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 40px;
  padding: 0 12px;
  color: #475467;
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  text-align: left;
  font-weight: 500;
  position: relative;
  transition: all 0.2s ease;
}

.group-item:hover {
  background: #f8fafc;
  color: #0f172a;
}

.group-item--active {
  color: #ff1831 !important;
  background: #fff4f4 !important;
  font-weight: 700 !important;
}

.group-item--active::after {
  content: '';
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 4px;
  background: #ff1831;
  border-radius: 0 4px 4px 0;
}

.group-item span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.group-item strong {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  font-size: 11px;
  font-weight: 600;
  color: #64748b;
  background: #f1f5f9;
  border-radius: 10px;
  font-variant-numeric: tabular-nums;
  transition: all 0.2s ease;
}

.group-item--active strong {
  color: #ff1831;
  background: #ffebeb;
}

.group-panel {
  min-width: 0;
  padding: 20px;
}

.group-panel__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid #f1f5f9;
}

.group-panel__header p {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  background: #fff4f4;
  color: #ff1831;
  font-size: 11px;
  font-weight: 700;
  border-radius: 4px;
  margin: 0 0 6px;
  letter-spacing: 0.5px;
}

.group-panel__header h2 {
  margin: 0 0 4px;
  color: #0f172a;
  font-size: 22px;
  font-weight: 800;
}

.group-panel__header span {
  color: #64748b;
  font-size: 12px;
}

.delete-group-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  font-size: 13px;
  font-weight: 500;
  color: #64748b;
  background: transparent;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.delete-group-btn:hover {
  color: #ef4444;
  border-color: #fecaca;
  background: #fef2f2;
}

.resource-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.resource-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 188px;
  gap: 16px;
  padding: 16px;
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
  transition: all 0.2s ease;
}

.resource-card:hover {
  border-color: #ffccd1;
  box-shadow: 0 4px 12px rgba(255, 24, 49, 0.05);
  transform: translateY(-1px);
}

.resource-card__main {
  display: flex;
  gap: 14px;
  min-width: 0;
}

.resource-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  color: #ff1831;
  background: #fff4f4;
  border-radius: 8px;
  font-size: 16px;
}

.resource-card__content {
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.resource-name {
  display: block;
  overflow: hidden;
  color: #1e293b;
  font-size: 16px;
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.4;
}

a.resource-name {
  color: #ff1831;
  text-decoration: none;
  transition: color 0.2s ease;
}

a.resource-name:hover {
  color: #d41327;
  text-decoration: underline;
}

.resource-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.resource-meta span {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 4px;
  color: #475467;
  font-size: 12px;
  font-weight: 500;
}

.resource-meta .resource-meta--weight {
  color: #2f8fff;
  background: #eef6ff;
  border-color: #d0e5ff;
}

.resource-card p {
  margin: 10px 0 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #64748b;
  font-size: 12px;
  line-height: 1.5;
}

.resource-card__side {
  display: flex;
  align-items: flex-end;
  flex-direction: column;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
}

.resource-card__side strong {
  color: #ff1831;
  font-size: 20px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}

.resource-id-text {
  color: #64748b;
  font-size: 11px;
  font-family: monospace;
}

.resource-card__side div {
  display: flex;
  gap: 8px;
}

.card-btn-submit {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 28px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 600;
  color: #fff;
  background: linear-gradient(135deg, #ff1831, #ff5c6e);
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.card-btn-submit:hover {
  background: linear-gradient(135deg, #e5152b, #e55256);
  transform: translateY(-0.5px);
  box-shadow: 0 2px 6px rgba(255, 24, 49, 0.15);
}

.card-btn-submit:active {
  transform: translateY(0);
}

.card-btn-remove {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 500;
  color: #ef4444;
  background: #fff;
  border: 1px solid #fecaca;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.card-btn-remove:hover {
  color: #dc2626;
  background: #fef2f2;
  border-color: #fee2e2;
}

/* Modal styling overrides */
.create-group-modal-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 0 4px;
}

.create-group-modal-label {
  font-size: 13px;
  font-weight: 600;
  color: #344054;
}

.create-group-modal-body :deep(.ant-input) {
  border-radius: 6px !important;
  border-color: #d0d5dd !important;
  height: 36px !important;
  transition: all 0.2s ease !important;
}

.create-group-modal-body :deep(.ant-input:hover),
.create-group-modal-body :deep(.ant-input:focus) {
  border-color: #ff1831 !important;
}

.create-group-modal-body :deep(.ant-input:focus) {
  box-shadow: 0 0 0 3px rgba(255, 24, 49, 0.12) !important;
}

.favorite-modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.modal-btn-cancel {
  min-height: 32px;
  padding: 0 16px;
  font-size: 13px;
  font-weight: 500;
  color: #475467;
  background: #fff;
  border: 1px solid #d0d5dd;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.modal-btn-cancel:hover {
  background: #f9fafb;
  color: #1d2939;
  border-color: #98a2b3;
}

.modal-btn-ok {
  min-height: 32px;
  padding: 0 18px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: linear-gradient(135deg, #ff1831, #ff5c6e);
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: 0 1px 2px rgba(255, 24, 49, 0.05);
}

.modal-btn-ok:hover {
  background: linear-gradient(135deg, #e5152b, #e55256);
  transform: translateY(-0.5px);
  box-shadow: 0 4px 8px rgba(255, 24, 49, 0.15);
}

.modal-btn-ok:active {
  transform: translateY(0);
}

@media (max-width: 960px) {
  .frequent-layout {
    grid-template-columns: 1fr;
  }

  .group-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  }
}

@media (max-width: 720px) {
  .frequent-toolbar,
  .frequent-toolbar__actions,
  .group-panel__header {
    align-items: stretch;
    flex-direction: column;
  }

  .frequent-toolbar__summary {
    justify-content: space-between;
  }

  .frequent-toolbar__input {
    width: 100%;
  }

  .resource-card {
    grid-template-columns: 1fr;
  }

  .resource-card__side {
    align-items: flex-start;
  }
}
</style>
