import React, { useCallback, useMemo, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useApiMutation } from '../../hooks/useApiMutation';
import { validateResponse } from '../../utils/validate';
import { roomTypesSchema, walletsSchema } from '../../api/schemas';
import {
  Button,
  Drawer,
  Form,
  Input,
  InputNumber,
  Modal,
  Radio,
  Select,
  Space,
  Switch,
  Table,
  Tag,
} from 'antd';
import { HistoryOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons';
import dayjs from 'dayjs';
import api from '../../api';
import PermissionButton from '../../components/PermissionButton';
import { message } from '../../ui/app-message';
import { newOperationId } from '../../utils/operation-id';
import { QueryErrorState, QueryEmpty } from '../../components/QueryState';
import { useVisibleRefetch } from '../../hooks/usePageVisible';

interface WalletRow {
  studentId: number;
  studentName: string;
  studentNo?: string;
  balance: number;
  outstandingAmount: number;
  roomType?: string;
  roomNumber?: string;
}

interface WalletTransaction {
  id: number;
  createdAt: string;
  type: string;
  amount: number;
  balanceAfter: number;
}

const transactionNames: Record<string, string> = {
  recharge: '充值',
  adjustment: '调账',
  bill_payment: '账单扣款',
  bill_refund: '账单冲正',
};

const WalletsPage: React.FC = () => {
  const [keyword, setKeyword] = useState('');
  const [debtOnly, setDebtOnly] = useState(false);
  const [roomType, setRoomType] = useState<string | undefined>();
  const [selected, setSelected] = useState<WalletRow | null>(null);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [form] = Form.useForm();
  const [batchForm] = Form.useForm();
  const [saving, setSaving] = useState(false);
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  const [batchModalOpen, setBatchModalOpen] = useState(false);

  const {
    data: rows = [],
    isLoading,
    isFetching,
    isError,
    refetch,
  } = useQuery<WalletRow[]>({
    queryKey: ['wallets', keyword, debtOnly, roomType],
    queryFn: async () => {
      return validateResponse<WalletRow[]>(
        walletsSchema,
        await api.get('/wallets', {
          params: { keyword: keyword || undefined, debtOnly, roomType },
        }),
      );
    },
  });
  const { data: roomTypes = [] } = useQuery<string[]>({
    queryKey: ['wallets', 'room-types'],
    queryFn: async () => {
      try {
        return validateResponse<string[]>(
          roomTypesSchema,
          await api.get('/wallets/room-types'),
        );
      } catch (error: any) {
        message.error(error?.message || '加载房型失败');
        return [];
      }
    },
  });
  const loading = isLoading || isFetching;
  // RouteKeeper 保活页面切回时刷新余额，避免费用/账单操作后数据陈旧
  useVisibleRefetch(['wallets']);

  const selectedStudentId = selected?.studentId;
  const {
    data: transactions = [],
    isLoading: txLoading,
    isFetching: txFetching,
    isError: txError,
    refetch: refetchTransactions,
  } = useQuery<WalletTransaction[]>({
    queryKey: ['wallets', 'transactions', selectedStudentId],
    enabled: drawerOpen && !!selectedStudentId,
    queryFn: async () => {
      return (
        (await api.get<WalletTransaction[]>('/wallets/transactions', {
          params: { studentId: selectedStudentId },
        })) || []
      );
    },
  });
  const fetchRows = useCallback(() => refetch(), [refetch]);

  const changeMutation = useApiMutation(
    async (payload: Record<string, unknown>) => api.post('/wallets/change-balance', payload),
    { invalidate: [['wallets']] },
  );
  const batchChangeMutation = useApiMutation(
    async (payload: Record<string, unknown>) =>
      api.post('/wallets/batch-change-balance', payload),
    { invalidate: [['wallets']] },
  );

  const updateKeyword = (value: string) => {
    setKeyword(value);
    setSelectedRowKeys([]);
  };
  const updateRoomType = (value: string | undefined) => {
    setRoomType(value);
    setSelectedRowKeys([]);
  };
  const updateDebtOnly = (value: boolean) => {
    setDebtOnly(value);
    setSelectedRowKeys([]);
  };

  const openChange = useCallback(
    (row: WalletRow) => {
      setSelected(row);
      form.setFieldsValue({ type: 'recharge', amount: undefined, description: '' });
    },
    [form, setSelected],
  );

  const openBatchChange = () => {
    batchForm.setFieldsValue({ type: 'recharge', amount: undefined, description: '' });
    setBatchModalOpen(true);
  };

  const submitChange = async () => {
    if (!selected) return;
    const values = await form.validateFields();
    setSaving(true);
    try {
      const result: any = await changeMutation.mutateAsync({
        operationId: newOperationId(),
        studentId: selected.studentId,
        ...values,
      });
      const paid = (result.payments || []).reduce(
        (sum: number, bill: any) => sum + Number(bill.paidAmount || 0),
        0,
      );
      message.success(paid > 0 ? `余额已更新，并自动补扣历史账单` : '余额已更新');
      setSelected(null);
    } catch {
      // 错误提示由 useApiMutation 统一处理
    } finally {
      setSaving(false);
    }
  };

  const submitBatchChange = async () => {
    const values = await batchForm.validateFields();
    setSaving(true);
    try {
      const result: any = await batchChangeMutation.mutateAsync({
        operationId: newOperationId(),
        studentIds: selectedRowKeys,
        ...values,
      });
      const paid = (result.results || []).reduce((sum: number, item: any) => {
        return (
          sum +
          (item.payments || []).reduce(
            (paymentSum: number, bill: any) => paymentSum + Number(bill.paidAmount || 0),
            0,
          )
        );
      }, 0);
      message.success(
        paid > 0
          ? `已批量更新 ${selectedRowKeys.length} 名学生余额，并自动补扣历史账单`
          : `已批量更新 ${selectedRowKeys.length} 名学生余额`,
      );
      setBatchModalOpen(false);
      setSelectedRowKeys([]);
      batchForm.resetFields();
    } catch {
      // 错误提示由 useApiMutation 统一处理
    } finally {
      setSaving(false);
    }
  };

  const showTransactions = useCallback(
    (row: WalletRow) => {
      setSelected(row);
      setDrawerOpen(true);
    },
    [setSelected, setDrawerOpen],
  );

  const columns = useMemo(
    () => [
      {
        title: '学生',
        render: (_: unknown, row: WalletRow) => (
          <>
            <strong>{row.studentName}</strong>
            <div style={{ color: '#999' }}>
              {row.roomType ? `${row.roomType}${row.roomNumber ? ` · ${row.roomNumber}` : ''}` : '未入住'}
            </div>
          </>
        ),
      },
      {
        title: '可用余额',
        dataIndex: 'balance',
        render: (value: number) => (
          <strong style={{ color: value > 0 ? '#1677ff' : undefined }}>
            ¥{value.toFixed(2)}
          </strong>
        ),
      },
      {
        title: '未付账单',
        dataIndex: 'outstandingAmount',
        render: (value: number) =>
          value > 0 ? (
            <Tag color="red">¥{value.toFixed(2)}</Tag>
          ) : (
            <Tag color="green">无欠费</Tag>
          ),
      },
      {
        title: '操作',
        fixed: 'right' as const,
        width: 140,
        render: (_: unknown, row: WalletRow) => (
          <Space>
            <PermissionButton
              permission="wallet:edit"
              type="primary"
              size="small"
              icon={<PlusOutlined />}
              onClick={() => openChange(row)}
            >
              充值/调账
            </PermissionButton>
            <Button size="small" icon={<HistoryOutlined />} onClick={() => showTransactions(row)}>
              流水
            </Button>
          </Space>
        ),
      },
    ],
    [openChange, showTransactions],
  );

  return (
    <div>
      <div
        style={{
          display: 'flex',
          justifyContent: 'space-between',
          gap: 12,
          marginBottom: 16,
          flexWrap: 'wrap',
        }}
      >
        <Space wrap>
          <Input.Search
            allowClear
            placeholder="搜索姓名或学号"
            style={{ width: 240 }}
            onSearch={updateKeyword}
            onChange={(event) => !event.target.value && updateKeyword('')}
          />
          <Select
            allowClear
            placeholder="按房型筛选"
            style={{ width: 180 }}
            value={roomType}
            onChange={updateRoomType}
            options={roomTypes.map((type) => ({ label: type, value: type }))}
          />
          <span>仅看欠费</span>
          <Switch checked={debtOnly} onChange={updateDebtOnly} />
        </Space>
        <Space wrap>
          <PermissionButton
            permission="wallet:edit"
            type="primary"
            icon={<PlusOutlined />}
            disabled={selectedRowKeys.length === 0}
            onClick={openBatchChange}
          >
            批量充值/调账
          </PermissionButton>
          <Button icon={<ReloadOutlined />} onClick={fetchRows}>
            刷新
          </Button>
        </Space>
      </div>
      {isError ? (
        <QueryErrorState
          title="钱包数据加载失败"
          description="请检查网络后重试。"
          onRetry={() => void refetch()}
        />
      ) : (
        <Table scroll={{ x: 'max-content' }}
          rowKey="studentId"
          loading={loading}
          locale={{ emptyText: <QueryEmpty description="暂无学生余额数据" /> }}
          dataSource={rows}
          columns={columns}
          rowSelection={{ selectedRowKeys, onChange: setSelectedRowKeys }}
          pagination={{
            defaultPageSize: 15,
            showSizeChanger: true,
            pageSizeOptions: [15, 30, 50, 100],
            showTotal: (total) => `共 ${total} 人`,
          }}
        />
      )}
      <Modal
        title={`${selected?.studentName || ''} - 余额操作`}
        open={!!selected && !drawerOpen}
        onCancel={() => setSelected(null)}
        onOk={submitChange}
        confirmLoading={saving}
        okText="确认"
      >
        <Form form={form} layout="vertical">
          <Form.Item name="type" label="操作类型" rules={[{ required: true }]}>
            <Radio.Group
              options={[
                { label: '充值', value: 'recharge' },
                { label: '调账', value: 'adjustment' },
              ]}
            />
          </Form.Item>

          <Form.Item
            name="amount"
            label="变动金额"
            extra="充值填正数；调减余额时填写负数。充值后会按最早账单优先自动补扣。"
            rules={[{ required: true, message: '请输入金额' }]}
          >
            <InputNumber precision={2} style={{ width: '100%' }} prefix="¥" />
          </Form.Item>

          <Form.Item name="description" label="备注">
            <Input.TextArea maxLength={300} />
          </Form.Item>
        </Form>
      </Modal>
      <Modal
        title={`批量余额操作（${selectedRowKeys.length} 人）`}
        open={batchModalOpen}
        onCancel={() => setBatchModalOpen(false)}
        onOk={submitBatchChange}
        confirmLoading={saving}
        okText="确认批量修改"
      >
        <Form form={batchForm} layout="vertical">
          <div style={{ marginBottom: 16, padding: 12, background: '#f5f5f5', borderRadius: 8 }}>
            已选择 <strong>{selectedRowKeys.length}</strong>{' '}
            名学生，将按相同金额批量修改水电费余额。可先按房型筛选并勾选对应学生后批量缴费。
          </div>
          <Form.Item name="type" label="操作类型" rules={[{ required: true }]}>
            <Radio.Group
              options={[
                { label: '充值', value: 'recharge' },
                { label: '调账', value: 'adjustment' },
              ]}
            />
          </Form.Item>

          <Form.Item
            name="amount"
            label="变动金额（元/人）"
            extra="充值填正数；调减余额时填写负数。充值后会按最早账单优先自动补扣。"
            rules={[{ required: true, message: '请输入金额' }]}
          >
            <InputNumber precision={2} style={{ width: '100%' }} prefix="¥" />
          </Form.Item>

          <Form.Item name="description" label="备注">
            <Input.TextArea maxLength={300} />
          </Form.Item>
        </Form>
      </Modal>
      <Drawer
        title={`${selected?.studentName || ''} - 余额流水`}
        size={680}
        open={drawerOpen}
        onClose={() => {
          setDrawerOpen(false);
          setSelected(null);
        }}
      >
        {txError ? (
          <QueryErrorState
            compact
            title="流水加载失败"
            description="请检查网络后重试。"
            onRetry={() => void refetchTransactions()}
          />
        ) : (
          <Table scroll={{ x: 'max-content' }}
            rowKey="id"
            dataSource={transactions}
            loading={txLoading || txFetching}
            pagination={{ pageSize: 10 }}
            columns={[
              {
                title: '时间',
                dataIndex: 'createdAt',
                render: (value: string) => dayjs(value).format('YYYY-MM-DD HH:mm'),
              },
              {
                title: '类型',
                dataIndex: 'type',
                render: (value: string) => transactionNames[value] || value,
              },
              {
                title: '金额',
                dataIndex: 'amount',
                render: (value: number) => (
                  <span style={{ color: value >= 0 ? '#389e0d' : '#cf1322' }}>
                    {value >= 0 ? '+' : ''}¥{value.toFixed(2)}
                  </span>
                ),
              },
              {
                title: '变动后余额',
                dataIndex: 'balanceAfter',
                render: (value: number) => `¥${value.toFixed(2)}`,
              },
              {
                title: '关联账单',
                dataIndex: 'billId',
                render: (value: number) => (value ? `#${value}` : '-'),
              },
              { title: '说明', dataIndex: 'description' },
            ]}
          />
        )}
      </Drawer>
    </div>
  );
};

export default WalletsPage;
