<script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { computed, reactive, ref } from 'vue'

import {
  fetchAdminListings,
  type AdminListingPage,
  type AdminListingQuery,
  type Listing,
} from '@/features/listings'
import { useAdminTable } from '@/features/admin/composables/useAdminTable'
import { adminPath } from '@/shared/utils/adminPath'
import { formatCentWithSymbol } from '@/shared/utils/money'
import {
  assetRegions,
  formatEstimatedRentalDuration,
  formatHafCoinM,
  formatListingCode,
  formatRatio,
  getCoinWan,
  getDailyLoss,
  getResourceQuantity,
  getSkinGroup,
} from '@/shared/utils/listingDisplay'

const filters = reactive<AdminListingQuery>({
  keyword: '',
  owner_id: '',
  status: '',
  review_status: '',
})

const pageSize = ref(10)
const currentPage = ref(1)

const {
  loading,
  data: listingPage,
  load: loadListings,
} = useAdminTable<AdminListingPage>({
  fetchFn: () =>
    fetchAdminListings({
      ...filters,
      page: currentPage.value,
      page_size: pageSize.value,
    }),
  initialData: {
    items: [],
    total: 0,
    page: 1,
    page_size: 10,
  },
})

const listings = computed(() => listingPage.value.items)
const totalListings = computed(() => listingPage.value.total)
const publishedCount = computed(
  () => listings.value.filter(item => item.status === 'published').length
)
const rentedCount = computed(() => listings.value.filter(item => item.status === 'rented').length)
const pendingCount = computed(
  () => listings.value.filter(item => item.review_status === 'pending').length
)
const totalPages = computed(() => Math.max(1, Math.ceil(totalListings.value / pageSize.value)))

const screenshotColumns = [
  { label: '商品编码', width: 88, read: (row: Listing) => formatListingCode(row) },
  { label: '地区', width: 92, read: (row: Listing) => regionText(row) },
  { label: '上号方式', width: 78, read: (row: Listing) => row.login_platform || '-' },
  { label: '哈夫币(M)', width: 86, read: (row: Listing) => listingCoinM(row) },
  { label: '保险', width: 56, read: (row: Listing) => assetText(row, 'season_insurance') },
  { label: '体力(级)', width: 70, read: (row: Listing) => levelText(row, 'stamina_level') },
  { label: '负重(级)', width: 70, read: (row: Listing) => levelText(row, 'load_level') },
  { label: '账号等级', width: 76, read: (row: Listing) => assetText(row, 'fire_level') },
  { label: '绝密KD', width: 66, read: (row: Listing) => assetText(row, 'secret_kd') },
  { label: 'awm子弹', width: 74, read: (row: Listing) => resourceText(row, 'awmAmmo') },
  { label: '六头', width: 50, read: (row: Listing) => resourceText(row, 'helmet6') },
  { label: '六甲', width: 50, read: (row: Listing) => resourceText(row, 'armor6') },
  { label: '特殊刀皮', width: 110, read: (row: Listing) => skinGroupText(row, 'melee') },
  {
    label: '人物红皮/人物金皮/武器皮肤',
    width: 420,
    read: (row: Listing) => characterAndWeaponSkinText(row),
  },
  { label: '租金/押金', width: 96, read: (row: Listing) => rentAndDepositText(row) },
  { label: '比例', width: 64, read: (row: Listing) => formatRatio(row) },
  {
    label: '租期',
    width: 92,
    read: (row: Listing) => rentalPeriodText(row),
  },
] as const

async function queryListings() {
  currentPage.value = 1
  await loadListings()
}

function resetFilters() {
  filters.keyword = ''
  filters.owner_id = ''
  filters.status = ''
  filters.review_status = ''
  void queryListings()
}

function setStatusFilter(status: string) {
  filters.status = (filters.status === status ? '' : status) as AdminListingQuery['status']
  filters.review_status = ''
  void queryListings()
}

function setReviewStatusFilter(reviewStatus: string) {
  filters.review_status = (
    filters.review_status === reviewStatus ? '' : reviewStatus
  ) as AdminListingQuery['review_status']
  filters.status = ''
  void queryListings()
}

async function handlePageSizeChange(size: number) {
  pageSize.value = size
  currentPage.value = 1
  await loadListings()
}

