import { useCallback, useMemo, useRef, useState } from 'react';
import { Button, message } from 'antd';
import { SettingOutlined } from '@ant-design/icons';
import type { ColumnsType, ColumnType } from 'antd/es/table';
import type { HqListColumnKey } from '@dukang/shared-types';
import { AdminListColumnsModal } from '../components/AdminListColumnsModal';
import { useListColumnPrefs } from './ListColumnPrefsContext';
import {
  ACTIONS_COLUMN_KEY,
  SERIAL_COLUMN_KEY,
  applyColumnPrefs,
  columnKey,
  settingItems,
  visibleColumnKeys,
  type ListColumnSettingItem,
} from './list-column-prefs';
import { beginColumnResize, withResizeTitle } from './column-resize';

type Options = {
  page?: number;
  pageSize?: number;
};

export function useAdminListColumns<T>(
  listKey: HqListColumnKey,
  allColumns: ColumnsType<T>,
  options: Options = {},
) {
  const { page = 1, pageSize = 20 } = options;
  const { prefs, save } = useListColumnPrefs();
  const [open, setOpen] = useState(false);
  const [saving, setSaving] = useState(false);
  const [localWidths, setLocalWidths] = useState<Record<string, number>>({});
  const pref = prefs[listKey];
  const prefRef = useRef(pref);
  prefRef.current = pref;
  const localWidthsRef = useRef(localWidths);
  localWidthsRef.current = localWidths;
  const itemsRef = useRef<ListColumnSettingItem[]>([]);

  const configured = useMemo(
    () => applyColumnPrefs(allColumns as ColumnType<T>[], pref),
    [allColumns, pref],
  );

  const items = useMemo(
    () => settingItems(allColumns as ColumnType<T>[], pref),
    [allColumns, pref],
  );
  itemsRef.current = items;

  const exportColumnKeys = useMemo(() => {
    const keyed = (allColumns as ColumnType<T>[]).map((col, i) => ({
      col,
      key: columnKey(col, i),
      actions: col.title === '操作' || col.key === ACTIONS_COLUMN_KEY || col.key === 'actions',
    }));
    const defaultKeys = keyed.filter((c) => !c.actions).map((c) => c.key);
    return visibleColumnKeys(defaultKeys, pref);
  }, [allColumns, pref]);

  const serialCol: ColumnType<T> = useMemo(
    () => ({
      key: SERIAL_COLUMN_KEY,
      title: '序号',
      width: 64,
      fixed: 'left' as const,
      render: (_: unknown, __: T, index: number) => (page - 1) * pageSize + index + 1,
    }),
    [page, pageSize],
  );

  const persistPref = useCallback(
    async (next: { order: string[]; hidden: string[]; widths?: Record<string, number> } | null) => {
      if (!next) {
        setLocalWidths({});
        await save(listKey, null);
        return;
      }
      await save(listKey, next);
    },
    [listKey, save],
  );

  const persist = useCallback(
    async (next: ListColumnSettingItem[] | null) => {
      setSaving(true);
      try {
        if (!next) {
          await persistPref(null);
        } else {
          const widths = { ...(prefRef.current?.widths ?? {}), ...localWidthsRef.current };
          await persistPref({
            order: next.map((i) => i.key),
            hidden: next.filter((i) => !i.visible).map((i) => i.key),
            ...(Object.keys(widths).length ? { widths } : {}),
          });
        }
        setOpen(false);
        message.success(next ? '列设置已保存' : '已恢复默认列');
      } catch (e) {
        message.error(e instanceof Error ? e.message : '保存失败');
      } finally {
        setSaving(false);
      }
    },
    [persistPref],
  );

  const persistWidth = useCallback(
    async (key: string, width: number) => {
      const current = prefRef.current;
      const prevW = current?.widths?.[key];
      if (prevW === width) return;
      const order = current?.order?.length ? current.order : itemsRef.current.map((i) => i.key);
      const hidden = current?.hidden ?? [];
      const widths = { ...(current?.widths ?? {}), ...localWidthsRef.current, [key]: width };
      try {
        await persistPref({ order, hidden, widths });
      } catch (e) {
        message.error(e instanceof Error ? e.message : '列宽保存失败');
      }
    },
    [persistPref],
  );

  const columns = useMemo<ColumnsType<T>>(() => {
    const merged: ColumnType<T>[] = [
      serialCol,
      ...configured.map((col) =>
        col.title === '操作' || col.key === ACTIONS_COLUMN_KEY || col.key === 'actions'
          ? { ...col, key: col.key ?? ACTIONS_COLUMN_KEY }
          : col,
      ),
    ];
    const widths = { ...(pref?.widths ?? {}), ...localWidths };
    return merged.map((col, i) => {
      const key = columnKey(col, i);
      const width = widths[key] ?? (typeof col.width === 'number' ? col.width : undefined);
      const prevHeader = col.onHeaderCell;
      return {
        ...col,
        key,
        width,
        title: withResizeTitle(col.title, (e) => {
          const th = (e.currentTarget as HTMLElement).closest('th');
          const startWidth = width ?? th?.getBoundingClientRect().width ?? 120;
          beginColumnResize(
            e,
            startWidth,
            (next) => setLocalWidths((prev) => ({ ...prev, [key]: next })),
            (next) => void persistWidth(key, next),
          );
        }),
        onHeaderCell: (column) => {
          const extra = typeof prevHeader === 'function' ? prevHeader(column) : {};
          return {
            ...extra,
            className: [extra.className, 'admin-th-resizable'].filter(Boolean).join(' '),
          };
        },
      };
    });
  }, [configured, serialCol, pref?.widths, localWidths, persistWidth]);

  const settingsButton = (
    <span className="admin-list-settings-slot">
      <Button type="text" icon={<SettingOutlined />} className="admin-list-settings-btn" onClick={() => setOpen(true)}>
        列设置
      </Button>
    </span>
  );

  const settingsModal = (
    <AdminListColumnsModal
      open={open}
      items={items}
      saving={saving}
      onCancel={() => setOpen(false)}
      onReset={() => void persist(null)}
      onSave={(draft) => void persist(draft)}
    />
  );

  return { columns, settingsButton, settingsModal, exportColumnKeys };
}
