import { useEffect, useState } from 'react';
import { useSearchParams, useNavigate } from 'react-router-dom';
import {
  Button,
  Card,
  DatePicker,
  Descriptions,
  Drawer,
  Form,
  Input,
  Modal,
  Select,
  Space,
  Statistic,
  Table,
  Tag,
  Tooltip,
  Typography,
  message,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import type { Dayjs } from 'dayjs';
import {
  STORE_SETTLEMENT_KIND_LABELS,
  STORE_SETTLEMENT_STATUS_LABELS,
  storeSettlementStatusLabel,
  type StoreSettlementKind,
  type StoreSettlementStatus,
} from '@dukang/shared-types';
import { request, type Paginated } from '../lib/api';
import { ADMIN_OPTIONS_PAGE_SIZE, fmtTime } from '../lib/constants';
import { downloadExcelCsv } from '../lib/exportExcel';
import { useAdminList } from '../lib/useAdminList';
import { useAdminListColumns } from '../lib/useAdminListColumns';
import { AdminListHeader } from '../components/AdminListHeader';
import { AdminPrimaryLink } from '../components/AdminPrimaryLink';


type Row = {
  kind: StoreSettlementKind;
  id: string;
  billNo: string;
  amount: number;
  status: StoreSettlementStatus;
  date: string;
  overdue?: boolean;
  redeemCount?: number | null;
  redeemAmount?: number | null;
  settlementRate?: number | null;
  payoutCount?: number | null;
  store?: { id: string; name: string; cityName: string; phone?: string | null };
  bankAccount?: {
    bankAccountName?: string | null;
    bankAccountNo?: string | null;
    bankBranch?: string | null;
  } | null;
};

type StoreOption = { id: string; name: string; phone: string };

const STATUS_COLORS: Record<string, string> = {
  UNPAID: 'red',
  PAID: 'green',
  PENDING_REVIEW: 'orange',
  REJECTED: 'red',
};

function settlementStatusColor(kind: StoreSettlementKind, status: string) {
  if (status === 'PAID') return kind === 'WITHDRAW' ? 'cyan' : 'green';
  return STATUS_COLORS[status] || 'default';
}

const KIND_COLORS: Record<StoreSettlementKind, string> = {
  T1_BILL: 'blue',
  WITHDRAW: 'purple',
};

export default function StoreBillsPage() {
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const initialKind = searchParams.get('kind') === 'WITHDRAW' ? 'WITHDRAW' : '';
  const initialStoreId = searchParams.get('storeId') || '';
  const initialStatus =
    searchParams.get('status')?.trim() ||
    (initialKind === 'WITHDRAW' ? 'PENDING_REVIEW' : '');
  const [form] = Form.useForm();
  const [filters, setFilters] = useState<Record<string, string>>({
    kind: initialKind,
    status: initialStatus,
    storeId: initialStoreId,
  });
  const [stores, setStores] = useState<StoreOption[]>([]);
  const { data, loading, page, pageSize, setPage, setPageSize, reload } = useAdminList<Row>(
    '/admin/store-settlements',
    () => {
      const qs = new URLSearchParams();
      if (filters.kind) qs.set('kind', filters.kind);
      if (filters.status) qs.set('status', filters.status);
      if (filters.storeId) qs.set('storeId', filters.storeId);
      if (filters.dateFrom) qs.set('dateFrom', filters.dateFrom);
      if (filters.dateTo) qs.set('dateTo', filters.dateTo);
      return qs;
    },
    [filters],
  );
  const [detail, setDetail] = useState<Record<string, unknown> | null>(null);
  const [detailKind, setDetailKind] = useState<StoreSettlementKind | null>(null);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [exporting, setExporting] = useState(false);
  const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
  const [batchLoading, setBatchLoading] = useState(false);
  const [overdueSummary, setOverdueSummary] = useState<{
    pendingCount: number;
    overdueCount: number;
  } | null>(null);

  useEffect(() => {
    form.setFieldsValue({
      kind: filters.kind || undefined,
      status: filters.status || undefined,
      storeId: filters.storeId || undefined,
    });
  }, [filters.kind, filters.status, filters.storeId, form]);

  useEffect(() => {
    void request<Paginated<StoreOption>>(`/admin/stores?pageSize=${ADMIN_OPTIONS_PAGE_SIZE}`)
      .then((res) => setStores(res.items))
      .catch(() => {});
    void request<{ pendingCount: number; overdueCount: number }>(
      '/admin/store-withdrawals/overdue-summary',
    )
      .then(setOverdueSummary)
      .catch(() => {});
  }, []);

  function confirmPay(ids: string[], amountHint?: number) {
    let paymentRef = '';
    Modal.confirm({
      title: '确认打款？',
      content: (
        <div>
          <div>
            将确认 {ids.length} 笔 T+1 门店对账单
            {amountHint != null ? `，合计约 ¥${amountHint.toFixed(2)}` : ''}。此操作不可撤销。
          </div>
          <Input
            placeholder="打款凭证号（可选）"
            style={{ marginTop: 8 }}
            onChange={(e) => {
              paymentRef = e.target.value;
            }}
          />
        </div>
      ),
      okText: '确认打款',
      cancelText: '取消',
      onOk: async () => {
        const body = JSON.stringify({ paymentRef: paymentRef.trim() || undefined });
        if (ids.length === 1) {
          await request(`/admin/store-bills/${ids[0]}/confirm`, { method: 'POST', body });
        } else {
          setBatchLoading(true);
          try {
            await request('/admin/store-bills/batch-confirm', {
              method: 'POST',
              body: JSON.stringify({ ids }),
            });
          } finally {
            setBatchLoading(false);
          }
        }
        message.success('已确认打款');
        setSelectedKeys([]);
        reload();
      },
    });
  }

  function approveWithdraw(id: string) {
    let paymentRef = '';
    Modal.confirm({
      title: '审核通过并标记已结算？',
      content: (
        <Input
          placeholder="打款凭证号（可选）"
          onChange={(e) => {
            paymentRef = e.target.value;
          }}
        />
      ),
      okText: '通过并结算',
      cancelText: '取消',
      onOk: async () => {
        await request(`/admin/store-withdrawals/${id}/approve`, {
          method: 'POST',
          body: JSON.stringify({ paymentRef: paymentRef.trim() || undefined }),
        });
        message.success('已通过并标记已结算');
        setDrawerOpen(false);
        reload();
        void request<{ pendingCount: number; overdueCount: number }>(
          '/admin/store-withdrawals/overdue-summary',
        )
          .then(setOverdueSummary)
          .catch(() => {});
      },
    });
  }

  function rejectWithdraw(id: string) {
    let reason = '';
    Modal.confirm({
      title: '驳回提现申请？',
      content: (
        <Input.TextArea
          rows={3}
          placeholder="请填写驳回理由"
          onChange={(e) => {
            reason = e.target.value;
          }}
        />
      ),
      okText: '确认驳回',
      okButtonProps: { danger: true },
      cancelText: '取消',
      onOk: async () => {
        if (!reason.trim()) {
          message.error('请填写驳回理由');
          throw new Error('reason required');
        }
        await request(`/admin/store-withdrawals/${id}/reject`, {
          method: 'POST',
          body: JSON.stringify({ reason: reason.trim() }),
        });
        message.success('已驳回');
        setDrawerOpen(false);
        reload();
      },
    });
  }

  async function openDetail(row: Row) {
    const path =
      row.kind === 'WITHDRAW' ? `/admin/store-withdrawals/${row.id}` : `/admin/store-bills/${row.id}`;
    const d = await request<Record<string, unknown>>(path);
    setDetail(d);
    setDetailKind(row.kind);
    setDrawerOpen(true);
  }

  async function exportExcel() {
    setExporting(true);
    try {
      const qs = new URLSearchParams();
      if (filters.status) qs.set('status', filters.status);
      if (filters.storeId) qs.set('storeId', filters.storeId);
      if (filters.dateFrom) qs.set('dateFrom', filters.dateFrom);
      if (filters.dateTo) qs.set('dateTo', filters.dateTo);
      const result = await request<{ csv: string; count: number }>(`/admin/store-bills/export?${qs}`);
      downloadExcelCsv(result.csv, `门店对账单_${filters.dateFrom || 'all'}_${filters.dateTo || 'all'}.csv`);
      message.success(`已导出 ${result.count} 条 T+1 账单`);
    } finally {
      setExporting(false);
    }
  }

  const summary = data?.summary;
  const selectedRows = (data?.items ?? []).filter(
    (r) =>
      selectedKeys.includes(`${r.kind}-${r.id}`) &&
      r.kind === 'T1_BILL' &&
      r.status === 'UNPAID',
  );
  const selectedAmount = selectedRows.reduce((s, r) => s + Number(r.amount), 0);

  const baseColumns: ColumnsType<Row> = [
    {
      title: '类型',
      dataIndex: 'kind',
      width: 100,
      render: (k: StoreSettlementKind) => (
        <Tag color={KIND_COLORS[k]} style={{ minWidth: 72, textAlign: 'center' }}>
          {STORE_SETTLEMENT_KIND_LABELS[k] ?? k}
        </Tag>
      ),
    },
    {
      title: '单号',
      dataIndex: 'billNo',
      width: 180,
      render: (v, row) => (
        <Space>
          <AdminPrimaryLink onClick={() => void openDetail(row)}>{v}</AdminPrimaryLink>
          {row.overdue ? <Tag color="magenta">超时</Tag> : null}
        </Space>
      ),
    },
    {
      title: (
        <Tooltip title="T+1 为账单日（对应昨日核销自然日窗口，不是该账单里最后一笔核销时间）；手动提现为申请时间">
          账单日
        </Tooltip>
      ),
      dataIndex: 'date',
      width: 160,
      render: (v, row) => (row.kind === 'T1_BILL' ? String(v || '').slice(0, 10) : fmtTime(v)),
    },
    { title: '门店', dataIndex: ['store', 'name'], width: 140 },
    { title: '登录手机', dataIndex: ['store', 'phone'], width: 120, render: (v) => v || '—' },
    { title: '城市', dataIndex: ['store', 'cityName'], width: 90 },
    {
      title: '收款户名',
      width: 100,
      render: (_, row) =>
        row.kind === 'T1_BILL' ? row.bankAccount?.bankAccountName || '—' : '—',
    },
    {
      title: '收款账号',
      width: 140,
      render: (_, row) =>
        row.kind === 'T1_BILL' ? row.bankAccount?.bankAccountNo || '—' : '—',
    },
    {
      title: '笔数',
      width: 80,
      render: (_, row) =>
        row.kind === 'T1_BILL' ? (row.redeemCount ?? '—') : (row.payoutCount ?? '—'),
    },
    {
      title: '应付金额',
      dataIndex: 'amount',
      width: 110,
      render: (v) => `¥${Number(v).toFixed(2)}`,
    },
    {
      title: '状态',
      dataIndex: 'status',
      width: 100,
      render: (s: string, row) => (
        <Tag color={settlementStatusColor(row.kind, s)}>
          {storeSettlementStatusLabel(row.kind, s)}
        </Tag>
      ),
    },
    {
      title: '操作',
      width: 200,
      fixed: 'right',
      render: (_, row) => (
        <Space size={0}>
          <Button type="link" size="small" onClick={() => void openDetail(row)}>
            明细
          </Button>
          {row.kind === 'T1_BILL' && row.status === 'UNPAID' && (
            <Button type="link" size="small" onClick={() => confirmPay([row.id], Number(row.amount))}>
              确认打款
            </Button>
          )}
          {row.kind === 'WITHDRAW' && row.status === 'PENDING_REVIEW' && (
            <>
              <Button type="link" size="small" onClick={() => approveWithdraw(row.id)}>
                通过
              </Button>
              <Button type="link" size="small" danger onClick={() => rejectWithdraw(row.id)}>
                驳回
              </Button>
            </>
          )}
        </Space>
      ),
    },
  ];

  const withdrawDetailItems =
    (detail?.items as Array<Record<string, unknown>> | undefined) ?? [];
  const storeAccount = detail?.storeAccount as
    | {
        name?: string;
        phone?: string;
        bankAccountName?: string;
        bankAccountNo?: string;
        bankBranch?: string;
      }
    | undefined;

  const { columns, settingsButton, settingsModal } = useAdminListColumns('finance-store-bills', baseColumns, { page, pageSize });

  return (
    <div>
      {settingsModal}
      <AdminListHeader
        title="门店账单"
        settings={settingsButton}
        description={
          <>
            含 T+1 自动出账与门店手动提现；按类型筛选，详情与审核动作沿用原接口。
            「已打款」= T+1 出账终态，「已结算」= 手动提现终态。
            T+1「账单日」是出账对应的核销自然日（定时任务按昨日窗口生成），不是最后一笔核销时间。
            {overdueSummary && overdueSummary.overdueCount > 0 ? (
              <div>
                <Typography.Text type="danger">
                  手动提现超时未审 {overdueSummary.overdueCount} 笔（待审共 {overdueSummary.pendingCount}）
                </Typography.Text>
              </div>
            ) : null}
          </>
        }
      />

      {summary && (
        <Card size="small" style={{ marginBottom: 16 }}>
          <Space size="large" wrap>
            <Statistic title="记录数" value={summary.count} />
            <Statistic title="核销金额合计" value={summary.redeemAmount ?? 0} prefix="¥" precision={2} />
            <Statistic title="应付合计" value={summary.payoutAmount ?? summary.totalAmount ?? 0} prefix="¥" precision={2} />
          </Space>
        </Card>
      )}

      <Form
        form={form}
        layout="inline"
        style={{ marginBottom: 16 }}
        initialValues={{
          kind: filters.kind || undefined,
          status: filters.status || undefined,
          storeId: filters.storeId || undefined,
        }}
        onFinish={(v: {
          kind?: string;
          storeId?: string;
          status?: string;
          range?: [Dayjs, Dayjs];
        }) => {
          setFilters({
            kind: v.kind || '',
            storeId: v.storeId || '',
            status: v.status || '',
            dateFrom: v.range?.[0] ? v.range[0].format('YYYY-MM-DD') : '',
            dateTo: v.range?.[1] ? v.range[1].format('YYYY-MM-DD') : '',
          });
          setPage(1);
          setSelectedKeys([]);
        }}
      >
        <Form.Item name="kind" label="类型">
          <Select
            allowClear
            style={{ width: 140 }}
            options={Object.entries(STORE_SETTLEMENT_KIND_LABELS).map(([value, label]) => ({
              value,
              label,
            }))}
          />
        </Form.Item>
        <Form.Item name="storeId" label="门店">
          <Select
            allowClear
            showSearch
            placeholder="全部门店"
            style={{ width: 200 }}
            optionFilterProp="label"
            options={stores.map((s) => ({ value: s.id, label: s.name || s.phone || s.id }))}
          />
        </Form.Item>
        <Form.Item name="status" label="状态">
          <Select
            allowClear
            style={{ width: 120 }}
            options={Object.entries(STORE_SETTLEMENT_STATUS_LABELS).map(([value, label]) => ({
              value,
              label:
                value === 'PAID'
                  ? '已打款/已结算'
                  : label,
            }))}
          />
        </Form.Item>
        <Form.Item name="range" label="账单日">
          <DatePicker.RangePicker />
        </Form.Item>
        <Form.Item>
          <Button type="primary" htmlType="submit">
            查询
          </Button>
        </Form.Item>
        <Form.Item>
          <Button
            onClick={() => {
              form.resetFields();
              setFilters({});
              setPage(1);
              setSelectedKeys([]);
            }}
          >
            重置
          </Button>
        </Form.Item>
        <Form.Item>
          <Button loading={exporting} onClick={() => void exportExcel()}>
            导出 T+1 Excel
          </Button>
        </Form.Item>
        <Form.Item>
          <Button
            type="primary"
            disabled={!selectedRows.length}
            loading={batchLoading}
            onClick={() => confirmPay(selectedRows.map((r) => r.id), selectedAmount)}
          >
            批量确认打款 ({selectedRows.length})
          </Button>
        </Form.Item>
      </Form>

      <Table
        rowKey={(r) => `${r.kind}-${r.id}`}
        className="admin-table-nowrap"
        loading={loading}
        columns={columns}
        dataSource={data?.items ?? []}
        rowClassName={(row) => (row.overdue ? 'ant-table-row-selected' : '')}
        rowSelection={{
          selectedRowKeys: selectedKeys,
          onChange: setSelectedKeys,
          getCheckboxProps: (r) => ({
            disabled: !(r.kind === 'T1_BILL' && r.status === 'UNPAID'),
          }),
        }}
        scroll={{ x: 'max-content' }}
        pagination={{
          current: page,
          pageSize,
          total: data?.total ?? 0,
          showSizeChanger: true,
          onChange: (p, ps) => {
            setPage(p);
            setPageSize(ps);
          },
        }}
      />

      <Drawer
        title={detailKind === 'WITHDRAW' ? '手动提现明细' : 'T+1 对账单明细'}
        open={drawerOpen}
        onClose={() => setDrawerOpen(false)}
        width={detailKind === 'WITHDRAW' ? 640 : 520}
      >
        {detail && detailKind === 'T1_BILL' && (
          <>
            <Descriptions column={1} size="small" bordered>
              <Descriptions.Item label="账单号">{String(detail.billNo)}</Descriptions.Item>
              <Descriptions.Item label="账单日">
                {String(detail.billDate || '').slice(0, 10)}
              </Descriptions.Item>
              <Descriptions.Item label="应付">
                ¥{Number(detail.payoutAmount ?? 0).toFixed(2)}
              </Descriptions.Item>
              <Descriptions.Item label="状态">
                {storeSettlementStatusLabel('T1_BILL', String(detail.status))}
              </Descriptions.Item>
              <Descriptions.Item label="打款时间">
                {detail.paidAt ? fmtTime(String(detail.paidAt)) : '—'}
              </Descriptions.Item>
              <Descriptions.Item label="打款凭证">
                {detail.paymentRef ? String(detail.paymentRef) : '—'}
              </Descriptions.Item>
            </Descriptions>
            {(detail.storeAccount as {
              bankAccountName?: string;
              bankAccountNo?: string;
              bankBranch?: string;
            } | null) ? (
              <>
                <Typography.Title level={5} style={{ marginTop: 16 }}>
                  收款账户
                </Typography.Title>
                <Descriptions column={1} size="small" bordered>
                  <Descriptions.Item label="户名">
                    {(detail.storeAccount as { bankAccountName?: string }).bankAccountName || '—'}
                  </Descriptions.Item>
                  <Descriptions.Item label="账号">
                    {(detail.storeAccount as { bankAccountNo?: string }).bankAccountNo || '—'}
                  </Descriptions.Item>
                  <Descriptions.Item label="开户行">
                    {(detail.storeAccount as { bankBranch?: string }).bankBranch || '—'}
                  </Descriptions.Item>
                </Descriptions>
              </>
            ) : null}
            <Typography.Title level={5} style={{ marginTop: 16 }}>
              核销明细
            </Typography.Title>
            <Table
              size="small"
              rowKey="id"
              pagination={false}
              dataSource={(detail.payouts as Array<Record<string, unknown>>) || []}
              columns={[
                {
                  title: '核销单号',
                  render: (_, r) => {
                    const redeemNo = String(
                      (r.redeemRecord as { redeemNo?: string } | undefined)?.redeemNo || '',
                    );
                    return redeemNo ? (
                      <AdminPrimaryLink
                        onClick={() =>
                          navigate(`/redeem-records?redeemNo=${encodeURIComponent(redeemNo)}`)
                        }
                      >
                        {redeemNo}
                      </AdminPrimaryLink>
                    ) : (
                      '—'
                    );
                  },
                },
                {
                  title: '金额',
                  dataIndex: 'payoutAmount',
                  render: (v) => `¥${Number(v).toFixed(2)}`,
                },
                {
                  title: '状态',
                  dataIndex: 'status',
                  render: (s) => (s === 'PAID' ? '已打款' : '未打款'),
                },
              ]}
            />
          </>
        )}
        {detail && detailKind === 'WITHDRAW' && (
          <>
            <Descriptions column={1} size="small" bordered>
              <Descriptions.Item label="提现单号">{String(detail.withdrawNo)}</Descriptions.Item>
              <Descriptions.Item label="金额">
                ¥{Number(detail.amount ?? 0).toFixed(2)}
              </Descriptions.Item>
              <Descriptions.Item label="状态">
                {storeSettlementStatusLabel('WITHDRAW', String(detail.status))}
              </Descriptions.Item>
              <Descriptions.Item label="申请时间">
                {detail.appliedAt ? fmtTime(String(detail.appliedAt)) : '—'}
              </Descriptions.Item>
              <Descriptions.Item label="驳回理由">
                {detail.rejectReason ? String(detail.rejectReason) : '—'}
              </Descriptions.Item>
              <Descriptions.Item label="打款凭证">
                {detail.paymentRef ? String(detail.paymentRef) : '—'}
              </Descriptions.Item>
            </Descriptions>
            {storeAccount ? (
              <>
                <Typography.Title level={5} style={{ marginTop: 16 }}>
                  收款账户
                </Typography.Title>
                <Descriptions column={1} size="small" bordered>
                  <Descriptions.Item label="户名">
                    {storeAccount.bankAccountName || '—'}
                  </Descriptions.Item>
                  <Descriptions.Item label="账号">
                    {storeAccount.bankAccountNo || '—'}
                  </Descriptions.Item>
                  <Descriptions.Item label="开户行">
                    {storeAccount.bankBranch || '—'}
                  </Descriptions.Item>
                </Descriptions>
              </>
            ) : null}
            <Typography.Title level={5} style={{ marginTop: 16 }}>
              提现明细
            </Typography.Title>
            <Table
              size="small"
              rowKey="id"
              pagination={false}
              dataSource={withdrawDetailItems}
              columns={[
                {
                  title: '核销单号',
                  render: (_, r) => {
                    const payout = r.storePayout as
                      | { redeemRecord?: { redeemNo?: string }; payoutAmount?: number }
                      | undefined;
                    const redeemNo = payout?.redeemRecord?.redeemNo || '';
                    return redeemNo ? (
                      <AdminPrimaryLink
                        onClick={() =>
                          navigate(`/redeem-records?redeemNo=${encodeURIComponent(redeemNo)}`)
                        }
                      >
                        {redeemNo}
                      </AdminPrimaryLink>
                    ) : (
                      '—'
                    );
                  },
                },
                {
                  title: '应付',
                  render: (_, r) => {
                    const payout = r.storePayout as { payoutAmount?: number } | undefined;
                    return `¥${Number(payout?.payoutAmount ?? 0).toFixed(2)}`;
                  },
                },
              ]}
            />
            {String(detail.status) === 'PENDING_REVIEW' ? (
              <Space style={{ marginTop: 16 }}>
                <Button type="primary" onClick={() => approveWithdraw(String(detail.id))}>
                  通过
                </Button>
                <Button danger onClick={() => rejectWithdraw(String(detail.id))}>
                  驳回
                </Button>
              </Space>
            ) : null}
          </>
        )}
      </Drawer>
    </div>
  );
}
