'use client';

import { useState, useEffect, useCallback, useRef } from 'react';
import { usePathname, useRouter } from 'next/navigation';
import Sidebar from './Sidebar';
import Topbar from './Topbar';
import AlertOverlay from '@client/components/AlertOverlay';
import { LiveCountsProvider, useLiveCounts } from '@client/contexts/LiveCountsContext';
import { PageHeaderProvider, usePageHeader } from '@client/contexts/PageHeaderContext';
import { BrandingProvider } from '@client/contexts/BrandingContext';
import { PlanFeaturesProvider } from '@client/contexts/PlanFeaturesContext';
import { useAuth } from '@client/contexts/AuthContext';
import { useLanguage } from '@client/contexts/LanguageContext';
import type { AlertSettings } from '@client/api/alert-settings';
import { toast } from 'sonner';

interface LiveAlert {
  id: string;
  type: 'order' | 'booking' | 'escalation';
  title: string;
  subtitle: string;
  details: string[];
  timestamp: string;
  countdown: number;
}

const DEFAULT_ALERT_SETTINGS: AlertSettings = {
  soundEnabled: true,
  volume: 70,
  autoDismiss: 30,
  showOrders: true,
  showBookings: true,
  showAiEscalations: true,
  browserNotifications: false,
};

const TRIAL_EXEMPT = ['/billing', '/onboarding', '/sign-out', '/logout'];

function getCookie(name: string): string | null {
  if (typeof document === 'undefined') return null;
  const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  const match = document.cookie.match(new RegExp('(^| )' + escaped + '=([^;]+)'));
  return match ? decodeURIComponent(match[2]) : null;
}

