<template>
  <div class="media-ops-page">
    <div class="media-ops-header">
      <div>
        <h2 class="ops-page-title">媒体资源运营</h2>
        <div class="media-ops-header__meta">上游资源售价、客户可见性、投稿余额</div>
      </div>
      <a-button :loading="syncLoading" @click="queueSync">
        <template #icon><ReloadOutlined /></template>
        同步缓存
      </a-button>
    </div>

    <a-tabs v-model:active-key="activeTab" class="media-ops-tabs">
      <a-tab-pane key="resources" tab="资源与价格">
        <div class="ops-card media-ops-card">
          <div class="ops-toolbar media-ops-toolbar">
            <a-input
              v-model:value="resourceFilter.keyword"
              allow-clear
              placeholder="资源名称"
              style="width: 220px"
              @press-enter="resetResources"
            />
            <a-input
              v-model:value="resourceFilter.remarkKeyword"
              allow-clear
              placeholder="备注"
              style="width: 220px"
              @press-enter="resetResources"
            />
            <a-select
              v-model:value="resourceFilter.visibility"
              allow-clear
              placeholder="客户可见性"
              style="width: 150px"
              :options="visibilityOptions"
              @change="resetResources"
            />
            <a-input
              v-model:value="resourceFilter.channelType"
              allow-clear
              placeholder="频道类型"
              style="width: 150px"
              @press-enter="resetResources"
            />
            <a-input
              v-model:value="resourceFilter.region"
              allow-clear
              placeholder="地区"
              style="width: 130px"
              @press-enter="resetResources"
            />
            <a-input
              v-model:value="resourceFilter.minPrice"
              allow-clear
              placeholder="最低售价"
              style="width: 120px"
              @press-enter="resetResources"
            />
            <a-input
              v-model:value="resourceFilter.maxPrice"
              allow-clear
              placeholder="最高售价"
              style="width: 120px"
              @press-enter="resetResources"
            />
            <a-button type="primary" @click="resetResources">查询</a-button>
            <a-button @click="clearResourceFilters">重置</a-button>
          </div>

          <a-table
            :columns="resourceColumns"
            :data-source="resourceRows"
            :loading="resourceLoading"
            :pagination="resourcePagination"
            row-key="id"
            :scroll="{ x: 1680 }"
            @change="onResourceTableChange"
          >
            <template #bodyCell="{ column, record }">
              <template v-if="column.key === 'name'">
                <div class="resource-main">
                  <a
                    v-if="isValidUrl(record.resource_url)"
                    :href="record.resource_url || undefined"
                    target="_blank"
                    rel="noreferrer"
                    class="resource-link"
                  >
                    {{ record.name }}
                  </a>
                  <strong v-else>{{ record.name }}</strong>
                  <div class="resource-sub">
                    <code>{{ record.supplier_resource_id }}</code>
                    <a-tag :color="statusColor(record.status)">
                      {{ statusLabel(record.status) }}
                    </a-tag>
                  </div>
                </div>
              </template>
              <template v-else-if="column.key === 'price'">
                <div class="price-stack">
                  <strong>{{ formatSellPrice(record.sell_price_cents) }}</strong>
                  <span>成本 {{ formatMoney(record.cost_price_cents) }}</span>
                </div>
              </template>
              <template v-else-if="column.key === 'margin'">
                <span
                  :class="
                    record.sell_price_cents <= record.cost_price_cents ? 'margin-risk' : 'margin-ok'
                  "
                >
                  {{ formatMoney(record.sell_price_cents - record.cost_price_cents) }}
                </span>
              </template>
              <template v-else-if="column.key === 'baidu_weight'">
                <a-tag color="blue">百度 {{ record.baidu_weight ?? 0 }}</a-tag>
              </template>
              <template v-else-if="column.key === 'customer_visible'">
                <a-switch
                  :checked="record.customer_visible"
                  checked-children="显示"
                  un-checked-children="隐藏"
                  :loading="visibilityLoadingId === record.id"
                  @change="
                    (checked: boolean | string | number) =>
                      updateVisibility(record, Boolean(checked))
                  "
                />
              </template>
              <template v-else-if="column.key === 'remark'">
                <a-tooltip :title="displayValue(record.resource_remark)">
                  <span class="remark-cell">{{ displayValue(record.resource_remark) }}</span>
                </a-tooltip>
              </template>
              <template v-else-if="column.key === 'last_synced_at'">
                {{ formatDate(record.last_synced_at) }}
              </template>
              <template v-else-if="column.key === 'actions'">
                <div class="table-actions-row">
                  <a-tooltip title="调整售价">
                    <a-button
                      type="text"
                      class="action-btn action-edit"
                      @click="openPriceModal(record)"
                    >
                      <EditOutlined />
                    </a-button>
                  </a-tooltip>
                </div>
              </template>
            </template>
          </a-table>
        </div>
      </a-tab-pane>

      <a-tab-pane key="wallets" tab="客户余额">
        <div class="ops-card media-ops-card">
          <div class="ops-toolbar media-ops-toolbar">
            <a-input
              v-model:value="walletFilter.keyword"
              allow-clear
              placeholder="客户 / 手机 / 租户"
              style="width: 260px"
              @press-enter="resetWallets"
            />
            <a-input
              v-model:value="walletFilter.tenantId"
              allow-clear
              placeholder="租户 ID"
              style="width: 130px"
              @press-enter="resetWallets"
            />
            <a-button type="primary" @click="resetWallets">查询</a-button>
            <a-button @click="clearWalletFilters">重置</a-button>
          </div>

          <a-table
            :columns="walletColumns"
            :data-source="walletRows"
            :loading="walletLoading"
            :pagination="walletPagination"
            row-key="wallet_key"
            :scroll="{ x: 1100 }"
            @change="onWalletTableChange"
          >
            <template #bodyCell="{ column, record }">
              <template v-if="column.key === 'user'">
                <div class="resource-main">
                  <strong>
                    {{ record.user_name || record.user_phone || `用户 ${record.user_id}` }}
                  </strong>
                  <div class="resource-sub">
                    <code>U{{ record.user_id }}</code>
                    <span>{{ record.user_phone || '未绑定手机' }}</span>
                  </div>
                </div>
              </template>
              <template v-else-if="column.key === 'tenant'">
                <div>{{ record.tenant_name || `租户 ${record.tenant_id}` }}</div>
                <div class="muted">T{{ record.tenant_id }}</div>
              </template>
              <template v-else-if="column.key === 'balance_cents'">
                <strong class="wallet-balance">{{ formatMoney(record.balance_cents) }}</strong>
              </template>
              <template v-else-if="column.key === 'ledger'">
                <div>{{ record.ledger_entries }} 条</div>
                <div class="muted">
                  {{ record.last_ledger_at ? formatDate(record.last_ledger_at) : '暂无账单' }}
                </div>
              </template>
              <template v-else-if="column.key === 'updated_at'">
                {{ formatDate(record.updated_at) }}
              </template>
              <template v-else-if="column.key === 'actions'">
                <a-button type="link" @click="openWalletModal(record)">调整余额</a-button>
              </template>
            </template>
          </a-table>
        </div>
      </a-tab-pane>
    </a-tabs>

    <a-modal
      v-model:open="priceModalOpen"
      title="调整媒体售价"
      :confirm-loading="priceSaving"
      @ok="submitPrice"
      @cancel="priceTarget = null"
    >
      <div v-if="priceTarget" class="edit-stack">
        <a-descriptions :column="1" size="small" bordered>
          <a-descriptions-item label="资源">{{ priceTarget.name }}</a-descriptions-item>
          <a-descriptions-item label="成本">
            {{ formatMoney(priceTarget.cost_price_cents) }}
          </a-descriptions-item>
          <a-descriptions-item label="当前售价">
            {{ formatSellPrice(priceTarget.sell_price_cents) }}
          </a-descriptions-item>
        </a-descriptions>
        <a-form layout="vertical">
          <a-form-item label="平台售价">
            <a-input v-model:value="priceForm.yuan" prefix="￥" placeholder="不能低于上游成本价" />
          </a-form-item>
        </a-form>
      </div>
    </a-modal>

    <a-modal
      v-model:open="walletModalOpen"
      title="手动调整客户媒体余额"
      :confirm-loading="walletSaving"
      @ok="submitWalletAdjustment"
      @cancel="walletTarget = null"
    >
      <div v-if="walletTarget" class="edit-stack">
        <a-descriptions :column="1" size="small" bordered>
          <a-descriptions-item label="客户">
            {{ walletTarget.user_name || walletTarget.user_phone || walletTarget.user_id }}
          </a-descriptions-item>
          <a-descriptions-item label="租户">
            {{ walletTarget.tenant_name || walletTarget.tenant_id }}
          </a-descriptions-item>
          <a-descriptions-item label="当前余额">
            {{ formatMoney(walletTarget.balance_cents) }}
          </a-descriptions-item>
        </a-descriptions>
        <a-form layout="vertical">
          <a-form-item label="调整金额">
            <a-input v-model:value="walletForm.yuan" prefix="￥" placeholder="正数充值，负数扣减" />
          </a-form-item>
          <a-form-item label="备注">
            <a-textarea
              v-model:value="walletForm.note"
              :rows="3"
              placeholder="账单备注，客户可见"
            />
          </a-form-item>
        </a-form>
      </div>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { EditOutlined, ReloadOutlined } from '@ant-design/icons-vue'
