import { AppLayout, type SidebarItem } from "@/components/AppLayout";
import { useDisclosure } from "@mantine/hooks";
import {
  Home,
  Layers,
  Loader2,
  // MapPin,
  Package,
  Receipt,
  Settings,
} from "lucide-react";
import { useEffect, useRef } from "react";
import {
  Navigate,
  Outlet,
  Route,
  Routes,
  useLocation,
  useNavigate,
} from "react-router-dom";

import OnboardingResumeBanner, {
  AccountReviewBanner,
} from "./components/onboarding/OnboardingResumeBanner";
import OnboardingWizardDialog from "./components/onboarding/OnboardingWizardDialog";
import { ApiErrorModal } from "./components/errors/ApiErrorModal";
import useAuth from "./hooks/useAuth";
import { useIdentify } from "./lib/posthog";
import {
  startTokenRefreshScheduler,
  stopTokenRefreshScheduler,
} from "./utils/refreshScheduler";
import EDRFreightLandingPage from "./pages/EDRFreightLandingPage";
import MyPortalPage from "./pages/MyPortalPage";
import MySignaturePage from "./pages/MySignaturePage";
import SettingsPage from "./pages/SettingsPage";
import ForgotPasswordPage from "./pages/accounts/ForgotPasswordPage";
import ResetPasswordLinkPage from "./pages/accounts/ResetPasswordLinkPage";
import LoginPage from "./pages/accounts/LoginPage";
import SetPasswordPage from "./pages/accounts/SetPasswordPage";
import SignupPage from "./pages/accounts/SignupPage";
import VerificationOtpPage from "./pages/accounts/VerificationOtpPage";
import InvoiceDetailPage from "./pages/billing/InvoiceDetailPage";
import InvoicesList from "./pages/billing/InvoicesList";
import BookingContractPage from "./pages/bookings/BookingContractPage";
import BookingDetailPage from "./pages/bookings/BookingDetailPage";
import BookingsListPage from "./pages/bookings/BookingsListPage";
import EditBookingPage from "./pages/bookings/EditBookingPage";
import ContractClearanceFlow from "./pages/contracts/ContractClearanceFlow";
import ContractDetailPage from "./pages/contracts/ContractDetailPage";
import ContractViewPage from "./pages/contracts/ContractViewPage";
import ContractsList from "./pages/contracts/ContractsList";
import NewContractPage from "./pages/contracts/NewContractPage";
import NewShipmentPage from "./pages/contracts/NewShipmentPage";
import NewShipmentRequestPage from "./pages/contracts/NewShipmentRequestPage";
import CheckPaymentPage from "./pages/payments/CheckPaymentPage";
import PaymentFailurePage from "./pages/payments/PaymentFailurePage";
import PaymentSuccessPage from "./pages/payments/PaymentSuccessPage";
import TrackingPage from "./pages/tracking/TrackingPage";

function FullScreenSpinner() {
  return (
    <div className="flex items-center justify-center h-screen">
      <Loader2 className="animate-spin text-primary" />
    </div>
  );
}

function LogoutHandler() {
  const { logout } = useAuth();
  const navigate = useNavigate();
  const hasRun = useRef(false);

  useEffect(() => {
    if (hasRun.current) return;
    hasRun.current = true;
    logout().then(() => navigate("/login", { replace: true }));
  }, []);

  return <FullScreenSpinner />;
}

/** Blocks unauthenticated users; renders children only with a valid session. */
function RequireAuth() {
  const { isPending, isAuthenticated } = useAuth();
  const location = useLocation();

  if (isPending) return <FullScreenSpinner />;
  if (!isAuthenticated)
    return <Navigate to="/login" replace state={{ from: location }} />;
  return <Outlet />;
}

/**
 * Waits for the company query so downstream routes can rely on it being
 * resolved. Onboarding is enforced by OnboardingGate, not here.
 */
function RequireCompany() {
  const { customerQuery } = useAuth();

  if (customerQuery.isPending) return <FullScreenSpinner />;
  return <Outlet />;
}

/**
 * Routes an un-onboarded user may still visit. The wizard auto-opens but is
 * dismissable, so they can browse these freely; any other route forces the
 * wizard back open and bounces them home.
 */
