import { ReloadOutlined } from '@ant-design/icons'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import {
  App,
  Alert,
  Button,
  Card,
  Descriptions,
  Form,
  Input,
  InputNumber,
  Modal,
  Select,
  Space,
  Switch,
  Table,
  Tag,
  Typography,
} from 'antd'
import type { TableColumnsType } from 'antd'
import { useEffect, useState } from 'react'
import { useSearchParams } from 'react-router'

import ImageUpload from '@/components/files/ImageUpload'
import ImagePreviewList from '@/components/files/ImagePreviewList'
import {
  fetchAdminWorkerFinanceConfig,
  fetchAdminWorkerFinanceRequests,
  reviewAdminWorkerFinanceRequest,
  saveAdminWorkerFinanceConfig,
} from '@/services/admin'
import type {
  UploadedFile,
  WorkerFinanceConfig,
  WorkerFinanceRequest,
} from '@/types/worker-platform'
import { AdminRangePicker } from '@/components/admin/AdminDatePicker'
import dayjs, { ADMIN_DATE_TIME_FORMAT } from '@/lib/dayjs'
import { ADMIN_DEFAULT_PAGE_SIZE, buildAdminTablePagination } from '@/utils/admin-pagination'
import { formatAdminDateTime } from '@/utils/admin-time'
import { getAdminRole } from '@/utils/admin-auth'
import { asRecord, formatMoney } from './shared'
type FinanceConfigFormValues = {
  depositUnfreezeDays?: number
  rewardUnfreezeEnabled?: boolean
  recharge?: {
    enabled?: boolean
    channelName?: string
    accountName?: string
    accountNo?: string
    qrCodeImageList?: UploadedFile[]
    instructions?: string
  }
  adminContact?: {
    wechatQrCodeImageList?: UploadedFile[]
  }
  withdraw?: {
    enabled?: boolean
    instructions?: string
  }
}

type FinanceReviewAction = 'approved' | 'rejected' | 'cancelled'

