// aislop-ignore-file: duplicate-block -- 表格/表单声明结构相似且参数不同，渲染逻辑已共享组件化
import React from 'react';
import {
  Button,
  Input,
  Popconfirm,
  Select,
  Space,
  Table,
  Tag,
  Upload,
} from 'antd';
import {
  DeleteOutlined,
  DownloadOutlined,
  EditOutlined,
  ExportOutlined,
  InboxOutlined,
  UndoOutlined,
  UploadOutlined,
  ThunderboltOutlined,
} from '@ant-design/icons';
import dayjs from 'dayjs';
import PermissionButton from '../../components/PermissionButton';
import EditableCell from '../../components/EditableCell';
import { QueryEmpty } from '../../components/QueryState';
import { message } from '../../ui/app-message';

export const EXPENSE_FIELDS = {
  roomId: 'roomId',
  expenseType: 'expenseType',
  amount: 'amount',
  description: 'description',
  studentId: 'studentId',
  expenseDate: 'expenseDate',
} as const;

export interface ExpenseTablePanelProps {
  kind: 'room' | 'personal';
  searchText: string;
  onSearchChange: (value: string) => void;
  typeFilter: string | undefined;
  onTypeFilterChange: (value?: string) => void;
  typeOptions: Array<{ value: string; label: string }>;
  typeMap: Record<string, string>;
  data: any[];
  loading: boolean;
  selectedKeys: number[];
  onSelect: (keys: number[]) => void;
  rooms: any[];
  students: any[];
  readonly: boolean;
  showArchived: boolean;
  canPurgeExpense: boolean;
  batchLoading: boolean;
  canImport: boolean;
  onBatchRestore: () => void;
  onBatchPurge: () => void;
  onBatchDelete: () => void;
  onSaveCell: (record: any, field: string, value: unknown) => Promise<void> | void;
  onPeriodSave: (id: number, periodStart: string, periodEnd: string) => Promise<void> | void;
  onEdit: (record: any) => void;
  onArchive: (id: number) => Promise<unknown> | unknown;
  onPurge: (id: number) => void;
  onImport: (formData: FormData) => Promise<any>;
  onTemplateDownload: () => void;
  onExport?: () => void;
  templateLoading?: boolean;
  exportLoading?: boolean;
  onAddUtility?: () => void;
}

