"use client";

import * as React from "react";
import { usePathname, useRouter } from "next/navigation";

import { useCustomerPortalSession } from "@/app/customer/_components/customer-portal-session-context";
import { OPEN_PORTFOLIO_SCOPE_EVENT, PORTFOLIO_SCOPE_SHEET_OPEN_EVENT } from "@/app/customer/_lib/admin/impersonation-scope";
import type { CustomerNavigationPayload } from "@/navigation/sidebar/dynamic-sidebar";
import type { SidebarPanelId } from "@/navigation/sidebar/frontend-items";

import { TutorialCoachBar } from "./coach-bar";
import {
  coachPrimaryLabel,
  guideTaskStep,
  navigateForTask,
} from "./guide-actions";
import { TutorialHelpButton } from "./help-button";
import { useTutorialProgress } from "./progress";
import { resolveTutorialPlan } from "./resolver";
import { destroyTutorialTour, runWelcomeTour } from "./run-tour";
import { TutorialTaskChecklistSheet } from "./task-checklist-sheet";
import type { ResolvedTask, TutorialTaskId } from "./types";
import { TutorialWelcomeDialog } from "./welcome-dialog";

const OPEN_CHECKLIST_EVENT = "customer-tutorial:open-checklist";
const RESTART_TOUR_EVENT = "customer-tutorial:restart-tour";

/** Kill switch — set true to re-enable welcome tours / coachmarks. */
const CUSTOMER_TUTORIALS_ENABLED = false;

type TutorialApi = {
  openChecklist: () => void;
  restartTour: () => void;
};

const TutorialContext = React.createContext<TutorialApi | null>(null);

export function useCustomerTutorial(): TutorialApi {
  const value = React.useContext(TutorialContext);
  if (!value) {
    throw new Error("useCustomerTutorial must be used within CustomerTutorialProvider");
  }
  return value;
}

/** Safe for chrome that may render outside the provider. */
export function useCustomerTutorialOptional(): TutorialApi | null {
  return React.useContext(TutorialContext);
}

export function dispatchOpenTutorialChecklist() {
  if (typeof window !== "undefined") {
    window.dispatchEvent(new Event(OPEN_CHECKLIST_EVENT));
  }
}

export function dispatchRestartTutorialTour() {
  if (typeof window !== "undefined") {
    window.dispatchEvent(new Event(RESTART_TOUR_EVENT));
  }
}

/** Header help control — does not subscribe to tutorial progress (avoids shell re-renders). */
export function CustomerTutorialHelpSlot({ className }: { className?: string }) {
  const attention = React.useSyncExternalStore(
    () => () => undefined,
    () => {
      try {
        const keys = Object.keys(localStorage).filter((key) =>
          key.startsWith("customer_tutorial_v1:"),
        );
        if (keys.length === 0) {
          return true;
        }
        return keys.some((key) => {
          const raw = localStorage.getItem(key);
          if (!raw) return true;
          const parsed = JSON.parse(raw) as {
            skippedForever?: boolean;
            welcomeCompleted?: boolean;
          };
          if (parsed.skippedForever) return false;
          return !parsed.welcomeCompleted;
        });
      } catch {
        return false;
      }
    },
    () => false,
  );

  return (
    <TutorialHelpButton
      className={className}
      attention={attention}
      onClick={dispatchOpenTutorialChecklist}
    />
  );
}

type CustomerTutorialProviderProps = {
  children: React.ReactNode;
  tenant: string;
  userKey: string;
  navigation?: CustomerNavigationPayload;
  allowedRoutes?: readonly string[];
  canUsePortfolioScope?: boolean;
};

function panelIdsFromNavigation(
  navigation?: CustomerNavigationPayload,
): SidebarPanelId[] {
  if (!navigation?.panels?.length) {
    return [];
  }
  return navigation.panels.map((panel) => panel.id);
}

/**
 * Overlay-only host: owns tutorial UI state so progress updates do NOT re-render
 * the customer shell / page tree.
 */