export default function FinancePanel() {
  const { message } = App.useApp()
  const canEditConfig = getAdminRole() !== 'finance'
  const queryClient = useQueryClient()
  const [searchParams, setSearchParams] = useSearchParams()
  const [configForm] = Form.useForm<FinanceConfigFormValues>()
  const [reviewForm] = Form.useForm<{ reviewedNote?: string }>()
  const [requestStatus, setRequestStatus] = useState('')
  const [targetRequestId, setTargetRequestId] = useState<number | undefined>()
  const [requestType, setRequestType] = useState('')
  const [keywordInput, setKeywordInput] = useState('')
  const [keyword, setKeyword] = useState('')
  const [createdRange, setCreatedRange] = useState<[string, string] | null>(null)
  const [accountChannel, setAccountChannel] = useState('')
  const [page, setPage] = useState(1)
  const [pageSize, setPageSize] = useState(ADMIN_DEFAULT_PAGE_SIZE)
  const [savingConfig, setSavingConfig] = useState(false)
  const [configExpanded, setConfigExpanded] = useState(false)
  const [reviewing, setReviewing] = useState(false)
  const [reviewState, setReviewState] = useState<{
    action: FinanceReviewAction
    request: WorkerFinanceRequest
  } | null>(null)

  const financeConfigQuery = useQuery({
    queryKey: ['admin-worker-platform-finance-config'],
    queryFn: () => fetchAdminWorkerFinanceConfig(),
  })
  useEffect(() => {
    const requestId = Number(searchParams.get('financeRequestId') || 0)
    if (!Number.isInteger(requestId) || requestId <= 0) return
    setTargetRequestId(requestId)
    setRequestStatus('')
    setRequestType('')
    setKeyword('')
    setKeywordInput('')
    setPage(1)
    setSearchParams(
      (current) => {
        current.delete('financeRequestId')
        return current
      },
      { replace: true },
    )
  }, [searchParams, setSearchParams])
  const financeRequestsQuery = useQuery({
    queryKey: [
      'admin-worker-platform-finance-requests',
      requestStatus,
      requestType,
      targetRequestId,
      keyword,
      page,
      pageSize,
      createdRange ? createdRange[0] : '',
      createdRange ? createdRange[1] : '',
      accountChannel,
    ],
    queryFn: () =>
      fetchAdminWorkerFinanceRequests({
        status: requestStatus,
        requestType,
        requestId: targetRequestId,
        keyword,
        page,
        pageSize,
        accountChannel,
        ...(createdRange ? { createdFrom: createdRange[0], createdTo: createdRange[1] } : {}),
      }),
  })
  const financeRequestsPagination = financeRequestsQuery.data?.data.pagination

  useEffect(() => {
    const config = financeConfigQuery.data?.data
    if (!config) {
      return
    }
    configForm.setFieldsValue(mapFinanceConfigToFormValues(config))
  }, [financeConfigQuery.data, configForm])

  async function refreshAll() {
    await Promise.all([
      queryClient.invalidateQueries({
        queryKey: ['admin-worker-platform-finance-config'],
      }),
      queryClient.invalidateQueries({
        queryKey: ['admin-worker-platform-finance-requests'],
      }),
      queryClient.invalidateQueries({
        queryKey: ['admin-worker-platform-workers'],
      }),
    ])
  }

  async function submitFinanceConfig(values: FinanceConfigFormValues) {
    setSavingConfig(true)
    try {
      await saveAdminWorkerFinanceConfig({
        depositUnfreezeDays: Number(values.depositUnfreezeDays ?? 3),
        rewardUnfreezeEnabled: values.rewardUnfreezeEnabled !== false,
        recharge: {
          enabled: values.recharge?.enabled !== false,
          channelName: String(values.recharge?.channelName || '').trim(),
          accountName: String(values.recharge?.accountName || '').trim(),
          accountNo: String(values.recharge?.accountNo || '').trim(),
          qrCodeImage: values.recharge?.qrCodeImageList?.[0] || null,
          instructions: String(values.recharge?.instructions || '').trim(),
        },
        adminContact: {
          wechatQrCodeImage: values.adminContact?.wechatQrCodeImageList?.[0] || null,
        },
        withdraw: {
          enabled: values.withdraw?.enabled !== false,
          instructions: String(values.withdraw?.instructions || '').trim(),
        },
      })
      message.success('资金配置已保存')
      await refreshAll()
    } catch (error) {
      message.error(error instanceof Error ? error.message : '保存资金配置失败')
    } finally {
      setSavingConfig(false)
    }
  }

  function openReviewModal(request: WorkerFinanceRequest, action: FinanceReviewAction) {
    setReviewState({ request, action })
    reviewForm.setFieldsValue({ reviewedNote: '' })
  }

  async function submitFinanceReview(values: { reviewedNote?: string }) {
    if (!reviewState) return
    setReviewing(true)
    try {
      await reviewAdminWorkerFinanceRequest(reviewState.request.requestId, {
        status: reviewState.action,
        reviewedNote: String(values.reviewedNote || '').trim(),
      })
      message.success(`${formatFinanceReviewAction(reviewState.action)}成功`)
      setReviewState(null)
      reviewForm.resetFields()
      await refreshAll()
    } catch (error) {
      message.error(error instanceof Error ? error.message : '处理资金申请失败')
    } finally {
      setReviewing(false)
    }
  }

  const requestColumns: TableColumnsType<WorkerFinanceRequest> = [
    {
      title: '打手',
      minWidth: 250,
      render: (_, row) => (
        <div className="cell-stack">
          <Typography.Text strong>
            {row.worker?.displayName || row.worker?.username || '-'}
          </Typography.Text>
          <Typography.Text type="secondary">{row.worker?.username || '-'}</Typography.Text>
          {row.worker ? (
            <Space size={[4, 4]} wrap>
              <Tag color={row.worker.workerType === 'internal' ? 'blue' : 'default'}>
                {row.worker.workerType === 'internal' ? '内部打手' : '外部打手'}
              </Tag>
              <Tag>{row.worker.levelName || row.worker.levelKey || '未分级'}</Tag>
              <Typography.Text type="secondary">
                提现 {row.worker.withdrawRequestCount} 次，累计
                {formatMoney(row.worker.totalWithdrawAmount)}
              </Typography.Text>
            </Space>
          ) : null}
        </div>
      ),
    },
    {
      title: '类型',
      width: 120,
      render: (_, row) => (
        <Tag color={row.requestType === 'withdraw' ? 'green' : 'blue'}>
          {formatFinanceRequestType(row.requestType)}
        </Tag>
      ),
    },
    {
      title: '金额',
      width: 120,
      render: (_, row) => formatMoney(row.amount),
    },
    {
      title: '收款信息',
      minWidth: 240,
      render: (_, row) => renderFinanceRequestAccount(row),
    },
    {
      title: '凭证/收款码',
      minWidth: 140,
      render: (_, row) => (
        <ImagePreviewList
          files={row.requestType === 'recharge' ? getRechargeProofs(row) : getWithdrawQrCode(row)}
          size={48}
        />
      ),
    },
    {
      title: '备注',
      minWidth: 260,
      render: (_, row) => (
        <div className="cell-stack">
          <Typography.Text>{row.note || '-'}</Typography.Text>
          {row.reviewedNote ? (
            <Typography.Text type="secondary">审核备注：{row.reviewedNote}</Typography.Text>
          ) : null}
        </div>
      ),
    },
    {
      title: '状态',
      width: 120,
      render: (_, row) => (
        <Tag color={resolveFinanceRequestStatusColor(row.status)}>
          {formatFinanceRequestStatus(row.status)}
        </Tag>
      ),
    },
    {
      title: '时间',
      width: 180,
      render: (_, row) => (
        <div className="cell-stack">
          <Typography.Text>{formatAdminDateTime(row.createdAt)}</Typography.Text>
          <Typography.Text type="secondary">
            {row.reviewedAt
              ? `审核：${formatAdminDateTime(row.reviewedAt)}${resolveFinanceReviewer(row) ? `（${resolveFinanceReviewer(row)}）` : ''}`
              : '待审核'}
          </Typography.Text>
        </div>
      ),
    },
    {
      title: '操作',
      width: 240,
      render: (_, row) =>
        row.status === 'pending' ? (
          <Space wrap>
            <Button type="primary" onClick={() => openReviewModal(row, 'approved')}>
              通过
            </Button>
            <Button onClick={() => openReviewModal(row, 'rejected')}>拒绝</Button>
            <Button danger onClick={() => openReviewModal(row, 'cancelled')}>
              取消
            </Button>
          </Space>
        ) : (
          <Typography.Text type="secondary">已处理</Typography.Text>
        ),
    },
  ]

  return (
    <section className="platform-panel-stack">
      {targetRequestId ? (
        <Alert
          type="info"
          showIcon
          message={`已定位资金申请 #${targetRequestId}`}
          action={
            <Button size="small" onClick={() => setTargetRequestId(undefined)}>
              取消定位
            </Button>
          }
        />
      ) : null}
      <Card
        title="资金配置"
        bordered={false}
        loading={financeConfigQuery.isLoading}
        extra={
          <Space>
            <Button type="link" onClick={() => setConfigExpanded((expanded) => !expanded)}>
              {configExpanded ? '收起配置' : '展开配置'}
            </Button>
            <Button
              icon={<ReloadOutlined />}
              loading={financeConfigQuery.isFetching}
              onClick={() => financeConfigQuery.refetch()}
            >
              刷新
            </Button>
          </Space>
        }
      >
        {configExpanded && financeConfigQuery.error ? (
          <Typography.Text type="danger">
            {financeConfigQuery.error instanceof Error
              ? financeConfigQuery.error.message
              : '读取资金配置失败'}
          </Typography.Text>
        ) : null}
        {configExpanded ? (
          <Form
            form={configForm}
            layout="vertical"
            onFinish={submitFinanceConfig}
            initialValues={mapFinanceConfigToFormValues()}
          >
            <Card title="充值入口" size="small" style={{ marginBottom: 16 }}>
              <Form.Item
                label="开启充值申请"
                name={['recharge', 'enabled']}
                valuePropName="checked"
              >
                <Switch />
              </Form.Item>
              <Form.Item label="收款通道名称" name={['recharge', 'channelName']}>
                <Input placeholder="如：支付宝扫码、微信收款" />
              </Form.Item>
              <Form.Item label="收款人" name={['recharge', 'accountName']}>
                <Input placeholder="请输入收款人姓名" />
              </Form.Item>
              <Form.Item label="收款账号" name={['recharge', 'accountNo']}>
                <Input placeholder="请输入支付宝账号、微信号或银行卡号" />
              </Form.Item>
              <Form.Item label="收款二维码" name={['recharge', 'qrCodeImageList']}>
                <ImageUpload scene="worker-finance" scope="admin" maxCount={1} />
              </Form.Item>
              <Form.Item label="充值说明" name={['recharge', 'instructions']}>
                <Input.TextArea
                  rows={4}
                  placeholder="例如：转账后请填写付款时间、付款尾号、截图说明。"
                />
              </Form.Item>
            </Card>

            <Card title="管理员联系" size="small" style={{ marginBottom: 16 }}>
              <Form.Item label="管理员微信二维码" name={['adminContact', 'wechatQrCodeImageList']}>
                <ImageUpload scene="worker-admin-contact" scope="admin" maxCount={1} />
              </Form.Item>
            </Card>

            <Card title="押金与提现规则" size="small" style={{ marginBottom: 16 }}>
              <Form.Item
                label="押金解冻天数"
                name="depositUnfreezeDays"
                tooltip="验收通过后，押金进入待解冻，N 天后自动转入可用余额；0 表示押金立即释放"
              >
                <InputNumber min={0} max={30} step={1} addonAfter="天" />
              </Form.Item>
              <Form.Item
                label="报酬待解冻"
                name="rewardUnfreezeEnabled"
                valuePropName="checked"
                tooltip="开启后，验收报酬和押金一起进入待解冻；期间可由售后问题单优先扣减"
              >
                <Switch />
              </Form.Item>
              <Typography.Text type="secondary">
                解冻期间如订单出现问题，可在"接单工单"或"售后问题单"中优先扣减本单待解冻金额。
              </Typography.Text>
            </Card>

            <Card title="提现入口" size="small" style={{ marginBottom: 16 }}>
              <Form.Item
                label="开启提现申请"
                name={['withdraw', 'enabled']}
                valuePropName="checked"
              >
                <Switch />
              </Form.Item>
              <Form.Item label="提现说明" name={['withdraw', 'instructions']}>
                <Input.TextArea
                  rows={4}
                  placeholder="例如：每天 18:00 前审核，当日打款；银行卡请备注开户行。"
                />
              </Form.Item>
            </Card>

            <Button
              type="primary"
              htmlType="submit"
              loading={savingConfig}
              disabled={!canEditConfig}
            >
              保存配置
            </Button>
          </Form>
        ) : null}
      </Card>

      <Card
        title="资金申请"
        bordered={false}
        extra={
          <Space wrap>
            <Input.Search
              allowClear
              value={keywordInput}
              placeholder="搜索打手账号/昵称/手机号"
              style={{ width: 240 }}
              onChange={(event) => setKeywordInput(event.target.value)}
              onSearch={(value) => {
                setKeyword(String(value || '').trim())
                setPage(1)
              }}
            />
            <Select
              value={requestType}
              style={{ width: 140 }}
              options={[
                { value: '', label: '全部类型' },
                { value: 'recharge', label: '充值申请' },
                { value: 'withdraw', label: '提现申请' },
              ]}
              onChange={(nextType) => {
                setRequestType(nextType)
                setPage(1)
              }}
            />
            <Select
              value={requestStatus}
              style={{ width: 140 }}
              options={[
                { value: '', label: '全部状态' },
                { value: 'pending', label: '待处理' },
                { value: 'approved', label: '已通过' },
                { value: 'rejected', label: '已拒绝' },
                { value: 'cancelled', label: '已取消' },
              ]}
              onChange={(nextStatus) => {
                setRequestStatus(nextStatus)
                setPage(1)
              }}
            />
            <Select
              value={accountChannel}
              style={{ width: 130 }}
              options={[
                { value: '', label: '全部渠道' },
                { value: 'alipay', label: '支付宝' },
                { value: 'wechat', label: '微信' },
              ]}
              onChange={(nextChannel) => {
                setAccountChannel(nextChannel)
                setPage(1)
              }}
            />
            <AdminRangePicker
              format="YYYY-MM-DD HH:mm"
              showTime={{
                format: 'HH:mm',
                defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('23:59:59', 'HH:mm:ss')],
              }}
              value={createdRange ? [dayjs(createdRange[0]), dayjs(createdRange[1])] : null}
              onChange={(dates) => {
                const [start, end] = dates || []
                setCreatedRange(
                  start && end
                    ? [
                        // 起止各占满整分钟：开始 xx:00、结束 xx:59
                        start.second(0).format(ADMIN_DATE_TIME_FORMAT),
                        end.second(59).format(ADMIN_DATE_TIME_FORMAT),
                      ]
                    : null,
                )
                setPage(1)
              }}
            />
            <Button
              icon={<ReloadOutlined />}
              loading={financeRequestsQuery.isFetching}
              onClick={() => financeRequestsQuery.refetch()}
            >
              刷新
            </Button>
          </Space>
        }
      >
        <FinanceSummaryBar
          channels={financeRequestsQuery.data?.data.summary?.channels}
          totalCount={financeRequestsQuery.data?.data.summary?.totalCount}
          totalAmount={financeRequestsQuery.data?.data.summary?.totalAmount}
        />
        <Table<WorkerFinanceRequest>
          rowKey="requestId"
          loading={financeRequestsQuery.isLoading}
          dataSource={financeRequestsQuery.data?.data.items || []}
          columns={requestColumns}
          pagination={buildAdminTablePagination({
            current: financeRequestsPagination?.page || page,
            pageSize: financeRequestsPagination?.pageSize || pageSize,
            total: financeRequestsPagination?.total || 0,
            onChange: (nextPage, nextPageSize) => {
              setPage(nextPage)
              setPageSize(nextPageSize)
            },
          })}
          scroll={{ x: 1380 }}
        />
      </Card>

      <Modal
        title={
          reviewState ? `${formatFinanceReviewAction(reviewState.action)}资金申请` : '处理资金申请'
        }
        open={Boolean(reviewState)}
        destroyOnHidden
        width="min(860px, calc(100vw - 32px))"
        confirmLoading={reviewing}
        onCancel={() => {
          setReviewState(null)
          reviewForm.resetFields()
        }}
        onOk={() => reviewForm.submit()}
      >
        {reviewState ? (
          <Space direction="vertical" size={16} className="full-width">
            <div className="finance-review-layout">
              <div className="finance-review-details">
                <Typography.Text strong>
                  {reviewState.request.requestType === 'withdraw' ? '提现信息' : '充值信息'}
                </Typography.Text>
                <Descriptions column={1} bordered size="small">
                  <Descriptions.Item label="打手">
                    {reviewState.request.worker?.displayName ||
                      reviewState.request.worker?.username ||
                      '-'}
                  </Descriptions.Item>
                  <Descriptions.Item label="申请类型">
                    {formatFinanceRequestType(reviewState.request.requestType)}
                  </Descriptions.Item>
                  <Descriptions.Item label="金额">
                    {formatMoney(reviewState.request.amount)}
                  </Descriptions.Item>
                  <Descriptions.Item label="收款信息">
                    {renderFinanceRequestAccountText(reviewState.request)}
                  </Descriptions.Item>
                  {reviewState.request.requestType === 'withdraw' ? (
                    <Descriptions.Item label="收款账号">
                      {reviewState.request.accountNo ? (
                        <Typography.Text copyable>{reviewState.request.accountNo}</Typography.Text>
                      ) : (
                        '-'
                      )}
                    </Descriptions.Item>
                  ) : null}
                  {reviewState.request.requestType === 'recharge' ? (
                    <Descriptions.Item label="付款时间">
                      {getRechargePaidAt(reviewState.request)
                        ? formatAdminDateTime(getRechargePaidAt(reviewState.request))
                        : '-'}
                    </Descriptions.Item>
                  ) : null}
                  <Descriptions.Item label="申请备注">
                    {reviewState.request.note || '-'}
                  </Descriptions.Item>
                </Descriptions>
              </div>
              <div className="finance-review-evidence">
                <Typography.Text strong>
                  {reviewState.request.requestType === 'withdraw'
                    ? `${formatFinanceChannel(reviewState.request.accountChannel)}收款二维码`
                    : '付款凭证'}
                </Typography.Text>
                <ImagePreviewList
                  files={
                    reviewState.request.requestType === 'withdraw'
                      ? getWithdrawQrCode(reviewState.request)
                      : getRechargeProofs(reviewState.request)
                  }
                  size={280}
                />
              </div>
            </div>

            <Form form={reviewForm} layout="vertical" onFinish={submitFinanceReview}>
              <Form.Item label="审核备注" name="reviewedNote">
                <Input.TextArea
                  rows={4}
                  placeholder={`请输入${formatFinanceReviewAction(reviewState.action)}备注`}
                />
              </Form.Item>
            </Form>
          </Space>
        ) : null}
      </Modal>
    </section>
  )
}