export const ExpenseTablePanel: React.FC<ExpenseTablePanelProps> = ({
  kind,
  searchText,
  onSearchChange,
  typeFilter,
  onTypeFilterChange,
  typeOptions,
  typeMap,
  data,
  loading,
  selectedKeys,
  onSelect,
  rooms,
  students,
  readonly,
  showArchived,
  canPurgeExpense,
  batchLoading,
  canImport,
  onBatchRestore,
  onBatchPurge,
  onBatchDelete,
  onSaveCell,
  onPeriodSave,
  onEdit,
  onArchive,
  onPurge,
  onImport,
  onTemplateDownload,
  onExport,
  templateLoading,
  exportLoading,
  onAddUtility,
}) => {
  const isRoom = kind === 'room';
  const noun = isRoom ? '费用' : '个人费用';

  const EditableExpenseCell = ({
    value,
    editor,
    min,
    max,
    required,
    options,
    onSave,
    children,
  }: {
    value: unknown;
    editor?: React.ComponentProps<typeof EditableCell>['editor'];
    min?: number;
    max?: number;
    required?: boolean;
    options?: Array<{ value: string | number; label: string }>;
    onSave: (value: unknown) => Promise<void> | void;
    children?: React.ReactNode;
  }) => (
    <EditableCell
      value={value}
      editor={editor}
      min={min}
      max={max}
      required={required}
      options={options}
      permission="expense:edit"
      disabled={readonly}
      onSave={async (next) => {
        await onSave(next);
      }}
    >
      {children ?? String(value ?? '-')}
    </EditableCell>
  );

  const renderExpenseActions = (record: any) => {
    if (showArchived) {
      return (
        <Space>
          <Tag color="#999">已归档</Tag>
          {canPurgeExpense ? (
            <Button size="small" danger type="link" onClick={() => onPurge(record.id)}>
              删除
            </Button>
          ) : null}
        </Space>
      );
    }
    return (
      <Space>
        <PermissionButton
          permission="expense:edit"
          size="small"
          icon={<EditOutlined />}
          onClick={() => onEdit(record)}
        >
          编辑
        </PermissionButton>
        <Popconfirm
          title="确定归档？"
          onConfirm={async () => {
            try {
              await onArchive(record.id);
              message.success('归档成功');
            } catch {
              // 错误提示由 useApiMutation 统一处理
            }
          }}
        >
          <PermissionButton permission="expense:delete" size="small" danger icon={<InboxOutlined />}>
            归档
          </PermissionButton>
        </Popconfirm>
      </Space>
    );
  };

  const columns = isRoom
    ? [
        {
          title: '宿舍',
          width: 120,
          render: (_: any, r: any) => (
            <EditableExpenseCell
              value={r.roomId}
              editor="select"
              options={rooms.map((item) => ({ value: item.id, label: item.roomNumber }))}
              required
              onSave={(next) => onSaveCell(r, EXPENSE_FIELDS.roomId, next)}
            >
              {r.room?.roomNumber || '-'}
            </EditableExpenseCell>
          ),
        },
        {
          title: '费用类型',
          width: 100,
          dataIndex: 'expenseType',
          render: (v: string, r: any) => (
            <EditableExpenseCell
              value={v}
              editor="select"
              options={typeOptions}
              required
              onSave={(next) => onSaveCell(r, EXPENSE_FIELDS.expenseType, next)}
            >
              <Tag>{typeMap[v] || v}</Tag>
            </EditableExpenseCell>
          ),
        },
        {
          title: '金额',
          dataIndex: 'amount',
          width: 100,
          render: (v: number, r: any) => (
            <EditableExpenseCell
              value={v}
              editor="money"
              min={0.01}
              required
              onSave={(next) => onSaveCell(r, EXPENSE_FIELDS.amount, next)}
            >
              {`¥${v.toFixed(2)}`}
            </EditableExpenseCell>
          ),
        },
        {
          title: '账单周期',
          width: 200,
          render: (_: any, r: any) => (
            <EditableCell
              value={[r.periodStart, r.periodEnd]}
              editor="date-range"
              permission="expense:edit"
              disabled={readonly}
              required
              onSave={async (next) => {
                const [periodStart, periodEnd] = next as [string, string];
                await onPeriodSave(r.id, periodStart, periodEnd);
              }}
            >{`${r.periodStart} ~ ${r.periodEnd}`}</EditableCell>
          ),
        },
        {
          title: '说明',
          dataIndex: 'description',
          width: 150,
          render: (v: string, r: any) => (
            <EditableExpenseCell
              value={v}
              editor="textarea"
              onSave={(next) => onSaveCell(r, EXPENSE_FIELDS.description, next)}
            >
              {v || '-'}
            </EditableExpenseCell>
          ),
        },
        {
          title: '录入时间',
          width: 160,
          dataIndex: 'createdAt',
          render: (v: string) => dayjs(v).format('YYYY-MM-DD HH:mm'),
        },
        {
          title: '操作',
          width: 120,
          render: (_: any, record: any) => renderExpenseActions(record),
        },
      ]
    : [
        {
          title: '学生',
          width: 120,
          render: (_: any, r: any) => (
            <EditableExpenseCell
              value={r.studentId}
              editor="select"
              options={students.map((item) => ({ value: item.id, label: item.name }))}
              required
              onSave={(next) => onSaveCell(r, EXPENSE_FIELDS.studentId, next)}
            >
              {r.student?.name || '-'}
            </EditableExpenseCell>
          ),
        },
        {
          title: '费用类型',
          width: 100,
          dataIndex: 'expenseType',
          render: (v: string, r: any) => (
            <EditableExpenseCell
              value={v}
              editor="select"
              options={typeOptions}
              required
              onSave={(next) => onSaveCell(r, EXPENSE_FIELDS.expenseType, next)}
            >
              <Tag color="orange">{typeMap[v] || v}</Tag>
            </EditableExpenseCell>
          ),
        },
        {
          title: '金额',
          dataIndex: 'amount',
          render: (v: number, r: any) => (
            <EditableExpenseCell
              value={v}
              editor="money"
              min={0.01}
              required
              onSave={(next) => onSaveCell(r, EXPENSE_FIELDS.amount, next)}
            >
              {`¥${v.toFixed(2)}`}
            </EditableExpenseCell>
          ),
        },
        {
          title: '日期',
          dataIndex: 'expenseDate',
          width: 110,
          render: (v: string, r: any) => (
            <EditableExpenseCell
              value={v}
              editor="date"
              required
              onSave={(next) => onSaveCell(r, EXPENSE_FIELDS.expenseDate, next)}
            >
              {v}
            </EditableExpenseCell>
          ),
        },
        {
          title: '说明',
          dataIndex: 'description',
          width: 150,
          render: (v: string, r: any) => (
            <EditableExpenseCell
              value={v}
              editor="textarea"
              onSave={(next) => onSaveCell(r, EXPENSE_FIELDS.description, next)}
            >
              {v || '-'}
            </EditableExpenseCell>
          ),
        },
        {
          title: '操作',
          width: 120,
          render: (_: any, record: any) => renderExpenseActions(record),
        },
      ];

  return (
    <>
      <div
        style={{
          marginBottom: 16,
          display: 'flex',
          justifyContent: 'space-between',
          flexWrap: 'wrap',
          gap: 8,
        }}
      >
        <Space wrap>
          <Input.Search
            placeholder={isRoom ? '搜索宿舍号' : '搜索学生姓名'}
            allowClear
            style={{ width: 160 }}
            value={searchText}
            onSearch={(v) => onSearchChange(v)}
            onChange={(e) => {
              if (!e.target.value) onSearchChange('');
            }}
          />
          <Select
            placeholder="费用类型"
            allowClear
            style={{ width: 120 }}
            value={typeFilter}
            onChange={onTypeFilterChange}
            options={typeOptions}
          />
          {canImport && !showArchived && (
            <Upload
              accept=".xlsx,.xls"
              showUploadList={false}
              customRequest={async ({ file, onSuccess, onError }: any) => {
                try {
                  const formData = new FormData();
                  formData.append('file', file);
                  const res: any = await onImport(formData);
                  if (isRoom && res.errors?.length > 0) {
                    message.warning(res.message || '导入完成');
                    res.errors.forEach((e: string) => message.warning(e));
                  } else {
                    message.success(res.message || '导入完成');
                    if (res.errors?.length) res.errors.forEach((e: string) => message.warning(e));
                  }
                  onSuccess?.(res);
                } catch (e) {
                  onError?.(e as Error);
                }
              }}
            >
              <Button icon={<UploadOutlined />}>
                {isRoom ? '导入水电费Excel' : '导入个人附加费'}
              </Button>
            </Upload>
          )}
          {!showArchived && (
            <PermissionButton
              permission="expense:view"
              icon={<DownloadOutlined />}
              loading={templateLoading}
              onClick={onTemplateDownload}
            >
              {isRoom ? '下载水电费模板' : '下载模板'}
            </PermissionButton>
          )}
          {onExport && !showArchived ? (
            <PermissionButton
              permission="expense:view"
              icon={<ExportOutlined />}
              loading={exportLoading}
              onClick={onExport}
            >
              导出
            </PermissionButton>
          ) : null}
          {isRoom && onAddUtility && !showArchived ? (
            <PermissionButton
              permission="expense:create"
              icon={<ThunderboltOutlined />}
              onClick={onAddUtility}
            >
              添加学生水电费
            </PermissionButton>
          ) : null}
        </Space>
        <Space>
          {showArchived ? (
            <>
              <Popconfirm
                title={`确定恢复选中的 ${selectedKeys.length} 条${noun}？`}
                onConfirm={onBatchRestore}
                okText="恢复"
                cancelText="取消"
                disabled={selectedKeys.length === 0}
              >
                <PermissionButton
                  permission="expense:edit"
                  type="primary"
                  icon={<UndoOutlined />}
                  loading={batchLoading}
                  disabled={selectedKeys.length === 0}
                >
                  批量恢复
                </PermissionButton>
              </Popconfirm>
              {canPurgeExpense ? (
                <Popconfirm
                  title={`确定永久删除选中的 ${selectedKeys.length} 条${noun}？删除后不可恢复！`}
                  onConfirm={onBatchPurge}
                  okText="永久删除"
                  okButtonProps={{ danger: true }}
                  cancelText="取消"
                  disabled={selectedKeys.length === 0}
                >
                  <Button
                    danger
                    icon={<DeleteOutlined />}
                    loading={batchLoading}
                    disabled={selectedKeys.length === 0}
                  >
                    批量删除
                  </Button>
                </Popconfirm>
              ) : null}
            </>
          ) : (
            <Popconfirm
              title={`确定归档选中的 ${selectedKeys.length} 条${noun}？`}
              onConfirm={onBatchDelete}
              okText="归档"
              cancelText="取消"
              disabled={selectedKeys.length === 0}
            >
              <PermissionButton
                permission="expense:delete"
                danger
                icon={<InboxOutlined />}
                disabled={selectedKeys.length === 0}
              >
                批量归档
              </PermissionButton>
            </Popconfirm>
          )}
        </Space>
      </div>
      <Table
        columns={columns}
        dataSource={data}
        rowKey="id"
        loading={loading}
        scroll={{ x: 1200 }}
        pagination={{
          defaultPageSize: 15,
          showSizeChanger: true,
          pageSizeOptions: [15, 30, 50, 100],
          showTotal: (total) => `共 ${total} 条`,
        }}
        locale={{
          emptyText: (
            <QueryEmpty
              description="暂无数据"
              action={
                canImport && onAddUtility && !showArchived
                  ? { label: '添加学生水电费', onClick: onAddUtility }
                  : undefined
              }
            />
          ),
        }}
        rowSelection={{
          selectedRowKeys: selectedKeys,
          onChange: (keys) => onSelect(keys as number[]),
        }}
      />
    </>
  );
};
