import { useEffect, useState } from 'react';
import { NavLink, Outlet, useLocation } from 'react-router-dom';
import { useAuth } from '../AuthContext';
import { api, formatCredits, formatCreditsExact } from '../api';
import DropFeed from './DropFeed';
import SessionLimitOverlay from './SessionLimitOverlay';
import { onInventoryChanged } from '../inventoryEvents';
import { getSocket, onSessionLimitChange, getSessionLimitPayload } from '../socket';

const FEED_KEY = 'caseorion-feed-drop';

function ScrollToTop() {
  const { pathname } = useLocation();
  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);
  return null;
}

function countWaitingBattles(jackpotBattles) {
  let n = 0;

  for (const battle of jackpotBattles || []) {
    if (battle.status === 'spinning') continue;
    const jpPlayers = battle?.players?.length ?? 0;
    const jpDeposits = battle?.deposits?.length ?? 0;
    if (
      battle?.waitingForPlayers &&
      battle.status === 'open' &&
      (jpPlayers > 0 || jpDeposits > 0)
    ) {
      n += 1;
    }
  }

  return n;
}

export default function Layout() {
  const { user } = useAuth();
  const { pathname } = useLocation();
  const [feedOpen, setFeedOpen] = useState(() => {
    try {
      return localStorage.getItem(FEED_KEY) === '1';
    } catch {
      return false;
    }
  });
  const [waitingBattles, setWaitingBattles] = useState(0);
  const [prestigeVisible, setPrestigeVisible] = useState(false);
  const [sessionLimit, setSessionLimit] = useState(() => getSessionLimitPayload());
  const [navHidden, setNavHidden] = useState(false);

  useEffect(() => {
    setNavHidden(false);
  }, [pathname]);

  useEffect(() => {
    try {
      localStorage.setItem(FEED_KEY, feedOpen ? '1' : '0');
    } catch {
      /* ignore */
    }
  }, [feedOpen]);

  // Mobile: hide topnav while scrolling down, reveal on scroll up / near top
  useEffect(() => {
    const mq = window.matchMedia('(max-width: 700px)');
    let lastY = window.scrollY || 0;
    let hidden = false;

    const apply = (next) => {
      if (hidden === next) return;
      hidden = next;
      setNavHidden(next);
    };

    const onScroll = () => {
      if (!mq.matches) {
        apply(false);
        lastY = window.scrollY || 0;
        return;
      }
      const y = window.scrollY || 0;
      const delta = y - lastY;
      lastY = y;
      if (y < 48) {
        apply(false);
        return;
      }
      if (delta > 6) apply(true);
      else if (delta < -6) apply(false);
    };

    const onMq = () => {
      if (!mq.matches) apply(false);
    };

    window.addEventListener('scroll', onScroll, { passive: true });
    mq.addEventListener?.('change', onMq);
    return () => {
      window.removeEventListener('scroll', onScroll);
      mq.removeEventListener?.('change', onMq);
    };
  }, []);

  useEffect(() => {
    if (!user || user.role === 'admin') {
      setPrestigeVisible(false);
      return undefined;
    }
    if ((user.prestigeCount ?? 0) > 0) {
      setPrestigeVisible(true);
    }
    let cancelled = false;
    const refreshVisibility = async () => {
      try {
        const data = await api.prestige();
        if (!cancelled) setPrestigeVisible(Boolean(data.pageVisible));
      } catch {
        /* nav link optional */
      }
    };
    refreshVisibility();
    const offInv = onInventoryChanged(() => {
      refreshVisibility();
    });
    return () => {
      cancelled = true;
      offInv();
    };
  }, [user?.id, user?.role, user?.balance, user?.prestigeCount]);

  useEffect(() => {
    if (!user || user.role === 'admin') {
      setWaitingBattles(0);
      return undefined;
    }

    let jackpotBattles = [];
    let cancelled = false;

    const sync = () => {
      if (cancelled) return;
      setWaitingBattles((prev) => {
        const next = countWaitingBattles(jackpotBattles);
        return prev === next ? prev : next;
      });
    };

    (async () => {
      try {
        const jp = await api.jackpot();
        if (cancelled) return;
        jackpotBattles = jp.battles || [];
        sync();
      } catch {
        /* nav badge is optional */
      }
    })();

    const socket = getSocket();
    const offLimitChange = onSessionLimitChange((payload) => {
      setSessionLimit(payload);
    });
    const onJackpots = (payload) => {
      jackpotBattles = payload.battles || [];
      sync();
    };

    socket.emit('jackpots:subscribe');
    socket.on('jackpots:list', onJackpots);
    socket.on('connect', () => {
      socket.emit('jackpots:subscribe');
    });

    return () => {
      cancelled = true;
      offLimitChange();
      socket.emit('jackpots:unsubscribe');
      socket.off('jackpots:list', onJackpots);
    };
  }, [user?.id, user?.role]);

  const isPlayer = user && user.role !== 'admin';

  return (
    <div
      className={`app-shell${feedOpen ? ' feed-open' : ''}${sessionLimit ? ' session-locked' : ''}`}
    >
      <ScrollToTop />
      {sessionLimit && <SessionLimitOverlay max={sessionLimit.max || 2} />}
      <header className={`topnav${navHidden ? ' topnav--hidden' : ''}`}>
        <div className="topnav-left">
          <NavLink to="/dashboard" className="brand">
            CaseOrion
          </NavLink>
          {isPlayer && (
            <button
              type="button"
              className={`nav-toggle${feedOpen ? ' active' : ''}`}
              onClick={() => setFeedOpen((v) => !v)}
              aria-pressed={feedOpen}
            >
              Feed Drop
            </button>
          )}
        </div>
        <nav className="nav-links">
          {isPlayer && (
            <>
              <NavLink to="/dashboard">Inventory</NavLink>
              <NavLink to="/cases">Cases</NavLink>
              <NavLink to="/catalog">Catalog</NavLink>
              {prestigeVisible && <NavLink to="/prestige">Prestige</NavLink>}
              <NavLink
                to="/battle"
                className={({ isActive }) =>
                  [
                    'nav-battle',
                    isActive ? 'active' : '',
                    waitingBattles > 0 ? 'nav-battle-waiting' : '',
                  ]
                    .filter(Boolean)
                    .join(' ')
                }
              >
                Battle
                {waitingBattles > 0 && (
                  <span className="nav-battle-badge" aria-label={`${waitingBattles} waiting`}>
                    {waitingBattles}
                  </span>
                )}
              </NavLink>
            </>
          )}
          <NavLink to="/leaderboard">Leaderboard</NavLink>
          {user?.role === 'admin' && <NavLink to="/admin">Admin</NavLink>}
          {user && (
            isPlayer ? (
              <NavLink
                to="/shop"
                className="balance-pill balance-pill-link"
                title={`${formatCreditsExact(user.balance)} cr`}
              >
                {formatCredits(user.balance)} cr
              </NavLink>
            ) : (
              <span
                className="balance-pill"
                title={`${formatCreditsExact(user.balance)} cr`}
              >
                {formatCredits(user.balance)} cr
              </span>
            )
          )}
          {user ? (
            <NavLink to="/profile" className="nav-user" title="Profile">
              {user.avatarUrl ? (
                <img src={user.avatarUrl} alt="" className="nav-avatar" />
              ) : null}
              <span className="muted">{user.username}</span>
            </NavLink>
          ) : (
            <NavLink to="/login">Login</NavLink>
          )}
        </nav>
      </header>
      <div className="app-body">
        {feedOpen && isPlayer && <DropFeed />}
        <main className="main">
          <Outlet />
        </main>
      </div>
    </div>
  );
}
