import { useState, useEffect } from 'react';
import * as XLSX from 'xlsx';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { formatDate } from '@/lib/dateUtils';

export interface ExportColDef {
  key: string;
  label: string;
  /** 默认是否勾选，不传则视为 true */
  defaultChecked?: boolean;
  /** 必选列不可取消，用于回传模板中的稳定标识 */
  required?: boolean;
  /** 分组名，相同 group 的列归为一组渲染 */
  group?: string;
}

interface ExportDialogProps<T extends object> {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  data: T[];
  columns: ExportColDef[];
  filename?: string;
  /** 筛选后的全量数量，当 data 是已选子集时传入，用于显示"已选 X / 共 Y"提示 */
  totalCount?: number;
}

function formatCellValue(key: string, val: unknown): string | number {
  if (val == null) return '';
  if (Array.isArray(val)) return val.join(', ');
  if (key === 'created_at' || key === 'updated_at') return formatDate(String(val));
  if (typeof val === 'number') return val;
  return String(val);
}

export function ExportDialog<T extends object>({ open, onOpenChange, data, columns, filename, totalCount }: ExportDialogProps<T>) {
  const defaultSelected = () =>
    new Set(columns.filter(c => c.required || c.defaultChecked !== false).map(c => c.key));

  const [selected, setSelected] = useState<Set<string>>(defaultSelected);

  // 每次打开时重置勾选状态
  useEffect(() => {
    if (open) setSelected(defaultSelected());
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  function toggle(key: string) {
    const column = columns.find(item => item.key === key);
    if (column?.required) {
      return;
    }

    setSelected(prev => {
      const next = new Set(prev);
      if (next.has(key)) {
        next.delete(key);
      } else {
        next.add(key);
      }
      return next;
    });
  }

  function selectAll() { setSelected(new Set(columns.map(c => c.key))); }
  function selectNone() { setSelected(new Set(columns.filter(c => c.required).map(c => c.key))); }

  function handleExport() {
    const cols = columns.filter(c => selected.has(c.key));
    const header = cols.map(c => c.label);
    const rows = data.map(row =>
      cols.map(col => formatCellValue(col.key, (row as Record<string, unknown>)[col.key])),
    );

    const ws = XLSX.utils.aoa_to_sheet([header, ...rows]);
    ws['!cols'] = cols.map(c => ({ wch: Math.max(c.label.length * 2, 12) }));

    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');

    const defaultName = `导出_${new Date().toLocaleDateString('zh-CN').replace(/\//g, '-')}.xlsx`;
    XLSX.writeFile(wb, filename ?? defaultName);
    onOpenChange(false);
  }

  // 按 group 分组渲染
  const groups = [...new Set(columns.map(c => c.group).filter(Boolean))] as string[];
  const ungrouped = columns.filter(c => !c.group);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[460px]">
        <DialogHeader>
          <DialogTitle>导出 Excel</DialogTitle>
        </DialogHeader>

        <div className="py-2">
          {/* Sub-header */}
          <div className="flex justify-between items-center mb-6">
            <span className={`text-xs ${data.length === 0 ? 'text-destructive' : 'text-gray-500'}`}>
              {data.length === 0
                ? '未勾选数据，请先在表格中勾选需要导出的行'
                : totalCount !== undefined && data.length < totalCount
                  ? `已选 ${data.length} 条 / 共 ${totalCount} 条`
                  : `共 ${data.length} 条数据将被导出`}
            </span>
            <div className="flex items-center gap-3">
              <button type="button" onClick={selectAll} className="text-xs text-blue-600 hover:text-blue-700 hover:underline">全选</button>
              <button type="button" onClick={selectNone} className="text-xs text-blue-600 hover:text-blue-700 hover:underline">清除</button>
            </div>
          </div>

          {/* Field Groups */}
          <div className={`space-y-6 max-h-[55vh] overflow-y-auto pr-1 transition-opacity ${data.length === 0 ? 'opacity-40 pointer-events-none select-none' : ''}`}>
            {ungrouped.length > 0 && (
              <div className="grid grid-cols-2 gap-x-8 gap-y-4">
                {ungrouped.map(col => (
                  <label key={col.key} className="flex items-center gap-2.5 cursor-pointer select-none">
                    <Checkbox
                      checked={selected.has(col.key)}
                      onCheckedChange={() => toggle(col.key)}
                      disabled={col.required}
                      className="data-[state=checked]:bg-[#1e3a5f] data-[state=checked]:border-[#1e3a5f]"
                    />
                    <span className="text-sm">{col.label}{col.required ? '（必选）' : ''}</span>
                  </label>
                ))}
              </div>
            )}
            {groups.map(group => (
              <div key={group}>
                <p className="text-sm font-semibold text-gray-900 mb-3">{group}</p>
                <div className="grid grid-cols-2 gap-x-8 gap-y-4">
                  {columns.filter(c => c.group === group).map(col => (
                    <label key={col.key} className="flex items-center gap-2.5 cursor-pointer select-none">
                      <Checkbox
                        checked={selected.has(col.key)}
                        onCheckedChange={() => toggle(col.key)}
                        disabled={col.required}
                        className="data-[state=checked]:bg-[#1e3a5f] data-[state=checked]:border-[#1e3a5f]"
                      />
                      <span className="text-sm">{col.label}{col.required ? '（必选）' : ''}</span>
                    </label>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>取消</Button>
          <Button onClick={handleExport} disabled={selected.size === 0 || data.length === 0}>
            导出 Excel ({selected.size} 列)
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