const ONBOARDING_ALLOWED_PATHS = ["/portal", "/signature"];

function isOnboardingAllowedPath(pathname: string): boolean {
  const path = pathname.toLowerCase();
  return ONBOARDING_ALLOWED_PATHS.some(
    (p) => path === p || path.startsWith(p + "/"),
  );
}

/**
 * Enforces first-run onboarding. The home (dashboard) and signature pages stay
 * reachable while onboarding is incomplete; the wizard auto-opens on login but
 * can be dismissed to use those pages. Visiting any other page bounces back to
 * home and re-opens the wizard. New users (no company yet) are treated the same
 * as users who haven't completed onboarding.
 */
function OnboardingGate() {
  const { company, onboardingCompleted } = useAuth();
  const location = useLocation();

  const needsOnboarding = !company || !onboardingCompleted;
  const allowedHere = isOnboardingAllowedPath(location.pathname);

  // Open by default while onboarding is pending (covers the login case).
  const [wizardOpen, { open: openWizard, close: closeWizard }] =
    useDisclosure(false);

  // Re-evaluate on every navigation: force the wizard open on blocked routes,
  // and auto-open on first arrival while onboarding is pending.
  useEffect(() => {
    if (needsOnboarding && !allowedHere) {
      openWizard();
    }
  }, [needsOnboarding, allowedHere, location.pathname, openWizard]);

  // Auto-open once when onboarding becomes/loads as pending (login).
  const autoOpenedRef = useRef(false);
  useEffect(() => {
    if (needsOnboarding && !autoOpenedRef.current) {
      autoOpenedRef.current = true;
      openWizard();
    }
    if (!needsOnboarding) autoOpenedRef.current = false;
  }, [needsOnboarding, openWizard]);

  if (needsOnboarding && !allowedHere) {
    return <Navigate to="/portal" replace />;
  }

  return (
    <>
      {needsOnboarding && <OnboardingResumeBanner onResume={openWizard} />}
      {!needsOnboarding && <AccountReviewBanner />}
      <Outlet />
      <OnboardingWizardDialog
        opened={needsOnboarding && wizardOpen}
        onClose={closeWizard}
      />
    </>
  );
}

/** Keeps authenticated users off the login/signup pages. */
function RedirectIfAuthed() {
  const { isPending, isAuthenticated } = useAuth();

  if (isPending) return <FullScreenSpinner />;
  if (isAuthenticated) return <Navigate to="/portal" replace />;
  return <Outlet />;
}

/** Landing page for visitors; authenticated users go straight to the portal. */
function LandingRoute() {
  const { isPending, isAuthenticated } = useAuth();

  if (isPending) return <FullScreenSpinner />;
  if (isAuthenticated) return <Navigate to="/portal" replace />;
  return <EDRFreightLandingPage />;
}

const sidebarItems: SidebarItem[] = [
  { label: "Home", href: "/portal", icon: <Home size={18} /> },
  {
    label: "Contracts",
    href: "/contracts",
    icon: <Layers size={18} />,
  },
  {
    label: "Bookings",
    href: "/bookings",
    icon: <Package size={18} />,
  },
  // {
  //   label: "Tracking",
  //   href: "/tracking",
  //   icon: <MapPin size={18} />,
  // },
  {
    label: "Invoices",
    href: "/billing",
    icon: <Receipt size={18} />,
  },
  {
    section: "Account",
    label: "Settings",
    href: "/settings",
    icon: <Settings size={18} />,
  },
];