async function prevPage() {
  currentPage.value = Math.max(1, currentPage.value - 1)
  await loadListings()
}

async function nextPage() {
  currentPage.value = Math.min(totalPages.value, currentPage.value + 1)
  await loadListings()
}

async function copyTableScreenshot() {
  try {
    const blob = await createTableScreenshotBlob()
    if (!navigator.clipboard || typeof ClipboardItem === 'undefined') {
      ElMessage.warning('当前浏览器不支持直接复制图片，请使用下载截图')
      return
    }
    await navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })])
    ElMessage.success('表格截图已复制到剪贴板')
  } catch (error) {
    ElMessage.error(readScreenshotError(error, '复制截图失败'))
  }
}

async function downloadTableScreenshot() {
  try {
    const blob = await createTableScreenshotBlob()
    const url = URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = `商品管理表格-${formatFileTime(new Date())}.png`
    link.click()
    URL.revokeObjectURL(url)
    ElMessage.success('表格截图已下载')
  } catch (error) {
    ElMessage.error(readScreenshotError(error, '下载截图失败'))
  }
}

async function createTableScreenshotBlob() {
  if (!listings.value.length) throw new Error('当前页暂无可截图数据')
  const canvas = renderTableScreenshotCanvas(listings.value)
  const blob = await new Promise<Blob | null>(resolve => canvas.toBlob(resolve, 'image/png'))
  if (!blob) throw new Error('截图生成失败')
  return blob
}

function renderTableScreenshotCanvas(rows: Listing[]) {
  const ratio = window.devicePixelRatio || 1
  const paddingX = 24
  const paddingY = 20
  const titleHeight = 44
  const headerHeight = 34
  const lineHeight = 18
  const cellPaddingX = 8
  const cellPaddingY = 10
  const tableWidth = screenshotColumns.reduce((sum, column) => sum + column.width, 0)
  const canvasWidth = tableWidth + paddingX * 2

  const measureCanvas = document.createElement('canvas')
  const measureCtx = measureCanvas.getContext('2d')
  if (!measureCtx) throw new Error('截图画布初始化失败')
  measureCtx.font = '13px Arial, "Microsoft YaHei", sans-serif'

  const rowLines = rows.map(row =>
    screenshotColumns.map(column =>
      wrapCanvasText(measureCtx, column.read(row), column.width - cellPaddingX * 2)
    )
  )
  const rowHeights = rowLines.map(lineGroups => {
    const maxLines = Math.max(...lineGroups.map(lines => lines.length), 1)
    return Math.max(44, maxLines * lineHeight + cellPaddingY * 2)
  })
  const canvasHeight =
    paddingY * 2 + titleHeight + headerHeight + rowHeights.reduce((sum, height) => sum + height, 0)
  const canvas = document.createElement('canvas')
  canvas.width = Math.round(canvasWidth * ratio)
  canvas.height = Math.round(canvasHeight * ratio)
  canvas.style.width = `${canvasWidth}px`
  canvas.style.height = `${canvasHeight}px`
  const ctx = canvas.getContext('2d')
  if (!ctx) throw new Error('截图画布初始化失败')
  ctx.scale(ratio, ratio)
  ctx.fillStyle = '#ffffff'
  ctx.fillRect(0, 0, canvasWidth, canvasHeight)

  ctx.fillStyle = '#1b2559'
  ctx.font = '700 18px Arial, "Microsoft YaHei", sans-serif'
  ctx.fillText('商品管理', paddingX, paddingY + 20)
  ctx.fillStyle = '#8f9bba'
  ctx.font = '12px Arial, "Microsoft YaHei", sans-serif'
  ctx.fillText(
    `当前页 ${rows.length} 条 / 查询结果 ${totalListings.value} 条`,
    paddingX,
    paddingY + 40
  )

  let y = paddingY + titleHeight
  drawRect(ctx, paddingX, y, tableWidth, headerHeight, '#f8f9fe')
  ctx.font = '700 12px Arial, "Microsoft YaHei", sans-serif'
  ctx.fillStyle = '#8f9bba'
  let x = paddingX
  for (const column of screenshotColumns) {
    drawCellText(ctx, [column.label], x + cellPaddingX, y + 22, lineHeight)
    x += column.width
  }
  drawLine(ctx, paddingX, y + headerHeight, paddingX + tableWidth, y + headerHeight)
  y += headerHeight

  ctx.font = '13px Arial, "Microsoft YaHei", sans-serif'
  rows.forEach((row, rowIndex) => {
    const rowHeight = rowHeights[rowIndex] ?? 44
    drawRect(ctx, paddingX, y, tableWidth, rowHeight, rowIndex % 2 === 0 ? '#ffffff' : '#fbfcff')
    x = paddingX
    for (const [columnIndex, column] of screenshotColumns.entries()) {
      const lines = rowLines[rowIndex]?.[columnIndex] ?? ['-']
      ctx.fillStyle = columnIndex === 0 ? '#4b5563' : '#3f4654'
      ctx.font =
        columnIndex === 0
          ? '700 13px Arial, "Microsoft YaHei", sans-serif'
          : '13px Arial, "Microsoft YaHei", sans-serif'
      drawCellText(ctx, lines, x + cellPaddingX, y + cellPaddingY + 14, lineHeight)
      x += column.width
    }
    drawLine(ctx, paddingX, y + rowHeight, paddingX + tableWidth, y + rowHeight)
    y += rowHeight
  })
  return canvas
}

