<script setup lang="ts">
import { ArrowDownLeft, ArrowUpRight, CreditCard, DollarSign, Inbox, Loader2, Trash2, TrendingUp } from 'lucide-vue-next'
import type {
  ColumnDef,
  ColumnFiltersState,
  SortingState,
  VisibilityState,
} from '@tanstack/vue-table'

import {
  FlexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useVueTable,
} from '@tanstack/vue-table'
import { computed, h, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { toast } from 'vue-sonner'

import ConfirmDialog from '@/components/confirm-dialog.vue'
import DataTablePagination from '@/components/data-table/table-pagination.vue'
import { BasicPage } from '@/components/global-layout'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Checkbox } from '@/components/ui/checkbox'
import DateTimePicker from '@/components/ui/date-picker/DateTimePicker.vue'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { valueUpdater } from '@/lib/utils'
import api from '@/services/api'

interface Application {
  id: number
  name: string
}

interface FinanceRecord {
  id: number
  order_no: string
  type: 'recharge' | 'consumption'
  user_id: number
  app_id?: number
  amount: number
  detail: string
  status: string
  payment_type: string
  remark: string
  created_at: string
  user?: {
    id: number
    username: string
    email: string
  }
}

const { t } = useI18n()
const loading = ref(true)
const records = ref<FinanceRecord[]>([])
const applications = ref<Application[]>([])

const appFilter = ref<string>('all')
const statusFilter = ref<string>('all')
const dateRange = ref<{ from: string, to: string }>({ from: '', to: '' })

function setQuickRange(range: 'today' | 'week' | 'month') {
  const now = new Date()
  const today = now.toISOString().split('T')[0]
  const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1).toISOString().split('T')[0]

  switch (range) {
    case 'today':
      dateRange.value = { from: `${today}T00:00`, to: `${today}T23:59` }
      break
    case 'week': {
      const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
      dateRange.value = {
        from: `${weekAgo.toISOString().split('T')[0]}T00:00`,
        to: `${today}T23:59`,
      }
      break
    }
    case 'month':
      dateRange.value = { from: `${firstDayOfMonth}T00:00`, to: `${today}T23:59` }
      break
  }
}

const filteredRecords = computed(() => {
  let result = records.value

  if (appFilter.value !== 'all') {
    result = result.filter(r => r.app_id === Number(appFilter.value))
  }

  if (statusFilter.value !== 'all') {
    result = result.filter(r => r.status === statusFilter.value)
  }

  if (dateRange.value.from) {
    const fromDateTime = dateRange.value.from.includes('T')
      ? dateRange.value.from.replace('T', ' ')
      : `${dateRange.value.from} 00:00`
    result = result.filter(r => r.created_at >= fromDateTime)
  }
  if (dateRange.value.to) {
    const toDateTime = dateRange.value.to.includes('T')
      ? dateRange.value.to.replace('T', ' ')
      : `${dateRange.value.to} 23:59`
    result = result.filter(r => r.created_at <= toDateTime)
  }

  return result
})

const stats = computed(() => {
  const rechargeRecords = filteredRecords.value.filter(r => r.type === 'recharge' && r.status === 'success')
  const consumptionRecords = filteredRecords.value.filter(r => r.type === 'consumption' && r.status === 'success')

  const totalRecharge = rechargeRecords.reduce((sum, r) => sum + r.amount, 0)
  const totalConsumption = consumptionRecords.reduce((sum, r) => sum + r.amount, 0)

  return {
    rechargeCount: rechargeRecords.length,
    rechargeAmount: totalRecharge,
    consumptionCount: consumptionRecords.length,
    consumptionAmount: totalConsumption,
    profit: totalRecharge - totalConsumption,
  }
})

function formatTime(time: string) {
  if (!time)
    return '-'
  try {
    const date = new Date(time)
    return date.toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
    })
  }
  catch {
    return '-'
  }
}

const sorting = ref<SortingState>([])
const columnFilters = ref<ColumnFiltersState>([])
const columnVisibility = ref<VisibilityState>({})
const rowSelection = ref({})

const deleteDialogOpen = ref(false)
const deleteTarget = ref<FinanceRecord | null>(null)
const batchDeleteDialogOpen = ref(false)

async function confirmDelete(record: FinanceRecord) {
  deleteTarget.value = record
  deleteDialogOpen.value = true
}