function mapFinanceConfigToFormValues(config?: WorkerFinanceConfig): FinanceConfigFormValues {
  return {
    depositUnfreezeDays: Number(config?.depositUnfreezeDays ?? 3),
    rewardUnfreezeEnabled: config?.rewardUnfreezeEnabled !== false,
    recharge: {
      enabled: config?.recharge.enabled !== false,
      channelName: config?.recharge.channelName || '',
      accountName: config?.recharge.accountName || '',
      accountNo: config?.recharge.accountNo || '',
      qrCodeImageList: config?.recharge.qrCodeImage ? [config.recharge.qrCodeImage] : [],
      instructions: config?.recharge.instructions || '',
    },
    adminContact: {
      wechatQrCodeImageList: config?.adminContact.wechatQrCodeImage
        ? [config.adminContact.wechatQrCodeImage]
        : [],
    },
    withdraw: {
      enabled: config?.withdraw.enabled !== false,
      instructions: config?.withdraw.instructions || '',
    },
  }
}

function formatFinanceReviewAction(action: FinanceReviewAction) {
  if (action === 'approved') return '通过'
  if (action === 'rejected') return '拒绝'
  return '取消'
}

function formatFinanceRequestType(requestType: string) {
  if (requestType === 'recharge') return '充值申请'
  if (requestType === 'withdraw') return '提现申请'
  return requestType || '-'
}

