'use client';

import { createContext, useContext, useEffect, useRef, useCallback } from 'react';
import { usePathname } from 'next/navigation';
import { driver, type DriveStep, type Driver } from 'driver.js';
import 'driver.js/dist/driver.css';
import '@/styles/driver-onboarding.css';
import {
  MENTOR_ONBOARDING,
  CLIENT_ONBOARDING,
  PARENT_ONBOARDING,
  getOnboardingKey,
  getOnboardingProgress,
} from '@/lib/onboarding-steps';
import { getProfileSettings, updateProfileSettings } from '@/api/profile';
import { useAuth } from '@/contexts/AuthContext';

type Role = 'mentor' | 'client' | 'parent';

interface OnboardingContextType {
  markTourSeen: (pageId: string) => Promise<void>;
  runTourManually: (pageKey: string, options?: { force?: boolean }) => void;
  getProgress: () => { seen: number; total: number };
  refreshProgress: () => Promise<void>;
}

const OnboardingContext = createContext<OnboardingContextType | null>(null);

export function useOnboarding() {
  return useContext(OnboardingContext);
}

export function OnboardingProvider({ children }: { children: React.ReactNode }) {
  const pathname = usePathname();
  const { user } = useAuth();
  const toursSeenRef = useRef<Record<string, boolean>>({});
  const driverRef = useRef<Driver | null>(null);

  const markTourSeen = useCallback(async (pageId: string) => {
    if (!pageId) return;
    toursSeenRef.current[pageId] = true;
    try {
      await updateProfileSettings({
        onboarding_tours_seen: { [pageId]: true },
      });
    } catch {
      // ignore
    }
  }, []);

  const runTour = useCallback(
    (
      config: { pageId: string; steps: { element?: string; popover: { title: string; description: string; side?: string; align?: string } }[] },
      skipSeenCheck?: boolean
    ) => {
      if (!skipSeenCheck && toursSeenRef.current[config.pageId]) return;
      if (!config.steps.length) return;

      // Преобразуем шаги в формат driver.js
      const steps: DriveStep[] = config.steps
        .map((s) => {
          // driver.js: если элемент не найден, step показывается как overlay по центру
          const element = s.element && document.querySelector(s.element) ? s.element : undefined;
          return {
            element: element || undefined,
            popover: {
              title: s.popover.title,
              description: s.popover.description,
              side: (s.popover.side as 'top' | 'right' | 'bottom' | 'left') || 'bottom',
              align: (s.popover.align as 'start' | 'center' | 'end') || 'center',
            },
          };
        })
        .filter((s) => s.element || s.popover);

      if (steps.length === 0) return;

      if (driverRef.current) {
        driverRef.current.destroy();
        driverRef.current = null;
      }

      const driverObj = driver({
        showProgress: true,
        steps,
        nextBtnText: 'Далее',
        prevBtnText: 'Назад',
        doneBtnText: 'Понятно',
        progressText: '{{current}} из {{total}}',
        popoverClass: 'driver-onboarding-friendly',
        onDestroyStarted: () => {
          markTourSeen(config.pageId);
          driverObj.destroy();
          driverRef.current = null;
        },
      });
      driverRef.current = driverObj;
      driverObj.drive();
    },
    [markTourSeen]
  );

  const runTourManually = useCallback(
    (pageKey: string, options?: { force?: boolean }) => {
      const role = user?.role as Role;
      if (!role || !['mentor', 'client', 'parent'].includes(role)) return;
      const configs = role === 'mentor' ? MENTOR_ONBOARDING : role === 'client' ? CLIENT_ONBOARDING : PARENT_ONBOARDING;
      const config = configs[pageKey];
      if (config) runTour(config, options?.force);
    },
    [user?.role, runTour]
  );

  const getProgress = useCallback(() => {
    const role = user?.role as Role;
    if (!role || !['mentor', 'client', 'parent'].includes(role)) return { seen: 0, total: 0 };
    return getOnboardingProgress(toursSeenRef.current, role);
  }, [user?.role]);

  const refreshProgress = useCallback(async () => {
    try {
      const settings = await getProfileSettings();
      const seen = settings?.onboarding_tours_seen ?? {};
      toursSeenRef.current = { ...toursSeenRef.current, ...seen };
    } catch {
      // ignore
    }
  }, []);

  const runTourRef = useRef(runTour);
  runTourRef.current = runTour;

  useEffect(() => {
    if (!user) return;
    getProfileSettings()
      .then((s) => {
        const seen = s?.onboarding_tours_seen ?? {};
        toursSeenRef.current = { ...toursSeenRef.current, ...seen };
      })
      .catch(() => {});
  }, [user?.id]);

  useEffect(() => {
    if (!user || !pathname) return;
    const role = user.role as Role;
    if (!['mentor', 'client', 'parent'].includes(role)) return;

    if (pathname.startsWith('/login') || pathname.startsWith('/register') || pathname.startsWith('/livekit')) return;

    const key = getOnboardingKey(pathname, role);
    if (!key) return;

    const configs = role === 'mentor' ? MENTOR_ONBOARDING : role === 'client' ? CLIENT_ONBOARDING : PARENT_ONBOARDING;
    const config = configs[key];
    if (!config) return;

    let cancelled = false;
    const loadAndRun = async () => {
      try {
        const settings = await getProfileSettings();
        if (cancelled) return;
        const seen = settings?.onboarding_tours_seen ?? {};
        toursSeenRef.current = { ...toursSeenRef.current, ...seen };
        if (seen[config.pageId]) return;

        setTimeout(() => {
          if (!cancelled) runTourRef.current(config);
        }, 600);
      } catch {
        // при ошибке не показываем тур
      }
    };
    loadAndRun();
    return () => { cancelled = true; };
  }, [pathname, user]);

  const value: OnboardingContextType = {
    markTourSeen,
    runTourManually,
    getProgress,
    refreshProgress,
  };

  return (
    <OnboardingContext.Provider value={value}>
      {children}
    </OnboardingContext.Provider>
  );
}