async function handleDelete() {
  if (!deleteTarget.value)
    return

  try {
    await api.delete(`/dev/finance/records/${deleteTarget.value.id}?type=${deleteTarget.value.type}`)
    toast.success(t('admin.finance.deleteSuccess'))
    fetchRecords()
  }
  catch (error: any) {
    toast.error(error.message || t('admin.finance.deleteFailed'))
  }
  finally {
    deleteTarget.value = null
  }
}

const columns: ColumnDef<FinanceRecord>[] = [
  {
    id: 'select',
    header: ({ table }) => h(Checkbox, {
      'checked': table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'),
      'onUpdate:checked': (value: boolean | 'indeterminate') => table.toggleAllPageRowsSelected(!!value),
      'ariaLabel': 'Select all',
    }),
    cell: ({ row }) => h(Checkbox, {
      'checked': row.getIsSelected(),
      'onUpdate:checked': (value: boolean | 'indeterminate') => row.toggleSelected(!!value),
      'ariaLabel': 'Select row',
    }),
    enableSorting: false,
    enableHiding: false,
  },
  {
    accessorKey: 'type',
    header: () => t('admin.finance.columns.type'),
    cell: ({ row }) => {
      const type = row.getValue('type') as string
      return h(Badge, { variant: type === 'recharge' ? 'default' : 'secondary' }, () => type === 'recharge' ? t('admin.finance.types.recharge') : t('admin.finance.types.consumption'))
    },
  },
  {
    accessorKey: 'amount',
    header: () => t('admin.finance.columns.amount'),
    cell: ({ row }) => {
      const type = row.getValue('type') as string
      const amount = row.getValue('amount') as number
      const prefix = type === 'recharge' ? '+' : '-'
      return h('span', { class: 'font-medium' }, `${prefix}¥${amount.toFixed(2)}`)
    },
  },
  {
    accessorKey: 'user',
    header: () => t('admin.finance.columns.user'),
    cell: ({ row }) => {
      const user = row.original.user
      return user?.username || '-'
    },
  },
  {
    accessorKey: 'detail',
    header: () => t('admin.finance.columns.detail'),
    cell: ({ row }) => {
      const detail = row.getValue('detail') as string
      return h('span', { class: 'max-w-[200px] truncate text-muted-foreground block' }, detail || '-')
    },
  },
  {
    accessorKey: 'status',
    header: () => t('admin.finance.columns.status'),
    cell: ({ row }) => {
      const status = row.getValue('status') as string
      const map: Record<string, { label: string, variant: 'default' | 'secondary' | 'destructive' }> = {
        success: { label: t('admin.finance.success'), variant: 'default' },
        pending: { label: t('admin.finance.pending'), variant: 'secondary' },
        failed: { label: t('admin.finance.failed'), variant: 'destructive' },
      }
      const { label, variant } = map[status] || { label: status, variant: 'secondary' }
      return h(Badge, { variant }, () => label)
    },
  },
  {
    accessorKey: 'created_at',
    header: () => t('admin.finance.columns.time'),
    cell: ({ row }) => {
      return h('span', { class: 'text-muted-foreground whitespace-nowrap' }, formatTime(row.getValue('created_at')))
    },
  },
  {
    id: 'actions',
    header: () => t('admin.finance.columns.actions'),
    cell: ({ row }) => {
      return h(Button, {
        variant: 'ghost',
        size: 'sm',
        class: 'h-8 w-8 p-0',
        onClick: () => confirmDelete(row.original),
      }, () => h(Trash2, { class: 'size-4 text-muted-foreground hover:text-destructive' }))
    },
  },
]

const table = useVueTable({
  get data() { return filteredRecords.value },
  get columns() { return columns },
  state: {
    get sorting() { return sorting.value },
    get columnFilters() { return columnFilters.value },
    get columnVisibility() { return columnVisibility.value },
    get rowSelection() { return rowSelection.value },
  },
  enableRowSelection: true,
  onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
  onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
  onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
  onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
  getPaginationRowModel: getPaginationRowModel(),
  getSortedRowModel: getSortedRowModel(),
})

async function confirmBatchDelete() {
  const selectedRows = table.getSelectedRowModel().rows
  if (selectedRows.length === 0) {
    toast.error(t('admin.finance.delete'))
    return
  }
  batchDeleteDialogOpen.value = true
}

async function handleBatchDelete() {
  const selectedRows = table.getSelectedRowModel().rows
  const ids = selectedRows.map(row => row.original.id)
  try {
    await api.post('/dev/finance/records/batch-delete', { ids })
    toast.success(t('admin.finance.deleteSuccess'))
    fetchRecords()
  }
  catch (error: any) {
    toast.error(error.message || t('admin.finance.deleteFailed'))
  }
}