import type { TableColumnsType, TablePaginationConfig } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import dayjs from 'dayjs'
import { computed, onMounted, reactive, ref, watch } from 'vue'

import { showOpsError } from '@/lib/errors'
import {
  opsMediaSupplyApi,
  type OpsMediaSupplyResource,
  type OpsMediaSupplyWallet,
} from '@/lib/media-supply'

interface WalletRow extends OpsMediaSupplyWallet {
  wallet_key: string
}

const MODEL_ID_AUTHORITY_NEWS = 1
const PAGE_SIZE = 20

const activeTab = ref('resources')
const resourcePage = ref(1)
const resourcePageSize = ref(PAGE_SIZE)
const resourceLoading = ref(false)
const resourceTotal = ref(0)
const resourceRows = ref<OpsMediaSupplyResource[]>([])
const visibilityLoadingId = ref<number | null>(null)
const syncLoading = ref(false)
const priceModalOpen = ref(false)
const priceSaving = ref(false)
const priceTarget = ref<OpsMediaSupplyResource | null>(null)
const priceForm = reactive({
  yuan: '',
})

const walletPage = ref(1)
const walletPageSize = ref(PAGE_SIZE)
const walletLoading = ref(false)
const walletTotal = ref(0)
const walletRows = ref<WalletRow[]>([])
const walletModalOpen = ref(false)
const walletSaving = ref(false)
const walletTarget = ref<WalletRow | null>(null)
const walletForm = reactive({
  yuan: '',
  note: '',
})

