import { Table, Button, Space, Tooltip, Empty, Typography } from 'antd';
import { DownloadOutlined, ReloadOutlined } from '@ant-design/icons';
import type { TableColumnType, TableProps } from 'antd';
import { useDataTable } from '@/hooks/useDataTable';
import { formatCurrency, formatDate, formatNumber } from '@/lib/formatters';
import { getAmountClass } from '@/lib/formatters';
import * as XLSX from 'xlsx';
import { useCallback, useMemo } from 'react';

const { Text } = Typography;

export interface DataTableColumn<T> extends Omit<TableColumnType<T>, 'render' | 'dataIndex'> {
  dataIndex: string | string[];
  title: string;
  sortable?: boolean;
  filterable?: boolean;
  render?: (value: unknown, record: T, index: number) => React.ReactNode;
  columnType?: 'text' | 'number' | 'currency' | 'date' | 'boolean' | 'actions';
  decimalPlaces?: number;
  showSign?: boolean;
  exportable?: boolean;
}

interface DataTableProps<T extends { id: string }> {
  // Data source - either from hook or direct data
  queryKey?: string[];
  query?: string;
  variables?: Record<string, unknown>;
  dataPath?: string;
  totalPath?: string;

  // Or direct data
  data?: T[];
  loading?: boolean;

  // Columns
  columns: DataTableColumn<T>[];

  // Pagination
  pageSize?: number;
  pageSizeOptions?: number[];

  // Features
  rowSelection?: 'single' | 'multiple' | false;
  selectedRowKeys?: string[];
  onSelectionChange?: (selectedRowKeys: string[], selectedRows: T[]) => void;
  onRowClick?: (record: T) => void;
  exportable?: boolean;
  exportFilename?: string;
  refreshable?: boolean;

  // Row styling
  rowClassName?: (record: T, index: number) => string;

  // Actions
  toolbarActions?: React.ReactNode;
  toolbarTitle?: string;

  // Empty state
  emptyText?: string;

  // Scroll
  scroll?: TableProps<T>['scroll'];
}