function CustomerTutorialOverlay({
  tenant,
  userKey,
  navigation,
  allowedRoutes = [],
  canUsePortfolioScope = false,
}: Omit<CustomerTutorialProviderProps, "children">) {
  const router = useRouter();
  const pathname = usePathname();
  const { canMutateTransactions, portfolioScope } = useCustomerPortalSession();
  const {
    progress,
    markWelcomeCompleted,
    skipForever,
    restartWelcome,
    startTask,
    setTaskStep,
    completeTask,
    clearActiveTask,
    resetAll,
  } = useTutorialProgress(tenant, userKey);

  const [welcomeOpen, setWelcomeOpen] = React.useState(false);
  const [checklistOpen, setChecklistOpen] = React.useState(false);
  const autoWelcomeShown = React.useRef(false);
  const lastAutoStepKey = React.useRef<string>("");

  const panelIds = React.useMemo(
    () => panelIdsFromNavigation(navigation),
    [navigation],
  );

  const plan = React.useMemo(
    () =>
      resolveTutorialPlan({
        panelIds,
        allowedRoutes,
        canUsePortfolioScope: canUsePortfolioScope || portfolioScope,
        canMutateTransactions,
        progress,
      }),
    [
      panelIds,
      allowedRoutes,
      canUsePortfolioScope,
      portfolioScope,
      canMutateTransactions,
      progress,
    ],
  );

  const activeTaskDef: ResolvedTask | null = React.useMemo(() => {
    if (!progress.activeTask) {
      return null;
    }
    const fromPlan = plan.tasks.find((task) => task.id === progress.activeTask);
    if (fromPlan) {
      return fromPlan;
    }
    // Active task may already be marked complete in the filtered plan.
    return (
      resolveTutorialPlan({
        panelIds,
        allowedRoutes,
        canUsePortfolioScope: canUsePortfolioScope || portfolioScope,
        canMutateTransactions,
        progress: {
          ...progress,
          completedTasks: progress.completedTasks.filter(
            (id) => id !== progress.activeTask,
          ),
        },
      }).tasks.find((task) => task.id === progress.activeTask) ?? null
    );
  }, [
    progress,
    plan.tasks,
    panelIds,
    allowedRoutes,
    canUsePortfolioScope,
    portfolioScope,
    canMutateTransactions,
  ]);

  // Deferred welcome — don't compete with dashboard bootstrap APIs.
  React.useEffect(() => {
    if (autoWelcomeShown.current || !plan.showWelcome) {
      return;
    }
    autoWelcomeShown.current = true;
    const timer = window.setTimeout(() => {
      setWelcomeOpen(true);
    }, 2500);
    return () => window.clearTimeout(timer);
  }, [plan.showWelcome]);

  React.useEffect(() => {
    return () => {
      destroyTutorialTour();
    };
  }, []);

  React.useEffect(() => {
    const onOpen = () => {
      destroyTutorialTour();
      setWelcomeOpen(false);
      setChecklistOpen(true);
    };
    const onRestart = () => {
      destroyTutorialTour();
      setChecklistOpen(false);
      restartWelcome();
      autoWelcomeShown.current = true;
      setWelcomeOpen(true);
    };
    const onScopeOpened = () => {
      if (progress.activeTask === "task:scope" && progress.activeTaskStep === 0) {
        destroyTutorialTour();
        setTaskStep(1);
      }
    };
    const onScopeSheet = (event: Event) => {
      const open = Boolean(
        (event as CustomEvent<{ open?: boolean }>).detail?.open,
      );
      if (!open) return;
      destroyTutorialTour();
      if (progress.activeTask === "task:scope" && progress.activeTaskStep === 0) {
        setTaskStep(1);
      }
    };
    window.addEventListener(OPEN_CHECKLIST_EVENT, onOpen);
    window.addEventListener(RESTART_TOUR_EVENT, onRestart);
    window.addEventListener(OPEN_PORTFOLIO_SCOPE_EVENT, onScopeOpened);
    window.addEventListener(PORTFOLIO_SCOPE_SHEET_OPEN_EVENT, onScopeSheet);
    return () => {
      window.removeEventListener(OPEN_CHECKLIST_EVENT, onOpen);
      window.removeEventListener(RESTART_TOUR_EVENT, onRestart);
      window.removeEventListener(OPEN_PORTFOLIO_SCOPE_EVENT, onScopeOpened);
      window.removeEventListener(PORTFOLIO_SCOPE_SHEET_OPEN_EVENT, onScopeSheet);
    };
  }, [restartWelcome, progress.activeTask, progress.activeTaskStep, setTaskStep]);

  // Auto-advance at most once per pathname+task combination (no spotlight thrash).
  React.useEffect(() => {
    if (!progress.activeTask || !activeTaskDef) {
      return;
    }

    const key = `${progress.activeTask}:${pathname}`;
    if (lastAutoStepKey.current === key) {
      return;
    }

    const onReports = pathname.includes("/reports/");
    const onSettings = pathname.includes("/settings");
    const onTransactions =
      pathname.includes("/transactions") ||
      pathname.includes("/stock") ||
      pathname.includes("/bond");
    const onOrderBlotter = pathname.includes("/order-blotter");
    const onAdmin =
      pathname.includes("/admin/users") || pathname.includes("/admin/groups");
    const onDiscussion = pathname.includes("/discussion-board");
    const taskId = progress.activeTask;

    let nextStep: number | null = null;
    if (taskId.startsWith("task:report-") && onReports && progress.activeTaskStep < 2) {
      nextStep = 2;
    } else if (
      (taskId === "task:dashboard-widgets" || taskId === "task:report-banks") &&
      onSettings &&
      progress.activeTaskStep < 1
    ) {
      nextStep = 1;
    } else if (
      (taskId === "task:tx-browse" || taskId === "task:tx-view") &&
      onTransactions &&
      progress.activeTaskStep < 1
    ) {
      nextStep = 1;
    } else if (taskId === "task:order-blotter" && onOrderBlotter && progress.activeTaskStep < 1) {
      nextStep = 1;
    } else if (
      (taskId === "task:admin-users" || taskId === "task:admin-roles") &&
      onAdmin &&
      progress.activeTaskStep < 1
    ) {
      nextStep = 1;
    } else if (taskId === "task:discussion" && onDiscussion && progress.activeTaskStep < 1) {
      nextStep = 1;
    } else if (
      taskId === "task:dashboard-overview" &&
      pathname.includes("/dashboard") &&
      progress.activeTaskStep < 1
    ) {
      nextStep = 1;
    }

    if (nextStep == null) {
      return;
    }

    lastAutoStepKey.current = key;
    setTaskStep(nextStep);
  }, [
    pathname,
    progress.activeTask,
    progress.activeTaskStep,
    activeTaskDef,
    setTaskStep,
  ]);

  // Spotlight the active step target (once per step) without remounting the shell.
  React.useEffect(() => {
    if (!activeTaskDef || checklistOpen || welcomeOpen) {
      return;
    }
    const step = activeTaskDef.steps[progress.activeTaskStep];
    if (!step?.element) {
      destroyTutorialTour();
      return;
    }
    const timer = window.setTimeout(() => {
      void guideTaskStep(
        activeTaskDef,
        progress.activeTaskStep,
        {
          tenant,
          pathname,
          routerPush: (href) => router.push(href),
        },
        { navigate: false, forceHighlight: true },
      );
    }, 280);
    return () => window.clearTimeout(timer);
  }, [
    activeTaskDef,
    progress.activeTaskStep,
    checklistOpen,
    welcomeOpen,
    tenant,
    pathname,
    router,
  ]);

  const beginWelcomeTour = React.useCallback(() => {
    setWelcomeOpen(false);
    window.setTimeout(() => {
      void runWelcomeTour(plan.welcomeSteps, {
        onDestroyed: () => {
          markWelcomeCompleted();
          setChecklistOpen(true);
        },
      });
    }, 200);
  }, [plan.welcomeSteps, markWelcomeCompleted]);

  const handleSkipWelcome = React.useCallback(() => {
    setWelcomeOpen(false);
    markWelcomeCompleted();
  }, [markWelcomeCompleted]);

  const handleSkipForever = React.useCallback(() => {
    setWelcomeOpen(false);
    skipForever();
  }, [skipForever]);

  const restartTour = React.useCallback(() => {
    destroyTutorialTour();
    setChecklistOpen(false);
    restartWelcome();
    autoWelcomeShown.current = true;
    setWelcomeOpen(true);
  }, [restartWelcome]);

  const handleStartTask = React.useCallback(
    (taskId: TutorialTaskId) => {
      const task =
        plan.tasks.find((item) => item.id === taskId) ??
        (activeTaskDef?.id === taskId ? activeTaskDef : null);
      lastAutoStepKey.current = "";
      startTask(taskId);
      setChecklistOpen(false);
      if (!task) {
        return;
      }
      const ctx = {
        tenant,
        pathname,
        routerPush: (href: string) => router.push(href),
      };
      navigateForTask(task, ctx);
      window.setTimeout(() => {
        void guideTaskStep(task, 0, ctx, {
          navigate: false,
          forceHighlight: true,
        });
      }, 320);
    },
    [plan.tasks, activeTaskDef, startTask, router, tenant, pathname],
  );

  const handleOpenTarget = React.useCallback(() => {
    if (!activeTaskDef) {
      return;
    }
    const ctx = {
      tenant,
      pathname,
      routerPush: (href: string) => router.push(href),
    };
    navigateForTask(activeTaskDef, ctx);
    void guideTaskStep(activeTaskDef, progress.activeTaskStep, ctx, {
      forceHighlight: true,
    }).then(() => {
      // After opening Scope / Search, move past the "click this control" step.
      if (
        progress.activeTaskStep === 0 &&
        (activeTaskDef.id === "task:scope" ||
          activeTaskDef.id === "task:search" ||
          activeTaskDef.id === "task:holdings-search")
      ) {
        setTaskStep(1);
      }
    });
  }, [
    activeTaskDef,
    progress.activeTaskStep,
    router,
    tenant,
    pathname,
    setTaskStep,
  ]);

  const handleCoachNext = React.useCallback(() => {
    if (!activeTaskDef || !progress.activeTask) {
      return;
    }
    const next = progress.activeTaskStep + 1;
    if (next >= activeTaskDef.steps.length) {
      destroyTutorialTour();
      completeTask(progress.activeTask);
      setChecklistOpen(true);
      return;
    }
    setTaskStep(next);
  }, [
    activeTaskDef,
    progress.activeTask,
    progress.activeTaskStep,
    completeTask,
    setTaskStep,
  ]);

  const handleCoachBack = React.useCallback(() => {
    setTaskStep(Math.max(0, progress.activeTaskStep - 1));
  }, [progress.activeTaskStep, setTaskStep]);

  return (
    <>
      <TutorialWelcomeDialog
        open={welcomeOpen}
        onStart={beginWelcomeTour}
        onSkip={handleSkipWelcome}
        onSkipForever={handleSkipForever}
      />
      <TutorialTaskChecklistSheet
        open={checklistOpen}
        onOpenChange={setChecklistOpen}
        tasks={plan.tasks}
        completedTasks={progress.completedTasks}
        activeTask={progress.activeTask}
        onStartTask={handleStartTask}
        onRestartTour={restartTour}
        onResetProgress={() => {
          resetAll();
          setChecklistOpen(false);
          autoWelcomeShown.current = false;
        }}
      />
      {activeTaskDef && !checklistOpen && !welcomeOpen ? (
        <TutorialCoachBar
          task={activeTaskDef}
          stepIndex={progress.activeTaskStep}
          primaryLabel={coachPrimaryLabel(
            activeTaskDef.id,
            progress.activeTaskStep,
          )}
          onBack={handleCoachBack}
          onNext={handleCoachNext}
          onSkip={() => {
            destroyTutorialTour();
            clearActiveTask();
          }}
          onOpenTarget={handleOpenTarget}
        />
      ) : null}
    </>
  );
}

const tutorialApi: TutorialApi = {
  openChecklist: dispatchOpenTutorialChecklist,
  restartTour: dispatchRestartTutorialTour,
};

/**
 * Children render once without depending on tutorial progress.
 * Overlay listens to progress / window events separately.
 */
export function CustomerTutorialProvider({
  children,
  ...overlayProps
}: CustomerTutorialProviderProps) {
  return (
    <TutorialContext.Provider value={tutorialApi}>
      {children}
      {CUSTOMER_TUTORIALS_ENABLED ? (
        <CustomerTutorialOverlay {...overlayProps} />
      ) : null}
    </TutorialContext.Provider>
  );
}