function formatFinanceRequestStatus(status: string) {
  const labels: Record<string, string> = {
    pending: '待处理',
    approved: '已通过',
    rejected: '已拒绝',
    cancelled: '已取消',
  }
  return labels[status] || status || '-'
}

function resolveFinanceRequestStatusColor(status: string) {
  if (status === 'approved') return 'green'
  if (status === 'pending') return 'gold'
  if (status === 'rejected') return 'red'
  if (status === 'cancelled') return 'default'
  return 'blue'
}

function renderFinanceRequestAccount(request: WorkerFinanceRequest) {
  return (
    <div className="cell-stack">
      <Typography.Text>{renderFinanceRequestAccountText(request)}</Typography.Text>
      {request.requestType === 'withdraw' && request.accountNo ? (
        <Typography.Text copyable>{request.accountNo}</Typography.Text>
      ) : null}
    </div>
  )
}

function renderFinanceRequestAccountText(request: WorkerFinanceRequest) {
  if (request.requestType === 'withdraw') {
    const channel = formatFinanceChannel(request.accountChannel)
    const accountName = request.accountName || '-'
    return `${channel} / ${accountName}`
  }

  const rechargeSnapshot = getRechargeSnapshot(request)
  if (rechargeSnapshot.channelName || rechargeSnapshot.accountName || rechargeSnapshot.accountNo) {
    return [
      rechargeSnapshot.channelName,
      rechargeSnapshot.accountName,
      rechargeSnapshot.accountNo ? maskFinanceAccount(rechargeSnapshot.accountNo) : '',
    ]
      .filter(Boolean)
      .join(' / ')
  }

  return '线下充值，等待管理员核对'
}

