'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { usePaginatedQuery } from '@/lib/hooks/usePaginatedQuery';
import { useAdminFilters } from '@/components/ui/domain/admin/AdminFilterBar/useAdminFilters';
import type { Locale, StringBundle } from '@/lib/i18n';
import { captureCaught } from '@/lib/observability';
import type { UserMatchKind, UserRow, UsersMgmtProps } from './UsersMgmt';
import {
  createUsersMgmtActions,
  createUsersMgmtBulkActions,
  createUsersMgmtChips,
  createUsersMgmtColumns,
  createUsersMgmtFilterSelects,
  createUsersMgmtRangeLabel,
  createUsersMgmtSegments,
  createUsersMgmtSubtitle,
  createUsersMgmtSuggestions,
} from './UsersMgmt.config';
import { MAX_RECENT, PARAM_KEYS, RECENT_STORAGE_KEY, SELECT_ALL } from './usersMgmt.shared';
import { useUserActions } from './useUserActions';

type AdminUsersKey = keyof StringBundle['admin_users'];
type AdminListKey = keyof StringBundle['admin_list'];
type AdminActionDrawerKey = keyof StringBundle['admin_action_drawer'];

function loadRecentIds(): string[] {
  if (typeof window === 'undefined') return [];
  try {
    const raw = localStorage.getItem(RECENT_STORAGE_KEY);
    if (!raw) return [];
    const parsed = JSON.parse(raw) as unknown;
    return Array.isArray(parsed) ? parsed.filter((id): id is string => typeof id === 'string') : [];
  } catch (err) {
    captureCaught(err, {
      scope: 'features.admin-users.useUsersMgmtController.loadRecentIds',
      severity: 'info',
    });
    return [];
  }
}

function pushRecentId(id: string): void {
  if (typeof window === 'undefined') return;
  const next = [id, ...loadRecentIds().filter((candidate) => candidate !== id)].slice(
    0,
    MAX_RECENT,
  );
  localStorage.setItem(RECENT_STORAGE_KEY, JSON.stringify(next));
}

export function applySegmentParams(params: Record<string, string>): void {
  if (typeof window === 'undefined') return;
  const url = new URL(window.location.pathname, window.location.origin);
  for (const [k, v] of Object.entries(params)) {
    if (v) url.searchParams.set(k, v);
  }
  window.history.pushState({}, '', url.toString());
  window.dispatchEvent(new PopStateEvent('popstate'));
}

interface UseUsersMgmtControllerArgs extends UsersMgmtProps {
  t: (key: AdminUsersKey) => string;
  tList: (key: AdminListKey) => string;
  tD: (key: AdminActionDrawerKey) => string;
  locale: Locale;
  toast: (args: {
    title: string;
    description?: string;
    tone?: 'success' | 'warning' | 'danger';
  }) => void;
}