function wrapCanvasText(ctx: CanvasRenderingContext2D, text: string, maxWidth: number) {
  const paragraphs = String(text || '-').split('\n')
  const lines: string[] = []
  for (const paragraph of paragraphs) {
    let line = ''
    for (const char of paragraph) {
      const nextLine = line + char
      if (line && ctx.measureText(nextLine).width > maxWidth) {
        lines.push(line)
        line = char
      } else {
        line = nextLine
      }
    }
    lines.push(line || '-')
  }
  return lines
}

function drawCellText(
  ctx: CanvasRenderingContext2D,
  lines: string[],
  x: number,
  y: number,
  lineHeight: number
) {
  lines.forEach((line, index) => {
    ctx.fillText(line, x, y + index * lineHeight)
  })
}

function drawRect(
  ctx: CanvasRenderingContext2D,
  x: number,
  y: number,
  width: number,
  height: number,
  color: string
) {
  ctx.fillStyle = color
  ctx.fillRect(x, y, width, height)
}

function drawLine(
  ctx: CanvasRenderingContext2D,
  startX: number,
  startY: number,
  endX: number,
  endY: number
) {
  ctx.strokeStyle = '#e6eaf2'
  ctx.lineWidth = 1
  ctx.beginPath()
  ctx.moveTo(startX, startY)
  ctx.lineTo(endX, endY)
  ctx.stroke()
}

function formatFileTime(date: Date) {
  const pad = (value: number) => String(value).padStart(2, '0')
  return `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-${pad(date.getHours())}${pad(date.getMinutes())}`
}

function readScreenshotError(error: unknown, fallback: string) {
  return error instanceof Error ? error.message : fallback
}

function listingPrice(row: Listing) {
  return formatCentWithSymbol(row.price_cent)
}

function listingCoinM(row: Listing) {
  return formatHafCoinM(getCoinWan(row))
}

function assetText(row: Listing, key: string) {
  const value = row.asset_summary?.[key]
  if (typeof value === 'number') return formatQuantity(value)
  if (typeof value === 'string' && value.trim()) return value.trim()
  return '-'
}

function levelText(row: Listing, key: string) {
  const value = assetText(row, key)
  return value === '-' ? value : value.replace(/级$/, '')
}

function regionText(row: Listing) {
  const regions = assetRegions(row)
  return regions.length ? regions.join('、') : '-'
}

function resourceText(row: Listing, key: string) {
  const quantity = getResourceQuantity(row, key)
  return quantity > 0 ? formatQuantity(quantity) : '-'
}

function skinGroupText(row: Listing, groupKey: string) {
  const skins = getSkinGroup(row, groupKey)
  return skins.length ? skins.join('、') : '-'
}

function characterAndWeaponSkinText(row: Listing) {
  const groups = [
    { label: '红皮', key: 'operatorRed' },
    { label: '金皮', key: 'operatorGold' },
    { label: '武器', key: 'weapon' },
  ]
  const parts = groups
    .map(group => {
      const names = getSkinGroup(row, group.key)
      return names.length ? `${group.label}：${names.join('、')}` : ''
    })
    .filter(Boolean)
  return parts.length ? parts.join(' / ') : '-'
}

