'use client';

import { useSession } from 'next-auth/react';
import { signOutToPath } from '@/lib/auth-client';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useCallback, useEffect, useMemo, useState } from 'react';
import dynamic from 'next/dynamic';
import {
  AlertTriangle,
  Bell,
  CheckCircle2,
  Users,
  Settings,
  CreditCard,
  Info,
  LogOut,
  Bitcoin,
  ArrowLeft,
  LayoutDashboard,
  Loader2,
  X,
  UserCheck,
  FileText,
  Menu,
} from 'lucide-react';
import { AnimatePresence, motion } from 'framer-motion';
import ApiErrorAlert from '@/app/components/ApiErrorAlert';
import { getResponseErrorTextWithRequestId } from '@/lib/api-client';
import { ShieldAlert } from '@/app/admin/_components/icons';
import { OverviewTab } from '@/app/admin/_tabs/OverviewTab';
import { ApprovalsTab } from '@/app/admin/_tabs/ApprovalsTab';
import { UsersTab } from '@/app/admin/_tabs/UsersTab';
import { NotificationsTab } from '@/app/admin/_tabs/NotificationsTab';
import { PaymentsTab } from '@/app/admin/_tabs/PaymentsTab';
import {
  appSettingsCache,
  cryptobotSettingsCache,
  gateway2328SettingsCache,
  heleketSettingsCache,
  plategaSettingsCache,
} from '@/app/admin/_tabs/_cache';
import type {
  AdminAppSettingsResponse,
  CryptobotSettingsResponse,
  Gateway2328SettingsResponse,
  HeleketSettingsResponse,
  PlategaSettingsResponse,
} from '@/lib/types/admin';
import {
  applyUserPatch,
  cn,
  normalizeUser,
  parseBillingSource,
  parsePlan,
  toInputDate,
  toUserIdentity,
} from '@/lib/admin/utils';
import { PLAN_ORDER } from '@/lib/plans/catalog';
import { formatDateMoscow } from '@/lib/time';
import {
  PAID_PLAN_OPTIONS,
  PLAN_LABEL,
  type AdminUser,
  type BillingInvoice,
  type BillingResponse,
  type BillingStats,
  type NavTab,
  type OverrideModalDraft,
  type PaidPlanId,
  type UserRole,
} from '@/lib/types/admin';

const DynamicLoading = () => (
  <div className="h-full min-h-[240px] flex items-center justify-center">
    <div className="inline-flex items-center gap-2 text-gray-300">
      <Loader2 className="w-5 h-5 animate-spin text-violet-400" />
      Загружаем...
    </div>
  </div>
);

const CryptobotTab = dynamic(() => import('@/app/admin/_tabs/CryptobotTab').then((mod) => ({ default: mod.CryptobotTab })), {
  ssr: false,
  loading: DynamicLoading,
});
const Gateway2328Tab = dynamic(() => import('@/app/admin/_tabs/Gateway2328Tab').then((mod) => ({ default: mod.Gateway2328Tab })), {
  ssr: false,
  loading: DynamicLoading,
});
const HeleketTab = dynamic(() => import('@/app/admin/_tabs/HeleketTab').then((mod) => ({ default: mod.HeleketTab })), {
  ssr: false,
  loading: DynamicLoading,
});
const PlategaTab = dynamic(() => import('@/app/admin/_tabs/PlategaTab').then((mod) => ({ default: mod.PlategaTab })), {
  ssr: false,
  loading: DynamicLoading,
});
const SettingsTab = dynamic(() => import('@/app/admin/_tabs/SettingsTab').then((mod) => ({ default: mod.SettingsTab })), {
  ssr: false,
  loading: DynamicLoading,
});
const AuditTab = dynamic(() => import('@/app/admin/_tabs/AuditTab').then((mod) => ({ default: mod.AuditTab })), {
  ssr: false,
  loading: DynamicLoading,
});