const resourceFilter = reactive({
  keyword: '',
  remarkKeyword: '',
  visibility: undefined as string | undefined,
  channelType: '',
  region: '',
  minPrice: '',
  maxPrice: '',
})

const walletFilter = reactive({
  keyword: '',
  tenantId: '',
})

const visibilityOptions = [
  { label: '客户可见', value: 'visible' },
  { label: '客户隐藏', value: 'hidden' },
]

const resourceColumns: TableColumnsType<OpsMediaSupplyResource> = [
  { title: '媒体名称', key: 'name', width: 320, fixed: 'left' },
  { title: '售价 / 成本', key: 'price', width: 150, align: 'right' },
  { title: '毛利', key: 'margin', width: 120, align: 'right' },
  { title: '频道', dataIndex: 'channel_type', key: 'channel_type', width: 120 },
  { title: '地区', dataIndex: 'region', key: 'region', width: 110 },
  { title: '收录', dataIndex: 'inclusion_effect', key: 'inclusion_effect', width: 140 },
  { title: '权重', key: 'baidu_weight', width: 110, align: 'center' },
  { title: '链接', dataIndex: 'link_type', key: 'link_type', width: 110 },
  { title: '出稿', dataIndex: 'publish_rate', key: 'publish_rate', width: 110 },
  { title: '速度', dataIndex: 'delivery_speed', key: 'delivery_speed', width: 140 },
  { title: '备注', key: 'remark', width: 320 },
  { title: '客户可见', key: 'customer_visible', width: 130, align: 'center' },
  { title: '同步时间', key: 'last_synced_at', width: 170 },
  { title: '操作', key: 'actions', width: 90, fixed: 'right', align: 'center' },
]

const walletColumns: TableColumnsType<WalletRow> = [
  { title: '客户', key: 'user', width: 260, fixed: 'left' },
  { title: '租户', key: 'tenant', width: 220 },
  { title: '余额', key: 'balance_cents', width: 160, align: 'right' },
  { title: '账单', key: 'ledger', width: 180 },
  { title: '更新时间', key: 'updated_at', width: 180 },
  { title: '操作', key: 'actions', width: 130, fixed: 'right', align: 'center' },
]