export default function DataTable<T extends { id: string }>({
  queryKey,
  query,
  variables,
  dataPath,
  totalPath,
  data: directData,
  loading: directLoading,
  columns,
  pageSize = 20,
  rowSelection = false,
  selectedRowKeys: externalSelectedKeys,
  onSelectionChange,
  onRowClick,
  exportable = true,
  exportFilename = 'export',
  refreshable = true,
  rowClassName,
  toolbarActions,
  toolbarTitle,
  emptyText = 'Ingen data fundet',
  scroll,
}: DataTableProps<T>) {
  // Use hook if query is provided, otherwise use direct data
  const hookEnabled = !!(queryKey && query && dataPath && totalPath);

  const {
    data: hookData,
    total,
    isLoading: hookLoading,
    pagination,
    handleTableChange,
    refetch,
  } = useDataTable<T>({
    queryKey: queryKey || [],
    query: query || '',
    variables,
    dataPath: dataPath || '',
    totalPath: totalPath || '',
    pageSize,
    enabled: hookEnabled,
  });

  const data = hookEnabled ? hookData : (directData || []);
  const isLoading = hookEnabled ? hookLoading : (directLoading || false);

  // Process columns with default renders based on columnType
  const processedColumns = useMemo(() => {
    return columns.map((col) => {
      const processedCol: TableColumnType<T> = {
        ...col,
        sorter: col.sortable,
      };

      // Add default render based on columnType if no custom render
      if (!col.render && col.columnType) {
        switch (col.columnType) {
          case 'currency':
            processedCol.render = (value: unknown) => {
              const numValue = typeof value === 'number' ? value : 0;
              return (
                <span className={`currency tabular-nums ${getAmountClass(numValue)}`}>
                  {formatCurrency(numValue, {
                    showSign: col.showSign,
                    decimalPlaces: col.decimalPlaces,
                  })}
                </span>
              );
            };
            processedCol.align = 'right';
            break;

          case 'number':
            processedCol.render = (value: unknown) => {
              const numValue = typeof value === 'number' ? value : 0;
              return (
                <span className="tabular-nums">
                  {formatNumber(numValue, col.decimalPlaces)}
                </span>
              );
            };
            processedCol.align = 'right';
            break;

          case 'date':
            processedCol.render = (value: unknown) => {
              if (!value) return '-';
              return formatDate(value as string);
            };
            break;

          case 'boolean':
            processedCol.render = (value: unknown) => {
              return value ? 'Ja' : 'Nej';
            };
            break;
        }
      } else if (col.render) {
        processedCol.render = col.render;
      }

      return processedCol;
    });
  }, [columns]);

  // Row selection config
  const rowSelectionConfig = useMemo(() => {
    if (!rowSelection) return undefined;

    return {
      type: rowSelection === 'single' ? ('radio' as const) : ('checkbox' as const),
      selectedRowKeys: externalSelectedKeys,
      onChange: (keys: React.Key[], rows: T[]) => {
        onSelectionChange?.(keys as string[], rows);
      },
    };
  }, [rowSelection, externalSelectedKeys, onSelectionChange]);

  // Export to Excel
  const handleExport = useCallback(() => {
    const exportData = data.map((record) => {
      const row: Record<string, unknown> = {};
      columns.forEach((col) => {
        if (col.exportable !== false) {
          const value = Array.isArray(col.dataIndex)
            ? col.dataIndex.reduce(
                (obj: unknown, k) =>
                  obj && typeof obj === 'object' ? (obj as Record<string, unknown>)[k] : undefined,
                record
              )
            : record[col.dataIndex as keyof T];

          // Format value for export
          if (col.columnType === 'currency' && typeof value === 'number') {
            row[col.title] = value;
          } else if (col.columnType === 'date' && value) {
            row[col.title] = formatDate(value as string);
          } else {
            row[col.title] = value;
          }
        }
      });
      return row;
    });

    const worksheet = XLSX.utils.json_to_sheet(exportData);
    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, worksheet, 'Data');

    const filename = `${exportFilename}_${new Date().toISOString().split('T')[0]}.xlsx`;
    XLSX.writeFile(workbook, filename);
  }, [data, columns, exportFilename]);

  // Row click handler
  const onRow = useCallback(
    (record: T) => ({
      onClick: () => onRowClick?.(record),
      style: onRowClick ? { cursor: 'pointer' } : undefined,
    }),
    [onRowClick]
  );

  return (
    <div>
      {/* Toolbar */}
      {(toolbarTitle || toolbarActions || exportable || refreshable) && (
        <div
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            marginBottom: 16,
          }}
        >
          <div>
            {toolbarTitle && (
              <Text strong style={{ fontSize: 16 }}>
                {toolbarTitle}
              </Text>
            )}
          </div>
          <Space>
            {toolbarActions}
            {refreshable && hookEnabled && (
              <Tooltip title="Genindlaes">
                <Button
                  icon={<ReloadOutlined />}
                  onClick={() => refetch()}
                  loading={isLoading}
                />
              </Tooltip>
            )}
            {exportable && data.length > 0 && (
              <Tooltip title="Eksporter til Excel">
                <Button
                  icon={<DownloadOutlined />}
                  onClick={handleExport}
                >
                  Eksporter
                </Button>
              </Tooltip>
            )}
          </Space>
        </div>
      )}

      {/* Table */}
      <Table<T>
        columns={processedColumns}
        dataSource={data}
        rowKey="id"
        loading={isLoading}
        pagination={hookEnabled ? pagination : { pageSize, showSizeChanger: true }}
        onChange={hookEnabled ? handleTableChange : undefined}
        rowSelection={rowSelectionConfig}
        onRow={onRow}
        rowClassName={rowClassName}
        scroll={scroll || { x: 'max-content' }}
        size="small"
        bordered
        locale={{
          emptyText: <Empty description={emptyText} />,
        }}
        style={{ width: '100%' }}
      />

      {/* Footer with total count */}
      {hookEnabled && total > 0 && (
        <div style={{ marginTop: 8, textAlign: 'right' }}>
          <Text type="secondary">
            Total: {total.toLocaleString('da-DK')} poster
          </Text>
        </div>
      )}
    </div>
  );
}