export default function AdminPage() {
  const router = useRouter();
  const { data: session, status } = useSession();

  const isAdmin = session?.user?.role === 'ADMIN';
  const canAccessAdmin = session?.user?.role === 'ADMIN' || session?.user?.role === 'MODERATOR';

  const [currentTab, setCurrentTab] = useState<NavTab>('overview');
  const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
  const [approvalModeEnabled, setApprovalModeEnabled] = useState(false);

  const [users, setUsers] = useState<AdminUser[]>([]);
  const [invoices, setInvoices] = useState<BillingInvoice[]>([]);
  const [billingStats, setBillingStats] = useState<BillingStats>({
    totalRevenueUsdCents: 0,
    revenue30dUsdCents: 0,
    paidCount24h: 0,
    invoiceCount24h: 0,
  });

  const [overrideModal, setOverrideModal] = useState<OverrideModalDraft | null>(null);
  const [isInitialLoading, setIsInitialLoading] = useState(true);
  const [processingUserId, setProcessingUserId] = useState<string | null>(null);
  const [errorMessage, setErrorMessage] = useState('');
  const [successMessage, setSuccessMessage] = useState('');

  const navItems = useMemo(() => {
    const base: Array<{ id: NavTab; label: string; icon: typeof LayoutDashboard }> = [
      { id: 'overview', label: 'Обзор', icon: LayoutDashboard },
      ...(approvalModeEnabled ? [{ id: 'approvals' as NavTab, label: 'Одобрение', icon: UserCheck }] : []),
      { id: 'users', label: 'Пользователи', icon: Users },
      { id: 'notifications', label: 'Уведомления', icon: Bell },
    ];

    if (isAdmin) {
      base.push({ id: 'payments', label: 'Оплата и Биллинг', icon: CreditCard });
      base.push({ id: 'cryptobot', label: 'CryptoBot', icon: Bitcoin });
      base.push({ id: 'gateway2328', label: '2328.io', icon: CreditCard });
      base.push({ id: 'heleket', label: 'Heleket', icon: CreditCard });
      base.push({ id: 'platega', label: 'Platega', icon: CreditCard });
      base.push({ id: 'settings', label: 'Настройки', icon: Settings });
      base.push({ id: 'audit', label: 'Журнал действий', icon: FileText });
    }

    return base;
  }, [approvalModeEnabled, isAdmin]);

  const getApiErrorText = useCallback(async (response: Response, fallback: string) => {
    return getResponseErrorTextWithRequestId(response, fallback);
  }, []);

  const fetchUsers = useCallback(async () => {
    const response = await fetch('/api/admin/users', { cache: 'no-store' });
    if (!response.ok) {
      throw new Error(await getApiErrorText(response, 'Не удалось загрузить пользователей'));
    }

    const data = await response.json() as { users?: Array<Record<string, unknown>> };
    setUsers((data.users || []).map(normalizeUser));
  }, [getApiErrorText]);

  const fetchBilling = useCallback(async () => {
    const response = await fetch('/api/admin/billing/invoices', { cache: 'no-store' });
    if (!response.ok) {
      throw new Error(await getApiErrorText(response, 'Не удалось загрузить биллинг'));
    }

    const data = await response.json() as BillingResponse;
    setBillingStats(data.stats);
    setInvoices(data.invoices);
  }, [getApiErrorText]);

  useEffect(() => {
    if (status === 'unauthenticated') {
      router.replace('/login', { scroll: false });
      return;
    }

    if (status === 'authenticated' && !canAccessAdmin) {
      router.replace('/profile', { scroll: false });
      return;
    }

    if (status !== 'authenticated' || !canAccessAdmin) {
      return;
    }

    let cancelled = false;
    const loadData = async () => {
      setIsInitialLoading(true);

      void router.prefetch('/profile');

      // Billing is useful for analytics/widgets, but loading users first gives
      // faster first paint for the admin interface.
      void fetchBilling().catch((error) => {
        if (!cancelled) {
          setErrorMessage(error instanceof Error ? error.message : 'Не удалось загрузить биллинг');
        }
      });

      // Prefetch provider/app settings in the background so the corresponding
      // admin tabs mount instantly from cache instead of waiting on network.
      // Errors are swallowed here — they will resurface on tab visit.
      if (isAdmin) {
        void cryptobotSettingsCache
          .fetch(async () => {
            const response = await fetch('/api/admin/billing/providers/cryptobot', { cache: 'no-store' });
            if (!response.ok) throw new Error('prefetch failed');
            return await response.json() as CryptobotSettingsResponse;
          })
          .catch(() => {});
        void gateway2328SettingsCache
          .fetch(async () => {
            const response = await fetch('/api/admin/billing/providers/gateway2328', { cache: 'no-store' });
            if (!response.ok) throw new Error('prefetch failed');
            return await response.json() as Gateway2328SettingsResponse;
          })
          .catch(() => {});
        void heleketSettingsCache
          .fetch(async () => {
            const response = await fetch('/api/admin/billing/providers/heleket', { cache: 'no-store' });
            if (!response.ok) throw new Error('prefetch failed');
            return await response.json() as HeleketSettingsResponse;
          })
          .catch(() => {});
        void plategaSettingsCache
          .fetch(async () => {
            const response = await fetch('/api/admin/billing/providers/platega', { cache: 'no-store' });
            if (!response.ok) throw new Error('prefetch failed');
            return await response.json() as PlategaSettingsResponse;
          })
          .catch(() => {});
        void appSettingsCache
          .fetch(async () => {
            const response = await fetch('/api/admin/settings', { cache: 'no-store' });
            if (!response.ok) throw new Error('prefetch failed');
            return await response.json() as AdminAppSettingsResponse;
          })
          .catch(() => {});
      }

      try {
        const notificationsResponse = await fetch('/api/admin/notifications', { cache: 'no-store' });
        if (notificationsResponse.ok) {
          const notificationsData = await notificationsResponse.json() as { approvalModeEnabled?: boolean };
          setApprovalModeEnabled(Boolean(notificationsData.approvalModeEnabled));
        }
        await fetchUsers();
        if (!cancelled) {
          setErrorMessage('');
        }
      } catch (error) {
        if (!cancelled) {
          setErrorMessage(error instanceof Error ? error.message : 'Не удалось загрузить данные админки');
        }
      } finally {
        if (!cancelled) {
          setIsInitialLoading(false);
        }
      }
    };

    void loadData();
    return () => {
      cancelled = true;
    };
  }, [canAccessAdmin, fetchBilling, fetchUsers, isAdmin, router, status]);

  useEffect(() => {
    const adminOnlyTabs: NavTab[] = ['cryptobot', 'gateway2328', 'heleket', 'platega', 'settings', 'payments', 'audit'];
    if (adminOnlyTabs.includes(currentTab) && !isAdmin) {
      setCurrentTab('overview');
    }
    if (currentTab === 'approvals' && !approvalModeEnabled) {
      setCurrentTab('overview');
    }
  }, [approvalModeEnabled, currentTab, isAdmin]);

  useEffect(() => {
    if (!successMessage) return;
    const timeoutId = window.setTimeout(() => {
      setSuccessMessage('');
    }, 3200);
    return () => {
      window.clearTimeout(timeoutId);
    };
  }, [successMessage]);

  const pendingUsers = useMemo(() => users.filter((user) => !user.isApproved), [users]);

  const handleRoleChange = useCallback(async (userId: string, nextRole: UserRole) => {
    setProcessingUserId(userId);
    setSuccessMessage('');

    try {
      const response = await fetch('/api/admin/users', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ userId, role: nextRole }),
      });

      if (!response.ok) {
        throw new Error(await getApiErrorText(response, 'Не удалось обновить роль пользователя'));
      }

      const data = await response.json() as { user?: Record<string, unknown> };
      if (data.user) {
        setUsers((prev) => prev.map((user) => (user.id === userId ? applyUserPatch(user, data.user!) : user)));
      }

      setErrorMessage('');
      setSuccessMessage('Роль пользователя обновлена.');
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : 'Не удалось обновить роль пользователя');
    } finally {
      setProcessingUserId(null);
    }
  }, [getApiErrorText]);

  const handleApprovalChange = useCallback(async (userId: string, nextIsApproved: boolean) => {
    setProcessingUserId(userId);
    setSuccessMessage('');

    try {
      const response = await fetch('/api/admin/users', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ userId, isApproved: nextIsApproved }),
      });

      if (!response.ok) {
        throw new Error(await getApiErrorText(response, 'Не удалось обновить статус одобрения'));
      }

      const data = await response.json() as { user?: Record<string, unknown> };
      if (data.user) {
        setUsers((prev) => prev.map((user) => (user.id === userId ? applyUserPatch(user, data.user!) : user)));
      }

      setErrorMessage('');
      setSuccessMessage(nextIsApproved ? 'Пользователь одобрен.' : 'Одобрение пользователя снято.');
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : 'Не удалось обновить статус одобрения');
    } finally {
      setProcessingUserId(null);
    }
  }, [getApiErrorText]);

  const handleDeleteUser = useCallback(async (user: AdminUser) => {
    if (!isAdmin) return;
    const confirmed = window.confirm(`Удалить пользователя ${toUserIdentity(user)}?`);
    if (!confirmed) return;

    setProcessingUserId(user.id);
    setSuccessMessage('');

    try {
      const response = await fetch(`/api/admin/users?id=${user.id}`, { method: 'DELETE' });
      if (!response.ok) {
        throw new Error(await getApiErrorText(response, 'Не удалось удалить пользователя'));
      }

      setUsers((prev) => prev.filter((row) => row.id !== user.id));
      setErrorMessage('');
      setSuccessMessage('Пользователь удалён.');
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : 'Не удалось удалить пользователя');
    } finally {
      setProcessingUserId(null);
    }
  }, [getApiErrorText, isAdmin]);

  const applySnapshotToUser = useCallback((userId: string, snapshot: Record<string, unknown>) => {
    const nextPlan = parsePlan(snapshot.plan);
    const nextSource = parseBillingSource(snapshot.source);
    const endsAt = typeof snapshot.endsAt === 'string' ? snapshot.endsAt : null;
    const hasAdminOverride = Boolean(snapshot.hasAdminOverride || nextSource === 'ADMIN_OVERRIDE');

    setUsers((prev) => prev.map((user) => (user.id === userId
      ? {
          ...user,
          effectivePlan: nextPlan,
          billingSource: nextSource,
          planExpiresAt: endsAt,
          hasAdminOverride,
        }
      : user)));
  }, []);

  const handleOverrideAssign = useCallback(async (
    userId: string,
    plan: PaidPlanId,
    startsAt: string,
    endsAt: string | null,
  ) => {
    setProcessingUserId(userId);
    setSuccessMessage('');

    try {
      const response = await fetch('/api/admin/billing/overrides', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          userId,
          plan,
          startsAt,
          endsAt,
        }),
      });
      if (!response.ok) {
        throw new Error(await getApiErrorText(response, 'Не удалось назначить тариф вручную'));
      }

      const data = await response.json() as { snapshot?: Record<string, unknown> };
      if (data.snapshot) {
        applySnapshotToUser(userId, data.snapshot);
      }

      setErrorMessage('');
      setSuccessMessage('Тариф назначен вручную.');
      return true;
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : 'Не удалось назначить тариф вручную');
      return false;
    } finally {
      setProcessingUserId(null);
    }
  }, [applySnapshotToUser, getApiErrorText]);

  const openOverrideModal = useCallback((user: AdminUser) => {
    const today = toInputDate(new Date());
    setOverrideModal({
      userId: user.id,
      userLabel: toUserIdentity(user),
      plan: user.effectivePlan === 'FREE' ? 'MINIMAL' : (user.effectivePlan as PaidPlanId),
      startsAt: today,
      endsAt: today,
      isPermanent: true,
      currentEffectivePlan: user.effectivePlan,
      currentBillingSource: user.billingSource,
      currentPlanExpiresAt: user.planExpiresAt,
    });
  }, []);

  const closeOverrideModal = useCallback(() => {
    if (processingUserId) return;
    setOverrideModal(null);
  }, [processingUserId]);

  const submitOverrideModal = useCallback(async () => {
    if (!overrideModal) return;

    if (!overrideModal.startsAt) {
      setErrorMessage('Укажите дату начала действия тарифа.');
      return;
    }

    if (!overrideModal.isPermanent && !overrideModal.endsAt) {
      setErrorMessage('Укажите дату окончания или включите бессрочный режим.');
      return;
    }

    const startsAt = overrideModal.startsAt;
    const endsAt = overrideModal.isPermanent ? null : overrideModal.endsAt;

    if (endsAt && endsAt < startsAt) {
      setErrorMessage('Дата окончания должна быть позже даты начала.');
      return;
    }

    const isSuccess = await handleOverrideAssign(overrideModal.userId, overrideModal.plan, startsAt, endsAt);
    if (isSuccess) {
      setOverrideModal(null);
    }
  }, [handleOverrideAssign, overrideModal]);

  const handleOverrideRemove = useCallback(async (userId: string) => {
    setProcessingUserId(userId);
    setSuccessMessage('');

    try {
      const response = await fetch(`/api/admin/billing/overrides/${userId}`, { method: 'DELETE' });
      if (!response.ok) {
        throw new Error(await getApiErrorText(response, 'Не удалось снять ручное назначение тарифа'));
      }

      const data = await response.json() as { snapshot?: Record<string, unknown> };
      if (data.snapshot) {
        applySnapshotToUser(userId, data.snapshot);
      }

      setErrorMessage('');
      setSuccessMessage('Ручное назначение тарифа снято.');
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : 'Не удалось снять ручное назначение тарифа');
    } finally {
      setProcessingUserId(null);
    }
  }, [applySnapshotToUser, getApiErrorText]);

  if (status === 'loading' || status === 'unauthenticated' || !canAccessAdmin) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-[#050505]">
        <div className="text-center">
          <div className="w-8 h-8 border-2 border-violet-500 border-t-transparent rounded-full animate-spin mx-auto mb-4" />
          <p className="text-gray-400">Загрузка админки...</p>
        </div>
      </div>
    );
  }

  const sidebarContent = (
    <>
      <div className="absolute inset-0 bg-gradient-to-b from-violet-500/5 to-transparent pointer-events-none" />

      <div className="h-16 flex items-center px-6 border-b border-white/10 shrink-0 relative z-10">
        <div className="flex items-center gap-2 flex-1">
          <div className="w-6 h-6 rounded-md bg-gradient-to-br from-violet-500 to-fuchsia-600 flex items-center justify-center">
            <ShieldAlert className="w-3 h-3 text-white" strokeWidth={3} />
          </div>
          <span className="font-bold tracking-tight text-lg">AdminPanel</span>
        </div>
        <button
          onClick={() => setIsMobileMenuOpen(false)}
          className="md:hidden p-2 rounded-lg text-gray-400 hover:bg-white/[0.06] hover:text-white transition-colors"
          aria-label="Закрыть меню"
        >
          <X className="w-5 h-5" />
        </button>
      </div>

      <div className="p-4 flex-1 overflow-y-auto relative z-10">
        <div className="space-y-1 mb-6">
          <h3 className="px-3 text-xs font-semibold text-gray-500 uppercase tracking-wider mb-3">Меню</h3>
          {navItems.map((item) => (
            <button
              key={item.id}
              onClick={() => { setCurrentTab(item.id); setIsMobileMenuOpen(false); }}
              className={cn(
                'w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-all duration-300',
                currentTab === item.id
                  ? 'bg-white/5 text-white border border-white/5'
                  : 'text-gray-400 hover:bg-white/[0.03] hover:text-white',
              )}
            >
              <item.icon className={cn('w-4 h-4', currentTab === item.id ? 'text-violet-400' : 'text-gray-400')} />
              {item.label}
            </button>
          ))}
        </div>
      </div>

      <div className="p-4 border-t border-white/10 relative z-10 space-y-2">
        <Link
          href="/profile"
          onClick={() => setIsMobileMenuOpen(false)}
          className="w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-colors text-gray-400 hover:bg-white/[0.03] hover:text-white"
        >
          <ArrowLeft className="w-4 h-4 text-gray-400" />
          Вернуться в Дашборд
        </Link>
        <button
          onClick={() => void signOutToPath('/')}
          className="w-full flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-colors text-gray-400 hover:bg-red-500/10 hover:text-red-400 group"
        >
          <LogOut className="w-4 h-4 text-gray-400 group-hover:text-red-400 transition-colors" />
          Выйти
        </button>
      </div>
    </>
  );

  return (
    <div className="flex h-screen bg-[#050505] text-white font-sans overflow-hidden selection:bg-violet-500/30">
      {/* Desktop sidebar */}
      <aside className="hidden md:flex w-64 border-r border-white/10 bg-[#0A0A0A] flex-col z-20 shadow-2xl relative">
        {sidebarContent}
      </aside>

      {/* Mobile drawer overlay */}
      <AnimatePresence>
        {isMobileMenuOpen ? (
          <>
            <motion.div
              key="admin-drawer-backdrop"
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              transition={{ duration: 0.2 }}
              className="fixed inset-0 z-40 bg-black/60 backdrop-blur-sm md:hidden"
              onClick={() => setIsMobileMenuOpen(false)}
            />
            <motion.aside
              key="admin-drawer"
              initial={{ x: '-100%' }}
              animate={{ x: 0 }}
              exit={{ x: '-100%' }}
              transition={{ type: 'spring', damping: 30, stiffness: 300 }}
              className="fixed inset-y-0 left-0 z-50 w-72 bg-[#0A0A0A] border-r border-white/10 flex flex-col shadow-2xl md:hidden"
            >
              {sidebarContent}
            </motion.aside>
          </>
        ) : null}
      </AnimatePresence>

      <main className="flex-1 flex flex-col min-w-0 bg-[#050505] relative z-10">
        <header className="h-16 border-b border-white/10 flex items-center gap-3 px-4 md:px-6 bg-[#050505]/80 backdrop-blur-md sticky top-0 z-20">
          <button
            onClick={() => setIsMobileMenuOpen(true)}
            className="md:hidden p-2 -ml-1 rounded-lg text-gray-400 hover:bg-white/[0.06] hover:text-white transition-colors"
            aria-label="Открыть меню"
          >
            <Menu className="w-5 h-5" />
          </button>
          <h1 className="text-xl font-bold tracking-tight text-white/90">
            {navItems.find((item) => item.id === currentTab)?.label}
          </h1>
        </header>

        <div className="flex-1 overflow-y-auto overflow-x-hidden p-6 md:p-8 space-y-6">
          <ApiErrorAlert message={errorMessage} />

          {isInitialLoading ? (
            <div className="h-full min-h-[380px] flex items-center justify-center">
              <div className="inline-flex items-center gap-2 text-gray-300">
                <Loader2 className="w-5 h-5 animate-spin text-violet-400" />
                Загружаем данные...
              </div>
            </div>
          ) : (
            <AnimatePresence mode="wait">
              {currentTab === 'overview' ? (
                <OverviewTab
                  isAdmin={isAdmin}
                  users={users}
                  invoices={invoices}
                  billingStats={billingStats}
                  pendingUsers={pendingUsers}
                  onNavigate={setCurrentTab}
                />
              ) : null}

              {currentTab === 'approvals' && approvalModeEnabled ? (
                <ApprovalsTab
                  users={users}
                  processingUserId={processingUserId}
                  isAdmin={isAdmin}
                  onApprove={(userId) => void handleApprovalChange(userId, true)}
                  onUnapprove={(userId) => void handleApprovalChange(userId, false)}
                  onDeleteUser={(user) => void handleDeleteUser(user)}
                />
              ) : null}

              {currentTab === 'users' ? (
                <UsersTab
                  users={users}
                  isAdmin={isAdmin}
                  processingUserId={processingUserId}
                  onRoleChange={(userId, nextRole) => void handleRoleChange(userId, nextRole)}
                  onApprovalChange={(userId, nextIsApproved) => void handleApprovalChange(userId, nextIsApproved)}
                  onDeleteUser={(user) => void handleDeleteUser(user)}
                  onOpenOverride={openOverrideModal}
                  onOverrideRemove={(userId) => void handleOverrideRemove(userId)}
                />
              ) : null}

              {currentTab === 'notifications' ? (
                <NotificationsTab
                  isAdmin={isAdmin}
                  setErrorMessage={setErrorMessage}
                  setSuccessMessage={setSuccessMessage}
                  onApprovalModeChanged={setApprovalModeEnabled}
                />
              ) : null}

              {currentTab === 'payments' ? (
                <PaymentsTab invoices={invoices} billingStats={billingStats} />
              ) : null}

              {currentTab === 'cryptobot' ? (
                <CryptobotTab isAdmin={isAdmin} setErrorMessage={setErrorMessage} setSuccessMessage={setSuccessMessage} />
              ) : null}

              {currentTab === 'gateway2328' ? (
                <Gateway2328Tab isAdmin={isAdmin} setErrorMessage={setErrorMessage} setSuccessMessage={setSuccessMessage} />
              ) : null}

              {currentTab === 'heleket' ? (
                <HeleketTab isAdmin={isAdmin} setErrorMessage={setErrorMessage} setSuccessMessage={setSuccessMessage} />
              ) : null}

              {currentTab === 'platega' ? (
                <PlategaTab isAdmin={isAdmin} setErrorMessage={setErrorMessage} setSuccessMessage={setSuccessMessage} />
              ) : null}

              {currentTab === 'settings' ? (
                <SettingsTab isAdmin={isAdmin} setErrorMessage={setErrorMessage} setSuccessMessage={setSuccessMessage} />
              ) : null}

              {currentTab === 'audit' ? (
                <AuditTab isAdmin={isAdmin} setErrorMessage={setErrorMessage} />
              ) : null}
            </AnimatePresence>
          )}
        </div>
      </main>

      <AnimatePresence>
        {successMessage ? (
          <motion.div
            initial={{ opacity: 0, y: -8 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -8 }}
            className="fixed top-5 right-5 z-[120] max-w-sm rounded-2xl border border-emerald-500/25 bg-emerald-500/10 backdrop-blur-xl shadow-[0_15px_60px_rgba(16,185,129,0.15)]"
          >
            <div className="flex items-start gap-3 p-3.5">
              <CheckCircle2 className="w-5 h-5 text-emerald-300 mt-0.5 shrink-0" />
              <p className="text-sm text-emerald-100 leading-snug">{successMessage}</p>
              <button
                type="button"
                onClick={() => setSuccessMessage('')}
                className="ml-auto p-1 rounded-lg text-emerald-200/80 hover:text-emerald-100 hover:bg-emerald-500/20 transition-colors"
                aria-label="Закрыть уведомление"
              >
                <X className="w-4 h-4" />
              </button>
            </div>
          </motion.div>
        ) : null}
      </AnimatePresence>

      <AnimatePresence>
        {overrideModal ? (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="fixed inset-0 z-[130] bg-black/80 backdrop-blur-sm p-4 flex items-center justify-center"
            onMouseDown={(event) => {
              if (event.target === event.currentTarget) {
                closeOverrideModal();
              }
            }}
          >
            <motion.div
              initial={{ opacity: 0, y: 12, scale: 0.98 }}
              animate={{ opacity: 1, y: 0, scale: 1 }}
              exit={{ opacity: 0, y: 8, scale: 0.98 }}
              className="w-full max-w-lg rounded-3xl border border-white/10 bg-[#0A0A0A]/95 backdrop-blur-xl p-6 md:p-7 shadow-[0_25px_80px_rgba(0,0,0,0.55)]"
            >
              <div className="flex items-start justify-between gap-4 mb-6">
                <div>
                  <h3 className="text-xl font-bold tracking-tight text-white">Смена тарифа</h3>
                  <p className="text-sm text-gray-400 mt-1">Пользователь: {overrideModal.userLabel}</p>
                </div>
                <button
                  type="button"
                  onClick={closeOverrideModal}
                  disabled={Boolean(processingUserId)}
                  className="p-2 rounded-xl border border-white/10 bg-white/[0.03] hover:bg-white/[0.06] transition-colors text-gray-300 disabled:opacity-60"
                >
                  <X className="w-4 h-4" />
                </button>
              </div>

              {(() => {
                // Подсказка об эффекте override: админ-тарифы имеют приоритет над
                // PURCHASE, поэтому важно явно показать, что сейчас у юзера и
                // во что превратится картина после применения.
                const currentIdx = PLAN_ORDER.indexOf(overrideModal.currentEffectivePlan);
                const nextIdx = PLAN_ORDER.indexOf(overrideModal.plan);
                const currentExpiresLabel = overrideModal.currentPlanExpiresAt
                  ? formatDateMoscow(new Date(overrideModal.currentPlanExpiresAt), {
                      day: 'numeric', month: 'long', year: 'numeric',
                    })
                  : null;

                if (
                  overrideModal.currentBillingSource === 'PURCHASE'
                  && currentIdx > 0
                  && nextIdx < currentIdx
                ) {
                  return (
                    <div className="mb-5 flex items-start gap-2.5 rounded-2xl border border-amber-500/25 bg-amber-500/10 p-3 text-xs text-amber-100">
                      <AlertTriangle className="w-4 h-4 text-amber-300 mt-0.5 shrink-0" />
                      <div className="space-y-1">
                        <p className="font-semibold text-amber-50">
                          У пользователя активная оплаченная подписка {PLAN_LABEL[overrideModal.currentEffectivePlan]}
                          {currentExpiresLabel ? ` до ${currentExpiresLabel}` : ''}.
                        </p>
                        <p className="leading-relaxed">
                          Вы назначаете тариф ниже — на время действия ручного тарифа пользователь лишится оплаченного доступа. Купленная подписка не удаляется и восстановится после снятия ручного тарифа.
                        </p>
                      </div>
                    </div>
                  );
                }

                if (overrideModal.currentBillingSource === 'PURCHASE' && currentIdx > 0) {
                  return (
                    <div className="mb-5 flex items-start gap-2.5 rounded-2xl border border-blue-500/25 bg-blue-500/10 p-3 text-xs text-blue-100">
                      <Info className="w-4 h-4 text-blue-300 mt-0.5 shrink-0" />
                      <p className="leading-relaxed">
                        Сейчас у пользователя оплаченная подписка {PLAN_LABEL[overrideModal.currentEffectivePlan]}
                        {currentExpiresLabel ? ` до ${currentExpiresLabel}` : ''}. Ручной тариф перекроет её на указанный срок; после снятия ручного тарифа купленная подписка вернётся, если ещё не истекла.
                      </p>
                    </div>
                  );
                }

                if (overrideModal.currentBillingSource === 'ADMIN_OVERRIDE') {
                  return (
                    <div className="mb-5 flex items-start gap-2.5 rounded-2xl border border-violet-500/25 bg-violet-500/10 p-3 text-xs text-violet-100">
                      <Info className="w-4 h-4 text-violet-300 mt-0.5 shrink-0" />
                      <p className="leading-relaxed">
                        У пользователя уже активен ручной тариф {PLAN_LABEL[overrideModal.currentEffectivePlan]}
                        {currentExpiresLabel ? ` до ${currentExpiresLabel}` : ' (бессрочный)'}. Новое назначение заменит текущее.
                      </p>
                    </div>
                  );
                }

                return null;
              })()}

              <div className="space-y-5">
                <div className="space-y-2">
                  <label className="text-xs uppercase tracking-wider text-gray-500 font-semibold">Тариф</label>
                  <div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
                    {PAID_PLAN_OPTIONS.map((plan) => (
                      <button
                        key={plan}
                        type="button"
                        onClick={() => setOverrideModal((prev) => (prev ? { ...prev, plan } : prev))}
                        className={cn(
                          'px-3 py-2.5 rounded-xl border text-sm font-semibold transition-all',
                          overrideModal.plan === plan
                            ? 'border-violet-500/40 bg-violet-500/20 text-violet-200'
                            : 'border-white/10 bg-white/[0.03] text-gray-300 hover:border-white/20 hover:bg-white/[0.06]',
                        )}
                      >
                        {PLAN_LABEL[plan]}
                      </button>
                    ))}
                  </div>
                </div>

                <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
                  <div className="space-y-2">
                    <label className="text-xs uppercase tracking-wider text-gray-500 font-semibold">Дата начала</label>
                    <input
                      type="date"
                      value={overrideModal.startsAt}
                      onChange={(event) => setOverrideModal((prev) => (prev ? { ...prev, startsAt: event.target.value } : prev))}
                      className="w-full bg-black/40 border border-white/10 rounded-xl px-3 py-2.5 text-sm outline-none focus:border-violet-500/50 text-white"
                    />
                  </div>

                  <div className="space-y-2">
                    <label className="text-xs uppercase tracking-wider text-gray-500 font-semibold">Дата окончания</label>
                    <input
                      type="date"
                      value={overrideModal.endsAt}
                      disabled={overrideModal.isPermanent}
                      onChange={(event) => setOverrideModal((prev) => (prev ? { ...prev, endsAt: event.target.value } : prev))}
                      className="w-full bg-black/40 border border-white/10 rounded-xl px-3 py-2.5 text-sm outline-none focus:border-violet-500/50 text-white disabled:opacity-50"
                    />
                  </div>
                </div>

                <div className="space-y-2">
                  <label className="text-xs uppercase tracking-wider text-gray-500 font-semibold">Быстрый выбор периода</label>
                  <div className="grid grid-cols-3 gap-2">
                    {[
                      { days: 7, label: '7 дней' },
                      { days: 30, label: '30 дней' },
                      { days: 365, label: '365 дней' },
                    ].map((preset) => (
                      <button
                        key={preset.days}
                        type="button"
                        onClick={() => setOverrideModal((prev) => {
                          if (!prev) return prev;
                          const base = prev.startsAt ? new Date(prev.startsAt) : new Date();
                          if (Number.isNaN(base.getTime())) return prev;
                          const end = new Date(base);
                          end.setDate(end.getDate() + preset.days);
                          return {
                            ...prev,
                            startsAt: prev.startsAt || toInputDate(new Date()),
                            endsAt: toInputDate(end),
                            isPermanent: false,
                          };
                        })}
                        disabled={Boolean(processingUserId)}
                        className="px-3 py-2 rounded-xl border border-white/10 bg-white/[0.03] text-sm font-medium text-gray-200 hover:border-violet-500/40 hover:bg-violet-500/10 hover:text-violet-100 transition-all disabled:opacity-60"
                      >
                        {preset.label}
                      </button>
                    ))}
                  </div>
                </div>

                <label className="flex items-center gap-2.5 text-sm text-gray-300 cursor-pointer select-none">
                  <input
                    type="checkbox"
                    checked={overrideModal.isPermanent}
                    onChange={(event) => setOverrideModal((prev) => (prev ? { ...prev, isPermanent: event.target.checked } : prev))}
                    className="h-4 w-4 rounded border-white/20 bg-black/40 text-violet-500 focus:ring-violet-500/50"
                  />
                  Бессрочный тариф
                </label>
              </div>

              <div className="mt-7 flex items-center justify-end gap-2">
                <button
                  type="button"
                  onClick={closeOverrideModal}
                  disabled={Boolean(processingUserId)}
                  className="px-4 py-2.5 rounded-xl border border-white/10 bg-white/[0.03] text-gray-200 hover:bg-white/[0.08] transition-colors disabled:opacity-60"
                >
                  Отмена
                </button>
                <button
                  type="button"
                  onClick={() => void submitOverrideModal()}
                  disabled={Boolean(processingUserId)}
                  className="px-4 py-2.5 rounded-xl border border-violet-500/30 bg-gradient-to-r from-fuchsia-500 to-violet-600 text-white font-semibold hover:brightness-110 transition-all disabled:opacity-60"
                >
                  {processingUserId === overrideModal.userId ? 'Сохраняем...' : 'Применить'}
                </button>
              </div>
            </motion.div>
          </motion.div>
        ) : null}
      </AnimatePresence>
    </div>
  );
}