export function useUsersMgmtController({
  initialUsers,
  initialTotal,
  initialPage,
  initialMatchKind = null,
  t,
  tList,
  tD,
  locale,
  toast,
}: UseUsersMgmtControllerArgs) {
  const tableWrapRef = useRef<HTMLDivElement>(null);
  const [selectedIds, setSelectedIds] = useState<string[]>([]);
  const [highlightedIndex, setHighlightedIndex] = useState(-1);
  const [recentIds, setRecentIds] = useState<string[]>(() => loadRecentIds());
  const [cityOptions, setCityOptions] = useState<{ value: string; label: string }[]>([]);
  const [exporting, setExporting] = useState(false);
  const [drawerUser, setDrawerUser] = useState<UserRow | null>(null);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const { filters, getMulti } = useAdminFilters([...PARAM_KEYS]);

  const params = useMemo(() => {
    const next: Record<string, string> = {};
    const states = getMulti('states');
    if (states.length) next.states = states.join(',');
    if (filters.roles && filters.roles !== SELECT_ALL) next.roles = filters.roles;
    if (filters.search) next.search = filters.search;
    if (filters.purchaseActivity) next.purchaseActivity = filters.purchaseActivity;
    if (filters.hasEmail === 'true') next.hasEmail = 'true';
    if (filters.emailVerified === 'true') next.emailVerified = 'true';
    if (filters.hasShippingAddress === 'true') next.hasShippingAddress = 'true';
    if (filters.cityCode && filters.cityCode !== SELECT_ALL) next.cityCode = filters.cityCode;
    if (filters.joinedFrom) next.joinedFrom = filters.joinedFrom;
    if (filters.joinedTo) next.joinedTo = filters.joinedTo;
    next.sort = filters.sort || 'joined_desc';
    return next;
  }, [filters, getMulti]);

  const query = usePaginatedQuery<UserRow>({
    endpoint: '/api/admin/users',
    params,
    limit: 20,
    initialData: initialUsers,
    initialTotal,
    initialPage,
    dataKey: 'users',
    includeEnvelopeMeta: true,
  });

  const matchKind: UserMatchKind | null =
    query.meta === undefined
      ? initialMatchKind
      : ((query.meta.matchKind as UserMatchKind | null | undefined) ?? null);

  const copyToClipboard = useCallback(
    async (text: string, ariaLabel: string) => {
      try {
        await navigator.clipboard.writeText(text);
        toast({ title: t('copied'), description: ariaLabel, tone: 'success' });
      } catch (err) {
        captureCaught(err, {
          scope: 'features.admin-users.useUsersMgmtController.copyToClipboard',
          severity: 'info',
        });
        toast({ title: ariaLabel, tone: 'warning' });
      }
    },
    [t, toast],
  );

  const trackRecent = useCallback((id: string) => {
    pushRecentId(id);
    setRecentIds(loadRecentIds());
  }, []);

  const actionsApi = useUserActions({
    t: (key: string) => t(key as AdminUsersKey),
    tD: (key: string) => tD(key as AdminActionDrawerKey),
    toast,
    refetch: query.refetch,
    data: query.data,
    selectedIds,
    setSelectedIds,
  });

  const openDrawer = useCallback(
    (user: UserRow) => {
      trackRecent(user.id);
      setDrawerUser(user);
      actionsApi.setFreezeReason('');
      actionsApi.setActionError(null);
      actionsApi.setActionSuccess(null);
      setDrawerOpen(true);
    },
    [actionsApi, trackRecent],
  );

  useEffect(() => {
    let cancelled = false;
    async function loadCities() {
      try {
        const res = await fetch('/api/cities?v=2');
        if (!res.ok) return;
        const json = (await res.json()) as { cities?: { cityCode: string; city: string }[] };
        if (cancelled) return;
        const options = (json.cities ?? [])
          .filter((city) => city.cityCode && city.city)
          .map((city) => ({ value: city.cityCode, label: city.city }));
        setCityOptions([{ value: SELECT_ALL, label: t('filter_all') }, ...options]);
      } catch (err) {
        captureCaught(err, {
          scope: 'features.admin-users.useUsersMgmtController.loadCities',
          severity: 'info',
        });
      }
    }
    void loadCities();
    return () => {
      cancelled = true;
    };
  }, [t]);

  const handleExportCsv = useCallback(async () => {
    setExporting(true);
    try {
      const qs = new URLSearchParams({ ...params, export: 'csv' });
      const res = await fetch(`/api/admin/users?${qs.toString()}`);
      if (res.status === 413) {
        toast({ title: t('export_too_large'), tone: 'warning' });
        return;
      }
      if (!res.ok) {
        toast({ title: t('export_failed'), tone: 'danger' });
        return;
      }
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      link.download = `multideal-users-${new Date().toISOString().slice(0, 10)}.csv`;
      link.click();
      URL.revokeObjectURL(url);
    } finally {
      setExporting(false);
    }
  }, [params, t, toast]);

  const columns = useMemo(
    () => createUsersMgmtColumns({ t, locale, copyToClipboard }),
    [copyToClipboard, locale, t],
  );
  const segments = useMemo(() => createUsersMgmtSegments(t), [t]);
  const { stateMultiChips, activityChips, completenessChips } = useMemo(
    () => createUsersMgmtChips(t),
    [t],
  );
  const filterSelects = useMemo(
    () => createUsersMgmtFilterSelects(t, cityOptions),
    [cityOptions, t],
  );
  const suggestions = useMemo(() => createUsersMgmtSuggestions(query.data), [query.data]);
  const subtitle = useMemo(
    () => createUsersMgmtSubtitle(t, matchKind, query.total),
    [matchKind, query.total, t],
  );
  const rangeLabel = useMemo(
    () => createUsersMgmtRangeLabel(tList, query.page, query.total),
    [query.page, query.total, tList],
  );
  const bulkActions = useMemo(
    () =>
      createUsersMgmtBulkActions({
        t,
        selectedIds,
        openBulkFreeze: () => {
          actionsApi.setBulkFreezeReason('');
          actionsApi.setBulkFreezeOpen(true);
        },
      }),
    [actionsApi, selectedIds, t],
  );
  const actions = useMemo(
    () =>
      createUsersMgmtActions({
        t,
        copyToClipboard,
        openQuickFreeze: (user) => {
          actionsApi.setQuickFreezeUser(user);
          actionsApi.setQuickFreezeReason('');
        },
        unfreezeUser: (userId) => {
          void actionsApi.unfreezeUser(userId);
        },
        openDrawer,
      }),
    [actionsApi, copyToClipboard, openDrawer, t],
  );

  useEffect(() => {
    const wrap = tableWrapRef.current;
    if (!wrap) return;
    function onClick(e: MouseEvent) {
      const anchor = (e.target as HTMLElement).closest('a[href^="/admin/users/"]');
      const id = anchor?.getAttribute('href')?.split('/').pop();
      if (id) trackRecent(id);
    }
    wrap.addEventListener('click', onClick);
    return () => wrap.removeEventListener('click', onClick);
  }, [trackRecent]);

  useEffect(() => {
    function onKeyDown(e: KeyboardEvent) {
      const target = e.target;
      const inField =
        target instanceof HTMLInputElement ||
        target instanceof HTMLTextAreaElement ||
        target instanceof HTMLSelectElement;
      if (e.key === '/' && !inField) {
        e.preventDefault();
        document.getElementById('admin-filter-search')?.focus();
        return;
      }
      if (inField) return;
      if (e.key === 'ArrowDown') {
        e.preventDefault();
        setHighlightedIndex((index) => Math.min(index < 0 ? 0 : index + 1, query.data.length - 1));
      } else if (e.key === 'ArrowUp') {
        e.preventDefault();
        setHighlightedIndex((index) => Math.max(index <= 0 ? 0 : index - 1, 0));
      } else if (e.key === 'Enter' && highlightedIndex >= 0 && query.data[highlightedIndex]) {
        e.preventDefault();
        const row = query.data[highlightedIndex]!;
        trackRecent(row.id);
        window.location.href = `/admin/users/${row.id}`;
      }
    }
    document.addEventListener('keydown', onKeyDown);
    return () => document.removeEventListener('keydown', onKeyDown);
  }, [highlightedIndex, query.data, trackRecent]);

  return {
    tableWrapRef,
    selectedIds,
    setSelectedIds,
    highlightedIndex,
    recentIds,
    exporting,
    drawerUser,
    drawerOpen,
    setDrawerOpen,
    query,
    actionsApi,
    columns,
    segments,
    stateMultiChips,
    activityChips,
    completenessChips,
    filterSelects,
    suggestions,
    subtitle,
    rangeLabel,
    bulkActions,
    actions,
    handleExportCsv,
    trackRecent,
  };
}