async function fetchApplications() {
  try {
    const data = await api.get<{ applications: Application[] }>('/dev/applications')
    applications.value = data?.applications || []
  }
  catch (error) {
    console.error('获取应用列表失败:', error)
  }
}

async function fetchRecords() {
  loading.value = true
  try {
    const data = await api.get<{ records: FinanceRecord[] }>('/dev/finance/records')
    records.value = data?.records || []
  }
  catch (error) {
    console.error('获取财务记录失败:', error)
  }
  finally {
    loading.value = false
  }
}

onMounted(() => {
  fetchApplications()
  fetchRecords()
})
</script>

<template>
  <BasicPage
    :title="t('admin.finance.title')"
    :description="t('admin.finance.description')"
    sticky
  >
    <div class="space-y-6">
      <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-5">
        <UiCard>
          <UiCardHeader class="flex flex-row items-center justify-between pb-2 space-y-0">
            <UiCardTitle class="text-sm font-medium">
              {{ t('admin.finance.rechargeCount') }}
            </UiCardTitle>
            <ArrowDownLeft class="size-4 text-muted-foreground" />
          </UiCardHeader>
          <UiCardContent>
            <div class="text-2xl font-bold">
              {{ stats.rechargeCount }}
            </div>
          </UiCardContent>
        </UiCard>

        <UiCard>
          <UiCardHeader class="flex flex-row items-center justify-between pb-2 space-y-0">
            <UiCardTitle class="text-sm font-medium">
              {{ t('admin.finance.rechargeAmount') }}
            </UiCardTitle>
            <DollarSign class="size-4 text-muted-foreground" />
          </UiCardHeader>
          <UiCardContent>
            <div class="text-2xl font-bold">
              ¥{{ stats.rechargeAmount.toFixed(2) }}
            </div>
          </UiCardContent>
        </UiCard>

        <UiCard>
          <UiCardHeader class="flex flex-row items-center justify-between pb-2 space-y-0">
            <UiCardTitle class="text-sm font-medium">
              {{ t('admin.finance.consumptionCount') }}
            </UiCardTitle>
            <ArrowUpRight class="size-4 text-muted-foreground" />
          </UiCardHeader>
          <UiCardContent>
            <div class="text-2xl font-bold">
              {{ stats.consumptionCount }}
            </div>
          </UiCardContent>
        </UiCard>

        <UiCard>
          <UiCardHeader class="flex flex-row items-center justify-between pb-2 space-y-0">
            <UiCardTitle class="text-sm font-medium">
              {{ t('admin.finance.consumptionAmount') }}
            </UiCardTitle>
            <CreditCard class="size-4 text-muted-foreground" />
          </UiCardHeader>
          <UiCardContent>
            <div class="text-2xl font-bold">
              ¥{{ stats.consumptionAmount.toFixed(2) }}
            </div>
          </UiCardContent>
        </UiCard>

        <UiCard>
          <UiCardHeader class="flex flex-row items-center justify-between pb-2 space-y-0">
            <UiCardTitle class="text-sm font-medium">
              {{ t('admin.finance.profit') }}
            </UiCardTitle>
            <TrendingUp class="size-4 text-muted-foreground" />
          </UiCardHeader>
          <UiCardContent>
            <div class="text-2xl font-bold">
              ¥{{ stats.profit.toFixed(2) }}
            </div>
          </UiCardContent>
        </UiCard>
      </div>

      <UiCard>
        <UiCardHeader>
          <UiCardTitle>{{ t('admin.finance.transactionRecords') }}</UiCardTitle>
          <UiCardDescription>
            {{ t('admin.finance.transactionRecordsDesc') }}
          </UiCardDescription>
        </UiCardHeader>
        <UiCardContent>
          <div class="space-y-3 mb-4">
            <div class="flex items-center justify-end">
              <UiButton
                v-if="table.getSelectedRowModel().rows.length > 0"
                variant="destructive"
                size="sm"
                @click="confirmBatchDelete"
              >
                <Trash2 class="mr-2 size-4" />
                {{ t('admin.finance.batchDeleteBtn') }}
              </UiButton>
            </div>
            <div class="flex flex-wrap items-center justify-between gap-2">
              <div class="flex flex-wrap items-center gap-2">
                <UiSelect v-model="appFilter" class="w-[140px]">
                  <UiSelectTrigger>
                    <UiSelectValue :placeholder="t('admin.finance.allApplications')" />
                  </UiSelectTrigger>
                  <UiSelectContent>
                    <UiSelectItem value="all">
                      {{ t('admin.finance.allApplications') }}
                    </UiSelectItem>
                    <UiSelectItem v-for="app in applications" :key="app.id" :value="String(app.id)">
                      {{ app.name }}
                    </UiSelectItem>
                  </UiSelectContent>
                </UiSelect>

                <UiSelect v-model="statusFilter" class="w-[120px]">
                  <UiSelectTrigger>
                    <UiSelectValue :placeholder="t('admin.finance.allStatus')" />
                  </UiSelectTrigger>
                  <UiSelectContent>
                    <UiSelectItem value="all">
                      {{ t('admin.finance.allStatus') }}
                    </UiSelectItem>
                    <UiSelectItem value="success">
                      {{ t('admin.finance.success') }}
                    </UiSelectItem>
                    <UiSelectItem value="pending">
                      {{ t('admin.finance.pending') }}
                    </UiSelectItem>
                    <UiSelectItem value="failed">
                      {{ t('admin.finance.failed') }}
                    </UiSelectItem>
                  </UiSelectContent>
                </UiSelect>

                <DateTimePicker
                  v-model="dateRange.from"
                  :placeholder="t('admin.finance.startTime')"
                  class="w-[180px]"
                />
                <span class="text-muted-foreground">{{ t('admin.finance.to') }}</span>
                <DateTimePicker
                  v-model="dateRange.to"
                  :placeholder="t('admin.finance.endTime')"
                  class="w-[180px]"
                />
                <UiButton variant="ghost" size="sm" @click="setQuickRange('today')">
                  {{ t('admin.finance.today') }}
                </UiButton>
                <UiButton variant="ghost" size="sm" @click="setQuickRange('week')">
                  {{ t('admin.finance.last7Days') }}
                </UiButton>
                <UiButton variant="ghost" size="sm" @click="setQuickRange('month')">
                  {{ t('admin.finance.thisMonth') }}
                </UiButton>
              </div>
            </div>
          </div>

          <div v-if="loading" class="flex items-center justify-center py-12">
            <Loader2 class="size-8 animate-spin text-muted-foreground" />
          </div>

          <div v-else class="border rounded-md">
            <Table>
              <TableHeader>
                <TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
                  <TableHead v-for="header in headerGroup.headers" :key="header.id">
                    <FlexRender v-if="!header.isPlaceholder" :render="header.column.columnDef.header" :props="header.getContext()" />
                  </TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                <template v-if="table.getRowModel().rows?.length">
                  <TableRow
                    v-for="row in table.getRowModel().rows"
                    :key="row.id"
                    :data-state="row.getIsSelected() && 'selected'"
                  >
                    <TableCell v-for="cell in row.getVisibleCells()" :key="cell.id">
                      <FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
                    </TableCell>
                  </TableRow>
                </template>

                <TableRow v-else>
                  <TableCell
                    :colspan="columns.length"
                    class="h-24 text-center"
                  >
                    <div class="flex flex-col items-center justify-center text-muted-foreground">
                      <Inbox class="size-12 mb-2 opacity-50" />
                      <span>{{ t('admin.finance.noRecords') }}</span>
                    </div>
                  </TableCell>
                </TableRow>
              </TableBody>
            </Table>
          </div>

          <DataTablePagination v-if="!loading && table.getRowModel().rows?.length" :table="table" class="mt-4" />
        </UiCardContent>
      </UiCard>
    </div>
  </BasicPage>

  <ConfirmDialog
    v-model:open="deleteDialogOpen"
    destructive
    :confirm-button-text="t('admin.finance.delete')"
    :cancel-button-text="t('admin.finance.cancel')"
    @confirm="handleDelete"
  >
    <template #title>
      {{ t('admin.finance.delete') }}
    </template>
    <template #description>
      {{ t('admin.finance.deleteConfirm') }}
    </template>
  </ConfirmDialog>

  <ConfirmDialog
    v-model:open="batchDeleteDialogOpen"
    destructive
    :confirm-button-text="t('admin.finance.delete')"
    :cancel-button-text="t('admin.finance.cancel')"
    @confirm="handleBatchDelete"
  >
    <template #title>
      {{ t('admin.finance.batchDeleteBtn') }}
    </template>
    <template #description>
      {{ t('admin.finance.batchDeleteConfirm', { count: table.getSelectedRowModel().rows.length }) }}
    </template>
  </ConfirmDialog>
</template>