function rentAndDepositText(row: Listing) {
  return `${listingPrice(row)}/${formatCentWithSymbol(row.deposit_amount_cent)}`
}

function estimateTitle(row: Listing) {
  const dailyLoss = getDailyLoss(row)
  return dailyLoss ? `按哈夫币 ${listingCoinM(row)}、日耗 ${dailyLoss} 估算` : '未配置日耗'
}

function rentalPeriodText(row: Listing) {
  const dailyLoss = getDailyLoss(row)
  return [formatEstimatedRentalDuration(row), dailyLoss ? `日耗 ${dailyLoss}` : '']
    .filter(Boolean)
    .join('\n')
}

function formatQuantity(value: number) {
  const rounded = Math.round(value * 10) / 10
  return Number.isInteger(rounded) ? `${rounded}` : rounded.toFixed(1)
}
</script>

<template>
  <section class="page admin-listings-page">
    <div class="page-header-row">
      <div class="page-header">
        <p class="eyebrow">Listings</p>
        <h1>商品管理</h1>
        <p>查看商品编码、地区、上号方式、账号资产、租金押金、比例和预计租期。</p>
      </div>
    </div>

    <div class="listing-control-panel">
      <!-- 统计指标行 -->
      <div class="listing-stats-row">
        <div
          class="stat-card clickable"
          :class="{ active: !filters.status && !filters.review_status }"
          @click="resetFilters"
        >
          <span class="stat-label">全部商品</span>
          <strong class="stat-value">{{ totalListings }}</strong>
        </div>
        <div
          class="stat-card clickable"
          :class="{ active: filters.status === 'published' }"
          @click="setStatusFilter('published')"
        >
          <span class="stat-label">已上架</span>
          <strong class="stat-value">{{ publishedCount }}</strong>
        </div>
        <div
          class="stat-card clickable"
          :class="{ active: filters.status === 'rented' }"
          @click="setStatusFilter('rented')"
        >
          <span class="stat-label">已锁定</span>
          <strong class="stat-value">{{ rentedCount }}</strong>
        </div>
        <div
          class="stat-card clickable"
          :class="{ active: filters.review_status === 'pending' }"
          @click="setReviewStatusFilter('pending')"
        >
          <span class="stat-label">待审核</span>
          <strong class="stat-value">{{ pendingCount }}</strong>
        </div>
      </div>

      <!-- 筛选和操作行 -->
      <div class="listing-filter-row">
        <el-form class="listing-filter-bar" inline>
          <el-form-item label="编号">
            <el-input
              v-model="filters.keyword"
              clearable
              placeholder="商品编号 / 订单编号"
              style="width: 210px"
              @keyup.enter="queryListings"
              @clear="queryListings"
            />
          </el-form-item>
          <el-form-item label="号主 ID">
            <el-input
              v-model="filters.owner_id"
              clearable
              placeholder="筛选号主"
              style="width: 160px"
            />
          </el-form-item>
          <el-form-item label="商品状态">
            <el-select
              v-model="filters.status"
              clearable
              placeholder="全部状态"
              style="width: 140px"
            >
              <el-option label="草稿" value="draft" />
              <el-option label="已上架" value="published" />
              <el-option label="已锁定" value="rented" />
              <el-option label="已下架" value="offline" />
              <el-option label="异常" value="abnormal" />
            </el-select>
          </el-form-item>
          <el-form-item label="审核状态">
            <el-select
              v-model="filters.review_status"
              clearable
              placeholder="全部审核"
              style="width: 140px"
            >
              <el-option label="未提交" value="none" />
              <el-option label="待审核" value="pending" />
              <el-option label="已通过" value="approved" />
              <el-option label="已拒绝" value="rejected" />
            </el-select>
          </el-form-item>
        </el-form>
        <div class="listing-action-strip">
          <el-button @click="resetFilters">重置</el-button>
          <el-button type="primary" :icon="Search" :loading="loading" @click="queryListings"
            >查询</el-button
          >
          <el-button :disabled="!listings.length" @click="copyTableScreenshot">复制截图</el-button>
          <el-button :disabled="!listings.length" @click="downloadTableScreenshot"
            >下载截图</el-button
          >
        </div>
      </div>
    </div>

    <el-table
      v-loading="loading"
      class="table-panel admin-listings-table"
      :data="listings"
      row-key="id"
      stripe
      empty-text="暂无商品"
    >
      <el-table-column label="商品编码" width="88">
        <template #default="{ row }">
          <strong class="listing-code">{{ formatListingCode(row) }}</strong>
        </template>
      </el-table-column>
      <el-table-column label="地区" width="86">
        <template #default="{ row }">{{ regionText(row) }}</template>
      </el-table-column>
      <el-table-column prop="login_platform" label="上号方式" width="78" />
      <el-table-column label="哈夫币(M)" width="82">
        <template #default="{ row }">{{ listingCoinM(row) }}</template>
      </el-table-column>
      <el-table-column label="保险" width="54">
        <template #default="{ row }">{{ assetText(row, 'season_insurance') }}</template>
      </el-table-column>
      <el-table-column label="体力(级)" width="68">
        <template #default="{ row }">{{ levelText(row, 'stamina_level') }}</template>
      </el-table-column>
      <el-table-column label="负重(级)" width="68">
        <template #default="{ row }">{{ levelText(row, 'load_level') }}</template>
      </el-table-column>
      <el-table-column label="账号等级" width="74">
        <template #default="{ row }">{{ assetText(row, 'fire_level') }}</template>
      </el-table-column>
      <el-table-column label="绝密KD" width="66">
        <template #default="{ row }">{{ assetText(row, 'secret_kd') }}</template>
      </el-table-column>
      <el-table-column label="awm子弹" width="72">
        <template #default="{ row }">{{ resourceText(row, 'awmAmmo') }}</template>
      </el-table-column>
      <el-table-column label="六头" width="48">
        <template #default="{ row }">{{ resourceText(row, 'helmet6') }}</template>
      </el-table-column>
      <el-table-column label="六甲" width="48">
        <template #default="{ row }">{{ resourceText(row, 'armor6') }}</template>
      </el-table-column>
      <el-table-column label="特殊刀皮" width="104">
        <template #default="{ row }">
          {{ skinGroupText(row, 'melee') }}
        </template>
      </el-table-column>
      <el-table-column label="人物红皮/人物金皮/武器皮肤" min-width="226">
        <template #default="{ row }">
          {{ characterAndWeaponSkinText(row) }}
        </template>
      </el-table-column>
      <el-table-column label="租金/押金" width="90">
        <template #default="{ row }">{{ rentAndDepositText(row) }}</template>
      </el-table-column>
      <el-table-column label="比例" width="62">
        <template #default="{ row }">{{ formatRatio(row) }}</template>
      </el-table-column>
      <el-table-column label="租期" width="82">
        <template #default="{ row }">
          <span :title="estimateTitle(row)">{{ formatEstimatedRentalDuration(row) }}</span>
          <span v-if="getDailyLoss(row)" class="table-subtext">日耗 {{ getDailyLoss(row) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="详情" width="60">
        <template #default="{ row }">
          <RouterLink :to="adminPath(`listings/${row.id}`)">
            <el-button size="small">详情</el-button>
          </RouterLink>
        </template>
      </el-table-column>
    </el-table>

    <div class="table-pagination">
      <span class="pagination-summary"
        >当前页 {{ listings.length }} 条，共 {{ totalListings }} 条</span
      >
      <div class="pagination-controls">
        <span class="pagination-size-label">每页</span>
        <el-select
          :model-value="pageSize"
          class="page-size-select"
          size="small"
          @update:model-value="handlePageSizeChange"
        >
          <el-option :value="10" label="10条" />
          <el-option :value="20" label="20条" />
          <el-option :value="50" label="50条" />
          <el-option :value="100" label="100条" />
        </el-select>
        <span class="pagination-page">{{ currentPage }}/{{ totalPages }}页</span>
        <el-button size="small" :disabled="currentPage <= 1" @click="prevPage">上页</el-button>
        <el-button size="small" :disabled="currentPage >= totalPages" @click="nextPage"
          >下页</el-button
        >
      </div>
    </div>
  </section>
</template>