function AppLayoutInner({ children }: { children: React.ReactNode }) {
  const [isCollapsed, setIsCollapsed] = useState(false);
  const [mobileOpen, setMobileOpen] = useState(false);
  const [isAdminMode, setIsAdminMode] = useState(false);
  const [impersonatingName, setImpersonatingName] = useState<string | null>(null);
  const [impersonatingRestaurantId, setImpersonatingRestaurantId] = useState<string | null>(null);
  const [exitingImpersonation, setExitingImpersonation] = useState(false);
  const pathname = usePathname();
  const router = useRouter();
  const { title: pageTitle, subtitle: pageSubtitle } = usePageHeader();
  const { onAlert } = useLiveCounts();
  const { restaurantId, userRecord } = useAuth();
  const [liveAlerts, setLiveAlerts] = useState<LiveAlert[]>([]);
  const alertIdCounter = useRef(0);
  const alertSettingsRef = useRef<AlertSettings>(DEFAULT_ALERT_SETTINGS);

  useEffect(() => {
    const name = getCookie('impersonating_name');
    const rid = getCookie('impersonating_restaurant_id');
    setImpersonatingName(name);
    setImpersonatingRestaurantId(rid);
  }, [pathname]);

  useEffect(() => {
    if (!restaurantId) return;
    const userRole = userRecord?.role;
    if (userRole === 'superadmin' || userRole === 'support') return;
    if (TRIAL_EXEMPT.some(p => pathname.startsWith(p))) return;
    fetch('/api/billing')
      .then(r => r.ok ? r.json() : null)
      .then(data => {
        const sub = data?.subscription;
        if (!sub) return;
        const isTrialExpired =
          sub.status === 'trial' &&
          sub.trial_end &&
          new Date(sub.trial_end) < new Date();
        const isInactive = sub.status === 'inactive' || sub.status === 'cancelled';
        if (isTrialExpired || isInactive) {
          router.replace('/billing?reason=trial_expired');
        }
      })
      .catch(() => {});
  }, [restaurantId, userRecord, pathname, router]);

  useEffect(() => {
    fetch('/api/alert-settings', { credentials: 'include' })
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (d?.settings) alertSettingsRef.current = d.settings; })
      .catch(() => {});
  }, []);

  useEffect(() => {
    const unsubscribe = onAlert((type, newCount, prevCount) => {
      const s = alertSettingsRef.current;
      if (type === 'order' && !s.showOrders) return;
      if (type === 'booking' && !s.showBookings) return;

      const diff = newCount - prevCount;
      const now = new Date();
      const ts = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
      const id = `live-alert-${++alertIdCounter.current}`;

      const _t = tRef.current;
      const alert: LiveAlert = type === 'order'
        ? {
            id,
            type: 'order',
            title: `${diff} ${_t('alerts.newOrder', 'New Order')}${diff > 1 ? 's' : ''}`,
            subtitle: _t('alerts.justPlaced', 'Just placed'),
            details: [`${diff} ${_t('alerts.pendingOrders', 'pending order(s) awaiting confirmation')}`],
            timestamp: ts,
            countdown: s.autoDismiss,
          }
        : {
            id,
            type: 'booking',
            title: `${diff} ${_t('alerts.newBooking', 'New Booking')}${diff > 1 ? 's' : ''}`,
            subtitle: _t('alerts.justReceived', 'Just received'),
            details: [`${diff} ${_t('alerts.newReservations', 'new reservation(s) to review')}`],
            timestamp: ts,
            countdown: s.autoDismiss,
          };

      setLiveAlerts(prev => [...prev, alert]);
    });
    return unsubscribe;
  }, [onAlert]);

  useEffect(() => {
    if (!restaurantId) return;
    let aborted = false;
    const controller = new AbortController();
    const connect = () => {
      fetch('/api/alerts/escalations', { signal: controller.signal, headers: { 'Accept': 'text/event-stream' } }).then(async res => {
        if (!res.body || aborted) return;
        const reader = res.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';
        while (!aborted) {
          const { done, value } = await reader.read();
          if (done) break;
          buffer += decoder.decode(value, { stream: true });
          const lines = buffer.split('\n');
          buffer = lines.pop() || '';
          for (const line of lines) {
            if (!line.startsWith('data: ')) continue;
            try {
              const data = JSON.parse(line.slice(6));
              const s = alertSettingsRef.current;
              if (!s.showAiEscalations) continue;
              const ts = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
              const id = `escalation-${++alertIdCounter.current}`;
              const _t2 = tRef.current;
              setLiveAlerts(prev => [...prev, {
                id,
                type: 'escalation',
                title: _t2('alerts.aiEscalation', 'AI Escalation'),
                subtitle: data.reason || _t2('alerts.needsHumanAttention', 'Needs human attention'),
                details: [data.customerName ? `${_t2('alerts.customer', 'Customer')}: ${data.customerName}` : _t2('alerts.conversationRequiresIntervention', 'A conversation requires human intervention')],
                timestamp: ts,
                countdown: s.autoDismiss,
              }]);
            } catch {}
          }
        }
        if (!aborted) setTimeout(connect, 5000);
      }).catch(() => {
        if (!aborted) setTimeout(connect, 5000);
      });
    };
    connect();
    return () => { aborted = true; controller.abort(); };
  }, [restaurantId]);

  const handleDismissAlert = useCallback((id: string) => {
    setLiveAlerts(prev => prev.filter(a => a.id !== id));
  }, []);

  const handleAcceptAlert = useCallback((id: string) => {
    setLiveAlerts(prev => prev.filter(a => a.id !== id));
  }, []);

  const handleExitImpersonation = useCallback(async () => {
    setExitingImpersonation(true);
    try {
      const res = await fetch('/api/admin/support/impersonate/exit', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ restaurantId: impersonatingRestaurantId }),
      });
      if (!res.ok) throw new Error('Exit failed');
      const data = await res.json() as { restaurantId?: string };
      const targetId = data.restaurantId ?? impersonatingRestaurantId;
      setImpersonatingName(null);
      setImpersonatingRestaurantId(null);
      router.push(targetId ? `/admin/restaurants/${targetId}` : '/admin/restaurants');
    } catch {
      toast.error(tRef.current('appLayout.exitImpersonationFailed', 'Failed to exit impersonation'));
      setExitingImpersonation(false);
    }
  }, [impersonatingRestaurantId, router]);

  const isAdmin = userRecord?.role === 'superadmin' || userRecord?.role === 'support';
  const isAdminPath = pathname?.startsWith('/admin');
  const effectiveAdminMode = isAdminPath || isAdminMode;
  const { isRTL, t } = useLanguage();
  const tRef = useRef(t);
  useEffect(() => { tRef.current = t; }, [t]);

  return (
    <div className="flex h-screen overflow-hidden" style={{ backgroundColor: 'hsl(var(--background))' }}>
      {mobileOpen && (
        <div
          className="fixed inset-0 bg-black/40 z-30 lg:hidden"
          onClick={() => setMobileOpen(false)}
        />
      )}

      <div className="hidden lg:flex shrink-0 sidebar-left" style={{ transition: 'width 300ms ease', width: isCollapsed ? '64px' : '240px' }}>
        <Sidebar
          isCollapsed={isCollapsed}
          onToggle={() => setIsCollapsed(!isCollapsed)}
          isAdminMode={effectiveAdminMode}
          onToggleAdminMode={isAdmin ? () => setIsAdminMode(!isAdminMode) : undefined}
          impersonatingName={impersonatingName ?? undefined}
          onExitImpersonation={impersonatingName ? handleExitImpersonation : undefined}
          exitingImpersonation={exitingImpersonation}
        />
      </div>

      <div
        className={`fixed inset-y-0 z-40 lg:hidden sidebar-left transition-transform duration-300 ${isRTL ? 'right-0' : 'left-0'} ${mobileOpen ? 'translate-x-0' : isRTL ? 'translate-x-full' : '-translate-x-full'}`}
        style={{ width: '240px' }}
      >
        <Sidebar
          isCollapsed={false}
          onToggle={() => setMobileOpen(false)}
          isAdminMode={effectiveAdminMode}
          onToggleAdminMode={isAdmin ? () => setIsAdminMode(!isAdminMode) : undefined}
          impersonatingName={impersonatingName ?? undefined}
          onExitImpersonation={impersonatingName ? handleExitImpersonation : undefined}
          exitingImpersonation={exitingImpersonation}
        />
      </div>

      <div className="flex flex-col flex-1 min-w-0 overflow-hidden">
        <Topbar
          onMobileMenuToggle={() => setMobileOpen(true)}
          pageTitle={pageTitle}
          pageSubtitle={pageSubtitle}
          isAdminMode={effectiveAdminMode}
        />
        <main className="flex-1 overflow-y-auto scrollbar-thin">
          <div className="max-w-screen-2xl mx-auto px-4 lg:px-6 xl:px-8 2xl:px-10 py-6">
            {children}
          </div>
        </main>
      </div>

      {liveAlerts.length > 0 && (
        <AlertOverlay
          alerts={liveAlerts}
          onDismiss={handleDismissAlert}
          onAccept={handleAcceptAlert}
          soundEnabled={alertSettingsRef.current.soundEnabled}
          volume={alertSettingsRef.current.volume}
        />
      )}
    </div>
  );
}

export default function AppLayout({ children }: { children: React.ReactNode }) {
  return (
    <BrandingProvider>
      <PlanFeaturesProvider>
        <LiveCountsProvider>
          <PageHeaderProvider>
            <AppLayoutInner>{children}</AppLayoutInner>
          </PageHeaderProvider>
        </LiveCountsProvider>
      </PlanFeaturesProvider>
    </BrandingProvider>
  );
}
