import { ReloadOutlined, SearchOutlined } from '@ant-design/icons'
import { Alert, Button, Card, Empty, Form, Input, Select, Space, Table, Typography } from 'antd'
import type { TableColumnsType } from 'antd'
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import { useSearchParams } from 'react-router'

import { AdminRangePicker } from '@/components/admin/AdminDatePicker'
import PageHeader from '@/components/admin/PageHeader'
import StatusTag from '@/components/admin/StatusTag'
import dayjs from '@/lib/dayjs'
import { fetchAdminAuditLogs } from '@/services/admin'
import type { AdminAuditLogItem } from '@/types/admin'
import { hasAdminRole } from '@/utils/admin-auth'
import { formatAuditAction, formatAuditTargetType } from '@/utils/admin-display'
import { adminAuditActionOptions, adminAuditTargetTypeOptions } from '@/utils/admin-options'
import {
  ADMIN_DEFAULT_PAGE_SIZE,
  buildAdminTablePagination,
  resolveAdminPageSize,
} from '@/utils/admin-pagination'
import { formatAdminDateTime } from '@/utils/admin-time'
import { stringifyDisplayJson } from '@/utils/date-time'

type AuditFilterForm = {
  actorUsername?: string
  action?: string
  targetType?: string
  dateRange?: unknown
}

export default function AdminAuditLogsPage() {
  const isAdmin = hasAdminRole('admin')
  const [searchParams, setSearchParams] = useSearchParams()
  const page = Number(searchParams.get('page') || 1) || 1
  const pageSize = resolveAdminPageSize(searchParams.get('pageSize'), ADMIN_DEFAULT_PAGE_SIZE)
  const filters = {
    actorUsername: searchParams.get('actorUsername') || '',
    action: searchParams.get('action') || '',
    targetType: searchParams.get('targetType') || '',
    dateFrom: searchParams.get('dateFrom') || '',
    dateTo: searchParams.get('dateTo') || '',
  }
  const queryParams = useMemo(
    () => ({ page, pageSize, ...filters }),
    [
      filters.action,
      filters.actorUsername,
      filters.dateFrom,
      filters.dateTo,
      filters.targetType,
      page,
      pageSize,
    ],
  )
  const query = useQuery({
    queryKey: ['admin-audit-logs', queryParams],
    enabled: isAdmin,
    queryFn: () => fetchAdminAuditLogs(queryParams),
  })
  const data = query.data?.data

  const columns: TableColumnsType<AdminAuditLogItem> = [
    {
      title: '时间',
      dataIndex: 'createdAt',
      width: 180,
      render: (value) => formatAdminDateTime(value),
    },
    {
      title: '操作人',
      minWidth: 140,
      render: (_, row) => (
        <div className="cell-stack">
          <Typography.Text strong>{row.actorUsername || '-'}</Typography.Text>
          <StatusTag value={row.actorRole} />
        </div>
      ),
    },
    {
      title: '动作',
      dataIndex: 'action',
      minWidth: 180,
      render: (value) => <Typography.Text strong>{formatAuditAction(value)}</Typography.Text>,
    },
    {
      title: '目标',
      minWidth: 180,
      render: (_, row) => (
        <Typography.Text strong>
          {formatAuditTargetType(row.targetType)} #{row.targetId || '-'}
        </Typography.Text>
      ),
    },
    {
      title: '摘要',
      minWidth: 260,
      render: (_, row) => <span className="payload-text">{formatPayload(row.payload)}</span>,
    },
  ]

  function applyFilters(values: AuditFilterForm) {
    const [dateFrom, dateTo] = Array.isArray(values.dateRange)
      ? values.dateRange.map((item: { format?: (pattern: string) => string }) =>
          item?.format ? item.format('YYYY-MM-DD') : '',
        )
      : ['', '']

    setSearchParams(
      cleanParams({
        actorUsername: values.actorUsername,
        action: values.action,
        targetType: values.targetType,
        dateFrom,
        dateTo,
        page: 1,
        pageSize,
      }),
    )
  }

  function resetFilters() {
    setSearchParams(cleanParams({ page: 1, pageSize }))
  }

  return (
    <section className="page-stack">
      <PageHeader
        title="操作审计"
        description="集中查看高风险后台动作，便于排查谁在什么时间改了什么。"
        extra={
          <Typography.Text type="secondary">
            共 {data?.pagination.total || 0} 条审计记录
          </Typography.Text>
        }
      />

      {!isAdmin ? (
        <Alert type="warning" showIcon message="仅管理员可以访问操作审计" />
      ) : (
        <>
          <Card title="筛选审计日志">
            <Form<AuditFilterForm>
              layout="inline"
              initialValues={{
                actorUsername: filters.actorUsername,
                action: filters.action,
                targetType: filters.targetType,
                dateRange:
                  filters.dateFrom && filters.dateTo
                    ? [dayjs(filters.dateFrom), dayjs(filters.dateTo)]
                    : undefined,
              }}
              onFinish={applyFilters}
              className="filter-form"
            >
              <Form.Item name="actorUsername">
                <Input allowClear placeholder="操作账号" />
              </Form.Item>
              <Form.Item name="action">
                <Select
                  allowClear
                  placeholder="动作"
                  options={adminAuditActionOptions}
                  style={{ minWidth: 180 }}
                />
              </Form.Item>
              <Form.Item name="targetType">
                <Select
                  allowClear
                  placeholder="目标类型"
                  options={adminAuditTargetTypeOptions}
                  style={{ minWidth: 150 }}
                />
              </Form.Item>
              <Form.Item name="dateRange">
                <AdminRangePicker />
              </Form.Item>
              <Form.Item>
                <Space>
                  <Button type="primary" icon={<SearchOutlined />} htmlType="submit">
                    查询
                  </Button>
                  <Button icon={<ReloadOutlined />} onClick={resetFilters}>
                    重置
                  </Button>
                </Space>
              </Form.Item>
            </Form>
          </Card>

          {query.error ? (
            <Alert
              type="error"
              showIcon
              message={query.error instanceof Error ? query.error.message : '读取审计日志失败'}
            />
          ) : null}

          <Card>
            <Table<AdminAuditLogItem>
              rowKey="logId"
              loading={query.isLoading || query.isFetching}
              columns={columns}
              dataSource={data?.items || []}
              locale={{ emptyText: <Empty description="暂无审计记录" /> }}
              scroll={{ x: 980 }}
              pagination={buildAdminTablePagination({
                current: data?.pagination.page || page,
                pageSize: data?.pagination.pageSize || pageSize,
                total: data?.pagination.total || 0,
                onChange: (nextPage, nextPageSize) => {
                  setSearchParams(
                    cleanParams({ ...filters, page: nextPage, pageSize: nextPageSize }),
                  )
                },
              })}
            />
          </Card>
        </>
      )}
    </section>
  )
}

function formatPayload(payload: Record<string, unknown>) {
  const text = stringifyDisplayJson(payload, 0)
  return text.length > 140 ? `${text.slice(0, 140)}...` : text
}

function cleanParams(params: Record<string, unknown>) {
  const next = new URLSearchParams()
  Object.entries(params).forEach(([key, value]) => {
    const normalized = String(value ?? '').trim()
    if (normalized) {
      next.set(key, normalized)
    }
  })
  return next
}