const App = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const {
    user,
    company,
    companyType,
    createProfile,
    reapplyProfile,
    isAuthenticated,
  } = useAuth();

  // Attribute replays and exceptions to the signed-in user (id/org only).
  useIdentify(user, company);

  // Keep the server session alive while a user is logged in. Runs after
  // login, signup, and page-reload bootstrap alike.
  useEffect(() => {
    if (!isAuthenticated) {
      stopTokenRefreshScheduler();
      return;
    }

    startTokenRefreshScheduler();
    return stopTokenRefreshScheduler;
  }, [isAuthenticated]);

  const displayName = user?.name?.en || user?.username || user?.email || "User";
  const userEmail = user?.email;
  const companyProfiles = company?.company?.companyProfiles ?? [];

  return (
    <>
      {/* Global API error modal — shows the server's actual error message for
          every failed request (suppressed on onboarding/auth pages). */}
      <ApiErrorModal />
    <Routes>
      {/* Public routes */}
      <Route index element={<LandingRoute />} />
      <Route path="/logout" element={<LogoutHandler />} />
      <Route
        path="/booking/check-status/:orderId"
        element={<CheckPaymentPage />}
      />
      {/* Payment provider browser redirects (PAYMENT_RETURN_URL / PAYMENT_FAILURE_URL) */}
      <Route path="/payment/success" element={<PaymentSuccessPage />} />
      <Route path="/payment/failure" element={<PaymentFailurePage />} />

      {/* Auth pages — inaccessible once logged in */}
      <Route element={<RedirectIfAuthed />}>
        <Route path="/login" element={<LoginPage />} />
        <Route path="/signup" element={<SignupPage />} />
        <Route path="/forgot-password" element={<ForgotPasswordPage />} />
      </Route>

      {/* Staff-issued reset links land here. Deliberately outside
          RedirectIfAuthed: a customer with a stale session still needs the link
          to work, and the token — not the session — is what authorises it. */}
      <Route path="/reset-password" element={<ResetPasswordLinkPage />} />

      {/* Signup-flow pages; reached while a session already exists */}
      <Route path="/otp" element={<VerificationOtpPage />} />
      <Route path="/set-password" element={<SetPasswordPage />} />

      <Route element={<RequireAuth />}>
        <Route element={<RequireCompany />}>
          <Route
            element={
              <AppLayout
                title="EDR Freight"
                sidebarItems={sidebarItems}
                activeHref={location.pathname}
                onNavigate={navigate}
                enableThemeToggle
                userName={displayName}
                userEmail={userEmail}
                companyProfiles={companyProfiles}
                companyType={companyType}
                onCreateProfile={createProfile}
                onReapplyProfile={reapplyProfile}
              >
                <OnboardingGate />
              </AppLayout>
            }
          >
            <Route path="/portal" element={<MyPortalPage />} />
            {/* Bookings are created against a contract, but the full list is
                browsable here. New-booking entry still routes via a contract. */}
            <Route path="/bookings" element={<BookingsListPage />} />
            <Route
              path="/bookings/new"
              element={<Navigate to="/contracts/new" replace />}
            />
            <Route path="/bookings/:id/edit" element={<EditBookingPage />} />
            <Route path="/bookings/:id" element={<BookingDetailPage />} />
            <Route
              path="/bookings/:id/contract"
              element={<BookingContractPage />}
            />
            <Route path="/contracts" element={<ContractsList />} />
            <Route path="/contracts/new" element={<NewContractPage />} />
            <Route
              path="/contracts/:id/edit"
              element={<NewContractPage mode="edit" />}
            />
            <Route
              path="/contracts/:id/shipment-requests/new"
              element={<NewShipmentRequestPage />}
            />
            <Route
              path="/contracts/:id/bookings/new"
              element={<NewShipmentPage />}
            />
            {/* Completion of an initiated (bare) booking after per-booking
                clearance — same form, submits to the complete endpoint. */}
            <Route
              path="/contracts/:id/bookings/:bookingId/complete"
              element={<NewShipmentPage />}
            />
            <Route
              path="/contracts/:id/clearance"
              element={<ContractClearanceFlow />}
            />
            <Route
              path="/contracts/:id/view"
              element={<ContractViewPage />}
            />
            <Route path="/contracts/:id" element={<ContractDetailPage />} />
            <Route path="/tracking" element={<TrackingPage />} />
            <Route path="/billing" element={<InvoicesList />} />
            <Route path="/billing/:id" element={<InvoiceDetailPage />} />
            {/* Profile was merged into Settings — keep old links working. */}
            <Route
              path="/profile"
              element={<Navigate to="/settings" replace />}
            />
            <Route path="/signature" element={<MySignaturePage />} />
            <Route path="/settings" element={<SettingsPage />} />
          </Route>
        </Route>
      </Route>

      <Route path="*" element={<Navigate to="/" replace />} />
    </Routes>
    </>
  );
};

export default App;