function getRechargeSnapshot(request: WorkerFinanceRequest) {
  const payload = asRecord(request.payload)
  const financeConfig = asRecord(payload.financeConfig)
  return {
    channelName: String(financeConfig.channelName || '').trim(),
    accountName: String(financeConfig.accountName || '').trim(),
    accountNo: String(financeConfig.accountNo || '').trim(),
  }
}

function getRechargeProofs(request: WorkerFinanceRequest): UploadedFile[] {
  if (request.requestType !== 'recharge') return []
  const payload = asRecord(request.payload)
  const rawFiles = Array.isArray(payload.proofFiles) ? payload.proofFiles : []
  return rawFiles
    .map((item) => {
      const file = asRecord(item)
      const url = String(file.url || '').trim()
      if (!url) return null
      return {
        url,
        mediumUrl: String(file.mediumUrl || '').trim(),
        thumbnailUrl: String(file.thumbnailUrl || '').trim(),
      } as UploadedFile
    })
    .filter((item): item is UploadedFile => Boolean(item))
}

function getWechatWithdrawQrCode(request: WorkerFinanceRequest): UploadedFile[] {
  if (request.requestType !== 'withdraw' || request.accountChannel !== 'wechat') return []
  const payload = asRecord(request.payload)
  const file = asRecord(payload.wechatQrCodeImage)
  const url = String(file.url || '').trim()
  if (!url) return []
  return [
    {
      url,
      mediumUrl: String(file.mediumUrl || '').trim(),
      thumbnailUrl: String(file.thumbnailUrl || '').trim(),
      objectKey: String(file.objectKey || '').trim(),
      filename: String(file.filename || '').trim(),
      contentType: String(file.contentType || '').trim(),
      size: Number(file.size || 0),
    },
  ]
}

