import {
  AlertTriangle,
  Bell,
  Bot,
  FileText,
  Key,
  Lightbulb,
  Lock,
  LogOut,
  Menu,
  Palette,
  PenLine,
  Radio,
  Search,
  Shield as ShieldIcon,
  Sparkles,
  User,
  UserPlus,
  X,
} from 'lucide-react';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';

import { PropsWithChildren, useEffect, useMemo, useState } from 'react';

import { Link, router, usePage } from '@inertiajs/react';

import { ImpersonationBanner } from '@/Components/admin/ImpersonationBanner';
import AlertBanner from '@/Components/Alerts/AlertBanner';
import { PaymentFailedModal } from '@/Components/billing/PaymentFailedModal';
import { UpgradePrompt } from '@/Components/billing/UpgradePrompt';
import { Logo, TextLogo } from '@/Components/branding/Logo';
import { CommandPalette, useCommandPalette } from '@/Components/command-palette';
import CookieConsentBanner from '@/Components/CookieConsent/CookieConsentBanner';
import { FeedbackWidget } from '@/Components/FeedbackWidget';
import MicroSurveyModal from '@/Components/MicroSurvey/MicroSurveyModal';
import SiteSwitcher from '@/Components/Navigation/SiteSwitcher';
import { NotificationDropdown } from '@/Components/notifications/NotificationDropdown';
import NpsModal from '@/Components/NpsModal';
import ChangelogBanner from '@/Components/Shared/ChangelogBanner';
import GlobalJobNotifications from '@/Components/Shared/GlobalJobNotifications';
import LimitsBar from '@/Components/Shared/LimitsBar';
import SiteSetupChecklist from '@/Components/Shared/SiteSetupChecklist';
import { ThemeToggle } from '@/Components/theme';
import { Button } from '@/Components/ui/button';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/Components/ui/dropdown-menu';
import { ErrorBoundary } from '@/Components/ui/error-boundary';
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from '@/Components/ui/sheet';
import { getVisibleNavItems } from '@/config/navigation';
import { useChangelogBadge } from '@/hooks/useChangelogBadge';
import { usePageEngagement } from '@/hooks/usePageEngagement';
import { useWebVitals } from '@/hooks/useWebVitals';
import { hasAnalyticsConsent, identifyUser, trackEvent } from '@/lib/analytics';
import {
  DUNNING_BANNER_UPDATE_CLICKED,
  LIMIT_HIT,
  REFERRAL_CTA_SHOWN,
  TRIAL_BANNER_DISMISSED,
  TRIAL_BANNER_SHOWN,
  TRIAL_BANNER_UPGRADE_CLICKED,
} from '@/lib/event-catalog';
import type { PageProps } from '@/types';

