import { DEFAULT_FORM_FIELD_TYPES, PAGE_SIZE, STATUS_LABELS } from "../shared/constants.js";
import { createTableState } from "../shared/state.js";
import { sortByName, statusLabel } from "../shared/utils.js";

export function useTableActions({ api, setStatus, resolveTableConfig, tablesRef, setTableState, setDictionaries, buildUniversalQuery }) {
  const { useCallback } = React;

  const loadTable = useCallback(
    async (tableKey, options, tokenOverride) => {
      const opts = options || {};
      const config = resolveTableConfig(tableKey);
      if (!config) return false;

      const current = tablesRef.current[tableKey] || createTableState();
      const next = {
        ...current,
        filters: Array.isArray(opts.filtersOverride) ? [...opts.filtersOverride] : [...(current.filters || [])],
        sort: Array.isArray(opts.sortOverride) ? [...opts.sortOverride] : Array.isArray(current.sort) ? [...current.sort] : null,
        rows: [...(current.rows || [])],
      };

      if (opts.resetOffset) {
        next.offset = 0;
        next.showAll = false;
      }
      if (opts.loadAll) {
        next.offset = 0;
        next.showAll = true;
      }

      const statusKey = tableKey;
      setStatus(statusKey, "Загрузка...", "");

      try {
        const activeSort = next.sort && next.sort.length ? next.sort : config.sort;
        let limit = next.showAll ? Math.max(next.total || PAGE_SIZE, PAGE_SIZE) : PAGE_SIZE;
        const offset = next.showAll ? 0 : next.offset;
        let data = await api(
          config.endpoint,
          {
            method: "POST",
            body: buildUniversalQuery(next.filters, activeSort, limit, offset),
          },
          tokenOverride
        );

        next.total = Number(data.total || 0);
        next.rows = data.rows || [];

        if (next.showAll && next.total > next.rows.length) {
          limit = next.total;
          data = await api(
            config.endpoint,
            {
              method: "POST",
              body: buildUniversalQuery(next.filters, activeSort, limit, 0),
            },
            tokenOverride
          );
          next.total = Number(data.total || next.total);
          next.rows = data.rows || [];
        }

        if (!next.showAll && next.total > 0 && next.offset >= next.total) {
          next.offset = Math.floor((next.total - 1) / PAGE_SIZE) * PAGE_SIZE;
          setTableState(tableKey, next);
          return loadTable(tableKey, {}, tokenOverride);
        }

        setTableState(tableKey, next);

        if (tableKey === "requests") {
          setDictionaries((prev) => {
            const map = new Map((prev.topics || []).map((topic) => [topic.code, topic]));
            (next.rows || []).forEach((row) => {
              if (!row.topic_code || map.has(row.topic_code)) return;
              map.set(row.topic_code, { code: row.topic_code, name: row.topic_code });
            });
            return { ...prev, topics: sortByName(Array.from(map.values())) };
          });
        }

        if (tableKey === "topics") {
          setDictionaries((prev) => {
            const map = new Map((prev.topics || []).map((t) => [t.code, t]));
            (next.rows || []).forEach((row) => {
              if (row.code) map.set(row.code, { code: row.code, name: row.name || row.code });
            });
            return { ...prev, topics: sortByName(Array.from(map.values())) };
          });
        }

        if (tableKey === "statuses") {
          setDictionaries((prev) => {
            const map = new Map(Object.entries(STATUS_LABELS).map(([code, name]) => [code, { code, name }]));
            (next.rows || []).forEach((row) => {
              if (!row.code) return;
              map.set(row.code, { code: row.code, name: row.name || statusLabel(row.code) });
            });
            return { ...prev, statuses: sortByName(Array.from(map.values())) };
          });
        }

        if (tableKey === "formFields" || tableKey === "form_fields") {
          setDictionaries((prev) => {
            const set = new Set(DEFAULT_FORM_FIELD_TYPES);
            (next.rows || []).forEach((row) => {
              if (row?.type) set.add(row.type);
            });
            const fieldKeys = (next.rows || [])
              .filter((row) => row && row.key)
              .map((row) => ({ key: row.key, label: row.label || row.key }))
              .sort((a, b) => String(a.label || a.key).localeCompare(String(b.label || b.key), "ru"));
            return {
              ...prev,
              formFieldTypes: Array.from(set.values()).sort((a, b) => String(a).localeCompare(String(b), "ru")),
              formFieldKeys: fieldKeys,
            };
          });
        }

        if (tableKey === "users" || tableKey === "admin_users") {
          setDictionaries((prev) => {
            const map = new Map((prev.users || []).map((user) => [user.id, user]));
            (next.rows || []).forEach((row) => {
              map.set(row.id, {
                id: row.id,
                name: row.name || "",
                email: row.email || "",
                role: row.role || "",
                is_active: Boolean(row.is_active),
              });
            });
            return { ...prev, users: Array.from(map.values()) };
          });
        }

        setStatus(statusKey, "Список обновлен", "ok");
        return true;
      } catch (error) {
        setStatus(statusKey, "Ошибка: " + error.message, "error");
        return false;
      }
    },
    [api, buildUniversalQuery, resolveTableConfig, setDictionaries, setStatus, setTableState, tablesRef]
  );

  const loadPrevPage = useCallback(
    (tableKey) => {
      const tableState = tablesRef.current[tableKey] || createTableState();
      const next = { ...tableState, offset: Math.max(0, tableState.offset - PAGE_SIZE), showAll: false };
      setTableState(tableKey, next);
      loadTable(tableKey, {});
    },
    [loadTable, setTableState, tablesRef]
  );

  const loadNextPage = useCallback(
    (tableKey) => {
      const tableState = tablesRef.current[tableKey] || createTableState();
      if (tableState.offset + PAGE_SIZE >= tableState.total) return;
      const next = { ...tableState, offset: tableState.offset + PAGE_SIZE, showAll: false };
      setTableState(tableKey, next);
      loadTable(tableKey, {});
    },
    [loadTable, setTableState, tablesRef]
  );

  const loadAllRows = useCallback(
    (tableKey) => {
      const tableState = tablesRef.current[tableKey] || createTableState();
      if (!tableState.total) return;
      const next = { ...tableState, offset: 0, showAll: true };
      setTableState(tableKey, next);
      loadTable(tableKey, { loadAll: true });
    },
    [loadTable, setTableState, tablesRef]
  );

  const toggleTableSort = useCallback(
    (tableKey, field) => {
      const tableState = tablesRef.current[tableKey] || createTableState();
      const currentSort = Array.isArray(tableState.sort) ? tableState.sort[0] : null;
      const dir = currentSort && currentSort.field === field ? (currentSort.dir === "asc" ? "desc" : "asc") : "asc";
      const sortOverride = [{ field, dir }];
      const next = { ...tableState, sort: sortOverride, offset: 0, showAll: false };
      setTableState(tableKey, next);
      loadTable(tableKey, { resetOffset: true, sortOverride });
    },
    [loadTable, setTableState, tablesRef]
  );

  return {
    loadTable,
    loadPrevPage,
    loadNextPage,
    loadAllRows,
    toggleTableSort,
  };
}

export default useTableActions;