function getWithdrawQrCode(request: WorkerFinanceRequest): UploadedFile[] {
  if (request.accountChannel === 'alipay') return getAlipayWithdrawQrCode(request)
  return getWechatWithdrawQrCode(request)
}

function getAlipayWithdrawQrCode(request: WorkerFinanceRequest): UploadedFile[] {
  if (request.requestType !== 'withdraw' || request.accountChannel !== 'alipay') return []
  const payload = asRecord(request.payload)
  const file = asRecord(payload.alipayQrCodeImage)
  const url = String(file.url || '').trim()
  if (!url) return []
  return [
    {
      url,
      mediumUrl: String(file.mediumUrl || '').trim(),
      thumbnailUrl: String(file.thumbnailUrl || '').trim(),
      objectKey: String(file.objectKey || '').trim(),
      filename: String(file.filename || '').trim(),
      contentType: String(file.contentType || '').trim(),
      size: Number(file.size || 0),
    },
  ]
}

function getRechargePaidAt(request: WorkerFinanceRequest): string {
  const payload = asRecord(request.payload)
  return String(payload.paidAt || '').trim()
}

function formatFinanceChannel(channel: string) {
  if (channel === 'alipay') return '支付宝'
  if (channel === 'wechat') return '微信收款'
  if (channel === 'bank') return '银行卡'
  if (channel === 'manual') return '线下转账'
  return channel || '-'
}