export default function DashboardLayout({ children }: PropsWithChildren) {
  const page = usePage<PageProps>();
  const {
    auth,
    features,
    sites = [],
    limits,
    active_jobs = [],
    unacknowledged_alerts = [],
    changelog,
    plan = 'free',
    trial,
    nps_prompt = false,
    micro_survey_pending = false,
    grace_period_warning,
    billing_alert,
    flash,
  } = page.props;
  const navItems = getVisibleNavItems(features);
  const { open, setOpen } = useCommandPalette();
  const { hasNew: changelogHasNew } = useChangelogBadge();
  // Fires PAGE_ENGAGEMENT (scroll-depth + active-time) on Inertia navigation
  // and tab/window close. Consent-gated internally.
  usePageEngagement();

  // CHECKOUT-001: Billing alert banner — dismissable per session
  const [_billingAlertDismissed, _setBillingAlertDismissed] = useState(false);

  // BILL-007 / CRO-006: Trial urgency banner — shown throughout trial with escalating CTAs
  const trialDaysRemaining = trial?.daysRemaining ?? null;
  const showTrialBanner =
    features.billing &&
    trial?.active === true &&
    trialDaysRemaining !== null;

  // CRO-006: Loss-aversion CTA escalation: >7d→generic, 3-7d→retention, <3d→data-loss framing
  const trialCtaLabel =
    trialDaysRemaining !== null && trialDaysRemaining < 3
      ? 'Save My Data'
      : trialDaysRemaining !== null && trialDaysRemaining <= 7
        ? 'Keep Pro Access'
        : 'Upgrade Now';

  // CRO-006: Dismiss hidden at ≤3 days — data loss frame must stay visible
  const canDismissTrialBanner = trialDaysRemaining === null || trialDaysRemaining > 3;

  const [trialBannerDismissed, setTrialBannerDismissed] = useState(() => {
    if (typeof window === 'undefined') return false;
    const key = `trial_banner_dismissed_${new Date().toDateString()}`;
    return localStorage.getItem(key) === 'true';
  });

  const dismissTrialBanner = () => {
    const key = `trial_banner_dismissed_${new Date().toDateString()}`;
    if (typeof window !== 'undefined') localStorage.setItem(key, 'true');
    setTrialBannerDismissed(true);
    trackEvent(TRIAL_BANNER_DISMISSED, { days_remaining: trialDaysRemaining ?? 0 });
  };

  // DUNNING-001: Payment failed interceptor modal — show once per session
  const [dunningModalDismissed, setDunningModalDismissed] = useState(() => {
    if (typeof window === 'undefined') return true;
    return sessionStorage.getItem('dunning_modal_dismissed') === 'true';
  });

  const showDunningModal = !!billing_alert && !dunningModalDismissed;

  const dismissDunningModal = () => {
    if (typeof window !== 'undefined') sessionStorage.setItem('dunning_modal_dismissed', 'true');
    setDunningModalDismissed(true);
  };

  useEffect(() => {
    if (showTrialBanner && !trialBannerDismissed) {
      trackEvent(TRIAL_BANNER_SHOWN, { days_remaining: trialDaysRemaining ?? 0 });
    }
  }, [showTrialBanner, trialBannerDismissed, trialDaysRemaining]);

  const currentSite = useMemo(() => {
    if (!page.url) return null;
    const match = page.url.match(/\/sites\/(\d+)/);
    if (!match) return null;
    const siteId = parseInt(match[1], 10);
    return sites.find((s) => s.id === siteId) ?? null;
  }, [page.url, sites]);

  useEffect(() => {
    NProgress.configure({ showSpinner: false });

    const removeStart = router.on('start', () => NProgress.start());
    const removeFinish = router.on('finish', () => {
      NProgress.done();
      // ANA-008: Fire GA4 page_view on SPA navigations
      if (hasAnalyticsConsent()) {
        window.gtag?.('event', 'page_view', {
          page_title: document.title,
          page_path: window.location.pathname,
        });
      }
    });

    return () => {
      removeStart();
      removeFinish();
      NProgress.done();
    };
  }, []);

  // Identify the user in GA4 for cross-session user-level analysis
  useEffect(() => {
    if (!auth.user) return;

    const draftsMax = limits?.max_drafts_per_month ?? 0;
    const sitesMax = limits?.max_sites_per_user ?? 0;
    identifyUser(auth.user.id, {
      plan_tier: plan,
      site_count: sites.length,
      days_since_signup: auth.user.days_since_signup,
      drafts_utilization_pct:
        draftsMax > 0
          ? Math.round(((limits?.drafts_used_this_month ?? 0) / draftsMax) * 100)
          : undefined,
      sites_utilization_pct:
        sitesMax > 0
          ? Math.round(((limits?.sites_used_count ?? 0) / sitesMax) * 100)
          : undefined,
    });
  }, [auth.user, plan, sites.length, limits]);

  // BILL-005: Fire LIMIT_HIT analytics event when a flash upgrade_prompt is received.
  // This captures the highest-intent upgrade moment for PLG conversion tracking.
  useEffect(() => {
    if (!flash?.upgrade_prompt?.upgrade_required) return;
    trackEvent(LIMIT_HIT, {
      limit_key: flash.upgrade_prompt.limit_key,
      plan,
    });
  }, [flash?.upgrade_prompt?.limit_key, flash?.upgrade_prompt?.upgrade_required, plan]);

  // RET-004: Seed localStorage LATEST_KEY when server says there are new changelog entries.
  // This allows the nav badge (useChangelogBadge) to show for authenticated users even
  // before they visit /changelog. We only update if the known latest is older than what
  // the server reports, to avoid overwriting a newer seen timestamp.
  useEffect(() => {
    if (changelog?.has_new && changelog.entries.length > 0) {
      // Sort to find the newest date regardless of server ordering
      const latestDate = [...changelog.entries].map((e) => e.date).sort().at(-1);
      if (!latestDate) return;
      const latestAt = `${latestDate}T00:00:00.000Z`;
      try {
        const currentLatest = localStorage.getItem('rankwiz_changelog_latest_at');
        if (!currentLatest || currentLatest < latestAt) {
          localStorage.setItem('rankwiz_changelog_latest_at', latestAt);
          // Notify all useChangelogBadge instances in this tab that LATEST_KEY changed.
          // Use a distinct event name so the badge hook re-reads localStorage without
          // conflating this with a user visit to /changelog.
          window.dispatchEvent(new Event('changelog-latest-updated'));
        }
      } catch {
        // localStorage unavailable (private browsing, quota exceeded) — ignore
      }
    }
  }, [changelog?.has_new, changelog?.entries]);

  // Report Web Vitals to PostHog when available
  useWebVitals((metric) => {
    if (typeof window !== 'undefined') {
      const posthog = (
        window as Window & {
          posthog?: { capture: (name: string, props: Record<string, unknown>) => void };
        }
      ).posthog;
      if (posthog) {
        posthog.capture('web_vital', {
          name: metric.name,
          value: metric.value,
          rating: metric.rating,
        });
      }
    }
  });

  // Auto-detect and save timezone on first authenticated visit
  useEffect(() => {
    if (!auth.user) return;
    if (localStorage.getItem('timezone_detected')) return;

    const detected = Intl.DateTimeFormat().resolvedOptions().timeZone;
    if (!detected) return;

    fetch('/api/settings', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
      body: JSON.stringify({ key: 'timezone', value: detected }),
    })
      .then(() => {
        localStorage.setItem('timezone_detected', '1');
      })
      .catch(() => {
        // Silent failure — non-critical
      });
  }, [auth.user]);

  return (
    <div className="min-h-screen bg-background flex flex-col">
      <ImpersonationBanner />

      {/* BILL-004: Grace period warning banner (hidden when dunning banner is active) */}
      {grace_period_warning && !billing_alert && (
        <div className="bg-red-50 dark:bg-red-950 border-b border-red-200 dark:border-red-800 px-4 py-3 flex items-center justify-between">
          <span className="text-sm text-red-900 dark:text-red-100">
            Your payment is past due. Access will be restricted in{' '}
            <strong>
              {grace_period_warning.days_remaining} day
              {grace_period_warning.days_remaining !== 1 ? 's' : ''}
            </strong>
            . Please update your payment method.
          </span>
          <Link
            href={route('billing.index')}
            className="text-sm font-medium text-red-900 dark:text-red-100 underline underline-offset-4 hover:text-red-700 dark:hover:text-red-300 shrink-0 ml-4"
          >
            Update Payment
          </Link>
        </div>
      )}

      {/* DUNNING-001: Persistent dunning warning banner (visible even after modal dismiss) */}
      {billing_alert && (
        <div className="bg-red-50 dark:bg-red-950 border-b border-red-200 dark:border-red-800 px-4 py-2.5 flex items-center justify-between">
          <span className="text-sm text-red-900 dark:text-red-100">
            <AlertTriangle className="inline h-4 w-4 mr-1.5 -mt-0.5" />
            Your payment is past due
            {billing_alert.days_in_dunning > 0 && (
              <>
                {' '}
                ({billing_alert.days_in_dunning} day
                {billing_alert.days_in_dunning !== 1 ? 's' : ''})
              </>
            )}
            . Update your payment method to keep Pro features.
          </span>
          <a
            href={billing_alert.portal_url}
            onClick={() =>
              trackEvent(DUNNING_BANNER_UPDATE_CLICKED, {
                days_in_dunning: billing_alert.days_in_dunning,
              })
            }
            className="text-sm font-semibold text-red-900 dark:text-red-100 underline underline-offset-4 hover:text-red-700 dark:hover:text-red-300 shrink-0 ml-4"
          >
            Update Payment
          </a>
        </div>
      )}

      {/* BILL-007 / CRO-006: Trial urgency banner — escalating CTAs by days remaining */}
      {showTrialBanner && !trialBannerDismissed && (
        <div className="bg-amber-50 dark:bg-amber-950 border-b border-amber-200 dark:border-amber-800 px-4 py-3 flex items-center justify-between">
          <span className="text-sm text-amber-900 dark:text-amber-100">
            {trialDaysRemaining !== null && trialDaysRemaining < 3 ? (
              <>
                Your Pro trial expires in{' '}
                <strong>
                  {trialDaysRemaining} day{trialDaysRemaining !== 1 ? 's' : ''}
                </strong>
                . Your analyses, AI drafts, and Pro features will be removed.
              </>
            ) : (
              <>
                Your Pro trial ends in{' '}
                <strong>
                  {trialDaysRemaining} day{trialDaysRemaining !== 1 ? 's' : ''}
                </strong>
                . Upgrade to keep your analyses, AI drafts, and all Pro features.
              </>
            )}
          </span>
          <div className="flex items-center gap-3 ml-4 shrink-0">
            <Link
              href={route('pricing')}
              onClick={() =>
                trackEvent(TRIAL_BANNER_UPGRADE_CLICKED, {
                  days_remaining: trialDaysRemaining ?? 0,
                })
              }
              className="text-sm font-semibold text-amber-900 dark:text-amber-100 underline"
            >
              {trialCtaLabel}
            </Link>
            {canDismissTrialBanner && (
              <button
                onClick={dismissTrialBanner}
                className="text-amber-700 dark:text-amber-300 hover:text-amber-900 dark:hover:text-amber-100"
                aria-label="Dismiss trial banner"
              >
                <X className="h-4 w-4" />
              </button>
            )}
          </div>
        </div>
      )}

      <a
        href="#main-content"
        className="sr-only focus-visible:not-sr-only focus-visible:absolute focus-visible:z-100 focus-visible:bg-background focus-visible:px-4 focus-visible:py-2 focus-visible:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
      >
        Skip to main content
      </a>

      {/* Desktop Navigation */}
      <header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
        <div className="container flex h-16 items-center justify-between">
          {/* Left side - Logo and Nav */}
          <div className="flex items-center gap-6">
            <Link href="/dashboard" className="flex items-center gap-2">
              <Logo className="h-8 w-8" />
              <TextLogo className="hidden sm:block text-lg font-bold" />
            </Link>

            {/* Site Switcher */}
            {sites.length > 0 && <SiteSwitcher sites={sites} currentSiteId={currentSite?.id} />}

            {/* Desktop Nav */}
            <nav aria-label="Main navigation" className="hidden md:flex items-center gap-1">
              {navItems.map((item) => (
                <Button
                  key={item.href}
                  variant="ghost"
                  size="sm"
                  asChild
                  className="text-muted-foreground hover:text-foreground"
                >
                  <Link href={item.href}>
                    <item.icon className="mr-2 h-4 w-4" />
                    {item.label}
                  </Link>
                </Button>
              ))}
            </nav>
          </div>

          {/* Right side - Quick actions, Theme toggle and User menu */}
          <div className="flex items-center gap-2">
            {currentSite && (
              <Button variant="outline" size="sm" asChild className="hidden sm:inline-flex">
                <Link href={route('content-briefs.index', currentSite.id)}>
                  <PenLine className="mr-2 h-4 w-4" />
                  New Brief
                </Link>
              </Button>
            )}
            <ThemeToggle />
            {features.notifications && <NotificationDropdown />}

            {/* User Menu */}
            <DropdownMenu>
              <DropdownMenuTrigger asChild>
                <Button
                  variant="ghost"
                  className="relative h-9 w-9 rounded-full"
                  aria-label="User menu"
                >
                  <div className="flex h-9 w-9 items-center justify-center rounded-full bg-primary/10 text-primary">
                    {auth.user!.name.charAt(0).toUpperCase()}
                  </div>
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent className="w-56" align="end" forceMount>
                <DropdownMenuLabel className="font-normal">
                  <div className="flex flex-col space-y-1">
                    <p className="text-sm font-medium leading-none">{auth.user!.name}</p>
                    <p className="text-xs leading-none text-muted-foreground">{auth.user!.email}</p>
                  </div>
                </DropdownMenuLabel>
                <DropdownMenuSeparator />
                <DropdownMenuItem asChild>
                  <Link href="/profile" className="cursor-pointer">
                    <User className="mr-2 h-4 w-4" />
                    Profile
                  </Link>
                </DropdownMenuItem>
                {features.apiTokens && (
                  <DropdownMenuItem asChild>
                    <Link href="/settings/tokens" className="cursor-pointer">
                      <Key className="mr-2 h-4 w-4" />
                      API Tokens
                    </Link>
                  </DropdownMenuItem>
                )}
                {features.twoFactor && (
                  <DropdownMenuItem asChild>
                    <Link href="/settings/security" className="cursor-pointer">
                      <ShieldIcon className="mr-2 h-4 w-4" />
                      Security
                    </Link>
                  </DropdownMenuItem>
                )}
                {(plan === 'team' || plan === 'enterprise') && (
                  <DropdownMenuItem asChild>
                    <Link href={route('settings.branding')} className="cursor-pointer">
                      <Palette className="mr-2 h-4 w-4" />
                      Branding
                    </Link>
                  </DropdownMenuItem>
                )}
                <DropdownMenuItem asChild>
                  <Link href={route('privacy-settings.show')} className="cursor-pointer">
                    <Lock className="mr-2 h-4 w-4" />
                    Privacy
                  </Link>
                </DropdownMenuItem>
                <DropdownMenuItem asChild>
                  <Link href={route('settings.ai')} className="cursor-pointer">
                    <Bot className="mr-2 h-4 w-4" />
                    AI Settings
                  </Link>
                </DropdownMenuItem>
                <DropdownMenuItem asChild>
                  <Link href={route('settings.serp')} className="cursor-pointer">
                    <Search className="mr-2 h-4 w-4" />
                    SERP API Key
                  </Link>
                </DropdownMenuItem>
                {features.notifications && (currentSite || sites.length > 0) && (
                  <DropdownMenuItem asChild>
                    <Link
                      href={route('notification-settings.show', (currentSite ?? sites[0]).id)}
                      className="cursor-pointer"
                    >
                      <Bell className="mr-2 h-4 w-4" />
                      Notifications
                    </Link>
                  </DropdownMenuItem>
                )}
                {features.webhooks && (
                  <DropdownMenuItem asChild>
                    <Link href="/settings/webhooks" className="cursor-pointer">
                      <Radio className="mr-2 h-4 w-4" />
                      Webhooks
                    </Link>
                  </DropdownMenuItem>
                )}
                {features.apiDocs && (
                  <DropdownMenuItem asChild>
                    <a
                      href="/docs"
                      target="_blank"
                      rel="noopener noreferrer"
                      className="cursor-pointer"
                    >
                      <FileText className="mr-2 h-4 w-4" />
                      API Docs
                    </a>
                  </DropdownMenuItem>
                )}
                <DropdownMenuItem asChild>
                  <Link
                    href={route('settings.referral')}
                    className="cursor-pointer"
                    onClick={() => trackEvent(REFERRAL_CTA_SHOWN, { source: 'user_menu' })}
                  >
                    <UserPlus className="mr-2 h-4 w-4" />
                    Refer a Friend
                  </Link>
                </DropdownMenuItem>
                <DropdownMenuItem asChild>
                  <Link href="/feature-requests" className="cursor-pointer">
                    <Lightbulb className="mr-2 h-4 w-4" />
                    Feature Requests
                  </Link>
                </DropdownMenuItem>
                <DropdownMenuItem asChild>
                  <Link href={route('changelog.index')} className="cursor-pointer">
                    <Sparkles className="mr-2 h-4 w-4" />
                    What&apos;s New
                    {changelogHasNew && (
                      <span
                        className="ml-auto h-2 w-2 rounded-full bg-primary"
                        aria-label="New changelog entries"
                      />
                    )}
                  </Link>
                </DropdownMenuItem>
                {auth.user?.is_admin && features.admin && (
                  <>
                    <DropdownMenuSeparator />
                    <DropdownMenuItem asChild>
                      <Link href="/admin" className="cursor-pointer">
                        <ShieldIcon className="mr-2 h-4 w-4" />
                        Admin Panel
                      </Link>
                    </DropdownMenuItem>
                  </>
                )}
                <DropdownMenuSeparator />
                <DropdownMenuItem asChild>
                  <Link
                    href={route('logout')}
                    method="post"
                    as="button"
                    className="w-full cursor-pointer text-destructive focus:text-destructive"
                  >
                    <LogOut className="mr-2 h-4 w-4" />
                    Log out
                  </Link>
                </DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>

            {/* Mobile Menu */}
            <Sheet>
              <SheetTrigger asChild className="md:hidden">
                <Button variant="ghost" size="icon" aria-label="Toggle navigation menu">
                  <Menu className="h-5 w-5" />
                </Button>
              </SheetTrigger>
              <SheetContent side="left">
                <SheetHeader>
                  <SheetTitle className="flex items-center gap-2">
                    <Logo className="h-6 w-6" />
                    <TextLogo />
                  </SheetTitle>
                  <SheetDescription className="sr-only">Navigation menu</SheetDescription>
                </SheetHeader>
                <nav aria-label="Main navigation" className="mt-8 flex flex-col gap-2">
                  {navItems.map((item) => (
                    <Button key={item.href} variant="ghost" className="justify-start" asChild>
                      <Link href={item.href}>
                        <item.icon className="mr-2 h-4 w-4" />
                        {item.label}
                      </Link>
                    </Button>
                  ))}
                </nav>
              </SheetContent>
            </Sheet>
          </div>
        </div>
      </header>

      {/* Global job notifications */}
      <GlobalJobNotifications jobs={active_jobs} />

      {/* Limits usage bar + Site setup checklist + Alert Banner */}
      {auth.user && (
        <div className="container pt-4 flex flex-col gap-3">
          {limits &&
            (() => {
              const sitesPct =
                limits.max_sites_per_user > 0
                  ? (sites.length / limits.max_sites_per_user) * 100
                  : 0;
              const draftsPct =
                limits.max_drafts_per_month !== null && limits.max_drafts_per_month > 0
                  ? (limits.drafts_used_this_month / limits.max_drafts_per_month) * 100
                  : 0;
              const sitesAtLimit = sites.length >= limits.max_sites_per_user;
              const draftsAtLimit =
                limits.max_drafts_per_month !== null &&
                limits.drafts_used_this_month >= limits.max_drafts_per_month;
              const showLimitsBar = sitesPct > 70 || draftsPct > 70;
              return (
                <>
                  {showLimitsBar && (
                    <div className="flex gap-4">
                      {sitesPct > 70 && (
                        <LimitsBar
                          label="Sites"
                          current={sites.length}
                          max={limits.max_sites_per_user}
                          showUpgrade={features.billing && !sitesAtLimit}
                        />
                      )}
                      {limits.max_drafts_per_month !== null && draftsPct > 70 && (
                        <LimitsBar
                          label="AI Drafts"
                          current={limits.drafts_used_this_month}
                          max={limits.max_drafts_per_month}
                          showUpgrade={features.billing && !draftsAtLimit}
                        />
                      )}
                    </div>
                  )}
                  {sitesAtLimit && (
                    <UpgradePrompt
                      limitType="sites"
                      currentUsage={sites.length}
                      maxUsage={limits.max_sites_per_user}
                      proLimit={limits.pro_sites}
                    />
                  )}
                  {draftsAtLimit && limits.max_drafts_per_month !== null && (
                    <UpgradePrompt
                      limitType="drafts"
                      currentUsage={limits.drafts_used_this_month}
                      maxUsage={limits.max_drafts_per_month}
                      proLimit={limits.pro_drafts_per_month}
                    />
                  )}
                </>
              );
            })()}
          {currentSite && <SiteSetupChecklist site={currentSite} />}
          {currentSite && unacknowledged_alerts.length > 0 && (
            <AlertBanner
              alerts={unacknowledged_alerts.filter((alert) => alert.site_id === currentSite.id)}
              siteId={currentSite.id}
            />
          )}
          {changelog && <ChangelogBanner changelog={changelog} />}
        </div>
      )}

      {/* Main Content */}
      <main id="main-content" className="flex-1">
        <ErrorBoundary>{children}</ErrorBoundary>
      </main>

      <footer className="border-t mt-auto py-6">
        <div className="container flex flex-col sm:flex-row items-center justify-between gap-4 text-sm text-muted-foreground">
          <p>&copy; {new Date().getFullYear()} RankWiz</p>
          <div className="flex items-center gap-4">
            <a href="mailto:support@rankwiz.ai" className="hover:text-foreground transition-colors">
              Support
            </a>
            <a
              href={`mailto:feedback@rankwiz.ai?subject=${encodeURIComponent(`[RankWiz Feedback] ${currentSite?.name ?? 'General'}`)}&body=${encodeURIComponent(`Site: ${currentSite?.name ?? 'N/A'} (${currentSite?.domain ?? 'N/A'})\nPage: ${page.url}\n\n--- Your feedback below ---\n\n`)}`}
              className="hover:text-foreground transition-colors"
            >
              Send Feedback
            </a>
          </div>
        </div>
      </footer>

      <CommandPalette open={open} onOpenChange={setOpen} />
      <NpsModal nps_prompt={nps_prompt} />
      <MicroSurveyModal micro_survey_pending={micro_survey_pending} />
      <CookieConsentBanner />
      <FeedbackWidget />

      {/* DUNNING-001: Payment failed interceptor modal */}
      {billing_alert && (
        <PaymentFailedModal
          open={showDunningModal}
          onDismiss={dismissDunningModal}
          portalUrl={billing_alert.portal_url}
          daysInDunning={billing_alert.days_in_dunning}
        />
      )}
    </div>
  );
}