const resourcePagination = computed<TablePaginationConfig>(() => ({
  current: resourcePage.value,
  pageSize: resourcePageSize.value,
  total: resourceTotal.value,
  showSizeChanger: true,
  showTotal: (total) => `共 ${total} 条`,
}))

const walletPagination = computed<TablePaginationConfig>(() => ({
  current: walletPage.value,
  pageSize: walletPageSize.value,
  total: walletTotal.value,
  showSizeChanger: true,
  showTotal: (total) => `共 ${total} 条`,
}))

watch(activeTab, (key) => {
  if (key === 'wallets' && walletRows.value.length === 0) {
    void loadWallets()
  }
})

onMounted(() => {
  void loadResources()
})

async function loadResources(): Promise<void> {
  resourceLoading.value = true
  try {
    const result = await opsMediaSupplyApi.listResources({
      model_id: MODEL_ID_AUTHORITY_NEWS,
      keyword: resourceFilter.keyword.trim() || undefined,
      remark_keyword: resourceFilter.remarkKeyword.trim() || undefined,
      visibility: resourceFilter.visibility,
      channel_type: resourceFilter.channelType.trim() || undefined,
      region: resourceFilter.region.trim() || undefined,
      min_price_cents: yuanToCentsOptional(resourceFilter.minPrice),
      max_price_cents: yuanToCentsOptional(resourceFilter.maxPrice),
      page: resourcePage.value,
      page_size: resourcePageSize.value,
    })
    resourceRows.value = result.items
    resourceTotal.value = result.total
  } catch (error) {
    showOpsError(error)
  } finally {
    resourceLoading.value = false
  }
}

async function loadWallets(): Promise<void> {
  walletLoading.value = true
  try {
    const result = await opsMediaSupplyApi.listWallets({
      keyword: walletFilter.keyword.trim() || undefined,
      tenant_id: parsePositiveNumber(walletFilter.tenantId),
      page: walletPage.value,
      page_size: walletPageSize.value,
    })
    walletRows.value = result.items.map((item) => ({
      ...item,
      wallet_key: `${item.tenant_id}:${item.user_id}`,
    }))
    walletTotal.value = result.total
  } catch (error) {
    showOpsError(error)
  } finally {
    walletLoading.value = false
  }
}

function resetResources(): void {
  resourcePage.value = 1
  void loadResources()
}

function clearResourceFilters(): void {
  resourceFilter.keyword = ''
  resourceFilter.remarkKeyword = ''
  resourceFilter.visibility = undefined
  resourceFilter.channelType = ''
  resourceFilter.region = ''
  resourceFilter.minPrice = ''
  resourceFilter.maxPrice = ''
  resetResources()
}

function resetWallets(): void {
  walletPage.value = 1
  void loadWallets()
}

function clearWalletFilters(): void {
  walletFilter.keyword = ''
  walletFilter.tenantId = ''
  resetWallets()
}

function onResourceTableChange(pagination: TablePaginationConfig): void {
  resourcePage.value = pagination.current ?? 1
  resourcePageSize.value = pagination.pageSize ?? PAGE_SIZE
  void loadResources()
}

function onWalletTableChange(pagination: TablePaginationConfig): void {
  walletPage.value = pagination.current ?? 1
  walletPageSize.value = pagination.pageSize ?? PAGE_SIZE
  void loadWallets()
}

async function queueSync(): Promise<void> {
  syncLoading.value = true
  try {
    await opsMediaSupplyApi.queueSync(MODEL_ID_AUTHORITY_NEWS)
    message.success('调度任务已提交')
  } catch (error) {
    showOpsError(error)
  } finally {
    syncLoading.value = false
  }
}

function openPriceModal(row: OpsMediaSupplyResource): void {
  priceTarget.value = row
  priceForm.yuan = centsToYuan(row.sell_price_cents)
  priceModalOpen.value = true
}

async function submitPrice(): Promise<void> {
  if (!priceTarget.value) return
  const cents = roundUpToYuanCents(yuanToCents(priceForm.yuan))
  if (cents <= 0) {
    message.warning('请输入有效售价')
    return
  }
  if (cents < priceTarget.value.cost_price_cents) {
    message.warning('售价不能低于成本价')
    return
  }
  priceSaving.value = true
  try {
    await opsMediaSupplyApi.setPrice(priceTarget.value.id, {
      price_type: 'price',
      sell_price_cents: cents,
      enabled: true,
    })
    message.success('售价已更新')
    priceModalOpen.value = false
    priceTarget.value = null
    await loadResources()
  } catch (error) {
    showOpsError(error)
  } finally {
    priceSaving.value = false
  }
}