function maskFinanceAccount(value: string) {
  const text = String(value || '').trim()
  if (!text) return '-'
  if (text.length <= 8) return text
  return `${text.slice(0, 4)} **** ${text.slice(-4)}`
}

type FinanceSummaryChannel = { channel: string; count: number; amount: number }

/** 当前筛选条件下的渠道合计条：支付宝 / 微信 / 其他分列展示笔数与金额。 */
function FinanceSummaryBar({
  channels,
  totalCount,
  totalAmount,
}: {
  channels?: FinanceSummaryChannel[]
  totalCount?: number
  totalAmount?: number
}) {
  const items = channels || []
  const alipay = items.find((item) => item.channel === 'alipay')
  const wechat = items.find((item) => item.channel === 'wechat')
  const others = items.filter((item) => item.channel !== 'alipay' && item.channel !== 'wechat')
  const otherCount = others.reduce((sum, item) => sum + item.count, 0)
  const otherAmount = others.reduce((sum, item) => sum + item.amount, 0)

  return (
    <Space size={24} wrap style={{ marginBottom: 12 }}>
      <span className="finance-summary-item">
        支付宝 <strong>{alipay ? alipay.count : 0}</strong> 笔 /{' '}
        <strong>{formatMoney(alipay ? alipay.amount : 0)}</strong>
      </span>
      <span className="finance-summary-item">
        微信 <strong>{wechat ? wechat.count : 0}</strong> 笔 /{' '}
        <strong>{formatMoney(wechat ? wechat.amount : 0)}</strong>
      </span>
      <span className="finance-summary-item">
        其他 <strong>{otherCount}</strong> 笔 / <strong>{formatMoney(otherAmount)}</strong>
      </span>
      <span className="finance-summary-item">
        合计 <strong>{totalCount || 0}</strong> 笔 /{' '}
        <strong>{formatMoney(totalAmount || 0)}</strong>
      </span>
      <Typography.Text type="secondary">按当前筛选条件（含时间区间）统计</Typography.Text>
    </Space>
  )
}

function resolveFinanceReviewer(request: WorkerFinanceRequest): string {
  const review = asRecord(asRecord(request.payload).review)
  return String(review.by || '').trim()
}