async function updateVisibility(row: OpsMediaSupplyResource, checked: boolean): Promise<void> {
  visibilityLoadingId.value = row.id
  try {
    await opsMediaSupplyApi.setVisibility(row.id, checked)
    row.customer_visible = checked
    message.success(checked ? '已在客户后台显示' : '已从客户后台隐藏')
  } catch (error) {
    showOpsError(error)
  } finally {
    visibilityLoadingId.value = null
  }
}

function openWalletModal(row: WalletRow): void {
  walletTarget.value = row
  walletForm.yuan = ''
  walletForm.note = ''
  walletModalOpen.value = true
}

async function submitWalletAdjustment(): Promise<void> {
  if (!walletTarget.value) return
  const cents = yuanToCents(walletForm.yuan)
  if (cents === 0) {
    message.warning('请输入调整金额')
    return
  }
  if (walletTarget.value.balance_cents + cents < 0) {
    message.warning('扣减后余额不能为负')
    return
  }
  walletSaving.value = true
  try {
    await opsMediaSupplyApi.adjustWallet({
      tenant_id: walletTarget.value.tenant_id,
      user_id: walletTarget.value.user_id,
      delta_cents: cents,
      note: walletForm.note.trim() || undefined,
    })
    message.success('余额已调整')
    walletModalOpen.value = false
    walletTarget.value = null
    await loadWallets()
  } catch (error) {
    showOpsError(error)
  } finally {
    walletSaving.value = false
  }
}

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 centsToYuan(cents: number): string {
  return (cents / 100).toFixed(2)
}

function yuanToCents(value: string): number {
  const numeric = Number(value)
  if (!Number.isFinite(numeric)) return 0
  return Math.round(numeric * 100)
}

function roundUpToYuanCents(cents: number): number {
  return cents > 0 ? Math.ceil(cents / 100) * 100 : 0
}

function yuanToCentsOptional(value: string): number | undefined {
  const cents = yuanToCents(value)
  return cents > 0 ? cents : undefined
}

function parsePositiveNumber(value: string): number | undefined {
  const numeric = Number(value)
  return Number.isFinite(numeric) && numeric > 0 ? numeric : undefined
}

function displayValue(value?: string | null): string {
  return value?.trim() || '--'
}

function formatDate(value?: string | null): string {
  if (!value) return '--'
  return dayjs(value).isValid() ? dayjs(value).format('YYYY-MM-DD HH:mm') : '--'
}

function isValidUrl(value?: string | null): boolean {
  return /^https?:\/\//i.test(String(value ?? '').trim())
}

function statusLabel(status: string): string {
  if (status === 'normal' || status === 'enabled') return '可投'
  if (status === 'disabled') return '不可投'
  return status || '--'
}

function statusColor(status: string): string {
  if (status === 'normal' || status === 'enabled') return 'green'
  if (status === 'disabled') return 'default'
  return 'blue'
}
</script>

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

.media-ops-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.media-ops-header .ops-page-title {
  margin-bottom: 4px;
}

.media-ops-header__meta {
  color: #64748b;
  font-size: 13px;
}

.media-ops-tabs :deep(.ant-tabs-nav) {
  margin-bottom: 12px;
}

.media-ops-card {
  padding: 16px;
}

.media-ops-toolbar {
  gap: 10px;
  margin-bottom: 16px;
}

.resource-main {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.resource-main strong,
.resource-link,
.remark-cell {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.resource-link {
  color: #1677ff;
  font-weight: 700;
}

.resource-sub {
  display: flex;
  align-items: center;
  gap: 8px;
  color: #64748b;
  font-size: 12px;
}

.price-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}

.price-stack span,
.muted {
  color: #64748b;
  font-size: 12px;
}

.margin-ok {
  color: #15803d;
  font-weight: 700;
}

.margin-risk {
  color: #b91c1c;
  font-weight: 700;
}

.remark-cell {
  display: block;
  max-width: 300px;
}

.wallet-balance {
  color: #0f766e;
}

.edit-stack {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

@media (max-width: 900px) {
  .media-ops-header {
    align-items: flex-start;
    flex-direction: column;
  }
}
</style>
