const {
  THEME_OPTIONS,
  LOGGED_IN_MODULES,
  VALIDATION_CODES,
  resolveRoute,
  readAuthToken
} = window.PortfolioAppConfig;

const {
  getStoredTheme,
  applyTheme,
  getValidationMessage,
  clearSessionStorage
} = window.PortfolioApp;

const {
  TransactionsModulePage,
  TransactionsActionPlaceholder
} = window.PortfolioTransactions;
const securitiesModule = window.PortfolioSecurities || {};
const SecuritiesModulePage = securitiesModule.SecuritiesModulePage;
const accountSettingsModule = window.PortfolioAccountSettings || {};
const AccountSettingsModulePage = accountSettingsModule.AccountSettingsModulePage;
const valuationsModule = window.PortfolioValuations || {};
const ValuationsModulePage = valuationsModule.ValuationsModulePage;

const sharedComponents = window.PortfolioSharedComponents || {};
const loginModule = window.PortfolioLogin || {};
const LoginPage = loginModule.LoginPage;
const registerModule = window.PortfolioRegister || {};
const RegisterPage = registerModule.RegisterPage;
const getRegisterFallbackMessage = registerModule.getRegisterFallbackMessage;

const initialTheme = getStoredTheme();
applyTheme(initialTheme);

function PublicPage({ navigate }) {
  return (
    <div className="content">
      <section className="hero-card">
        <div>
          <p className="muted">Demo Version v0.1</p>
          <h1 className="hero-title">Designed for long term investment portfolios.</h1>
          <p className="hero-copy">
            Portfolio Manager is a tool to manage your individual investments as a cohesive unit.
          </p>
          <div className="hero-actions">
            <button className="secondary-btn" onClick={() => navigate('/auth/login')}>Login</button>
            <button className="secondary-btn" onClick={() => navigate('/auth/register')}>Register</button>
          </div>
        </div>
        <div className="feature-list">
          <div className="feature-item"><span className="dot" /> <span>Upload Transaction files exported from Degiro.</span></div>
          <div className="feature-item"><span className="dot" /> <span>Track quality metrics at portfolio level.</span></div>
          <div className="feature-item"><span className="dot" /> <span>Measure portfolio performance against a benchmark.</span></div>
          <div className="feature-item"><span className="dot" /> <span>Simulate changes to your portfolio.</span></div>
        </div>
      </section>

      <section className="metrics-grid" style={{ marginTop: '1rem' }}>
        <div className="metric">
          <strong>$4.8M</strong>
          <span>ARR influenced through healthier forecast cycles</span>
        </div>
        <div className="metric">
          <strong>98%</strong>
          <span>renewal confidence from teams using the workspace</span>
        </div>
        <div className="metric">
          <strong>36 hrs</strong>
          <span>saved each week by replacing manual reporting</span>
        </div>
      </section>

      <p className="footer-note">Responsive by design - to work seamlessly on your mobile.</p>
    </div>
  );
}

function LoggedInModulePage({ route, navigate }) {
  const [portfoliosModuleTick, setPortfoliosModuleTick] = React.useState(0);

  React.useEffect(() => {
    if (route.moduleKey !== 'portfolios') {
      return undefined;
    }

    if (window.PortfolioPortfolios && typeof window.PortfolioPortfolios.PortfoliosModulePage === 'function') {
      return undefined;
    }

    const intervalId = window.setInterval(() => {
      if (window.PortfolioPortfolios && typeof window.PortfolioPortfolios.PortfoliosModulePage === 'function') {
        setPortfoliosModuleTick((value) => value + 1);
        window.clearInterval(intervalId);
      }
    }, 100);

    return () => {
      window.clearInterval(intervalId);
    };
  }, [route.moduleKey]);

  const portfoliosModule = window.PortfolioPortfolios || {};
  const PortfoliosPage = portfoliosModule.PortfoliosModulePage;

  const isValuationsRoute = route.moduleKey === 'valuations'
    && (route.view === 'valuations' || route.view === 'valuations-add' || route.view === 'valuations-upload');

  if (isValuationsRoute) {
    if (typeof ValuationsModulePage === 'function') {
      return <ValuationsModulePage route={route} navigate={navigate} />;
    }

    return (
      <div className="content auth-shell" style={{ marginTop: '0.5rem' }}>
        <section className="panel-card">
          <h3 style={{ marginTop: 0 }}>Valuations</h3>
          <p className="muted" style={{ marginBottom: 0 }}>
            Loading valuations module...
          </p>
        </section>
      </div>
    );
  }

  if (route.moduleKey === 'portfolios') {
    if (typeof PortfoliosPage === 'function') {
      return <PortfoliosPage key={`portfolios-module-${portfoliosModuleTick}`} route={route} navigate={navigate} />;
    }

    return (
      <div className="content auth-shell" style={{ marginTop: '0.5rem' }}>
        <section className="panel-card">
          <h3 style={{ marginTop: 0 }}>Portfolios</h3>
          <p className="muted" style={{ marginBottom: 0 }}>
            Loading portfolios module...
          </p>
        </section>
      </div>
    );
  }

  const moduleMeta = {
    transactions: {
      title: 'Transactions',
      description: 'Review activity history, categorize movements, and reconcile posted transactions.'
    },
    securities: {
      title: 'Securities',
      description: 'Search securities by ticker, validate mapped identifiers, and inspect external details when available.'
    },
    watchlists: {
      title: 'Watchlists',
      description: 'Monitor tickers, price alerts, and momentum opportunities in one place.'
    },
    'stock-analysis': {
      title: 'Stock Analysis',
      description: 'Explore valuation signals, trend snapshots, and comparative fundamentals.'
    },
    'account-settings': {
      title: 'Account Settings',
      description: 'Manage your profile, security preferences, and workspace defaults.'
    }
  };

  if (route.moduleKey === 'transactions' && route.action) {
    return <TransactionsActionPlaceholder route={route} navigate={navigate} />;
  }

  if (route.moduleKey === 'transactions') {
    return <TransactionsModulePage navigate={navigate} />;
  }

  if (route.moduleKey === 'securities' && typeof SecuritiesModulePage === 'function') {
    return <SecuritiesModulePage navigate={navigate} />;
  }

  if (route.moduleKey === 'account-settings' && typeof AccountSettingsModulePage === 'function') {
    return <AccountSettingsModulePage navigate={navigate} />;
  }

  const meta = moduleMeta[route.moduleKey] || {
    title: 'Portfolios',
    description: 'Track balances, allocation, and performance across your investment accounts.'
  };

  return (
    <div className="content auth-shell" style={{ marginTop: '0.5rem' }}>
      <section className="hero-card">
        <div>
          <p className="muted">Authenticated workspace</p>
          <h1 className="hero-title" style={{ fontSize: 'clamp(1.8rem, 2.4vw, 2.4rem)' }}>{meta.title}</h1>
          <p className="hero-copy">{meta.description}</p>
        </div>
      </section>

      <section className="panel-card">
        <h3 style={{ marginTop: 0 }}>Module Placeholder</h3>
        <p className="muted" style={{ marginBottom: 0 }}>
          This module is scaffolded as part of the SPA shell. Next step: wire its dedicated API client functions and view state.
        </p>
      </section>
    </div>
  );
}

function ThemePicker({ currentTheme, isThemeMenuOpen, onToggleMenu, onCloseMenu, onSelectTheme, themeButtonRef, themeMenuRef }) {
  return (
    <div className="theme-picker">
      <button
        ref={themeButtonRef}
        className="theme-trigger"
        type="button"
        aria-label={`Selected theme ${currentTheme.label}`}
        aria-haspopup="menu"
        aria-expanded={isThemeMenuOpen}
        onClick={onToggleMenu}
      >
        <img className="theme-trigger-icon" src={currentTheme.icon} alt="" aria-hidden="true" />
      </button>
      {isThemeMenuOpen && (
        <div ref={themeMenuRef} className="theme-menu" role="menu" aria-label="Theme options">
          {THEME_OPTIONS.map((item) => (
            <button
              key={item.value}
              className={`theme-option ${currentTheme.value === item.value ? 'selected' : ''}`}
              type="button"
              role="menuitemradio"
              aria-checked={currentTheme.value === item.value}
              data-theme-option={item.value}
              onClick={() => {
                onSelectTheme(item.value);
                onCloseMenu();
              }}
            >
              <img className="theme-option-icon" src={item.icon} alt="" aria-hidden="true" />
              <span>{item.label}</span>
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function AppBrandTitle() {
  return 'foliomgr';
}

function CogIcon() {
  return (
    <svg className="brand-subtitle-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
      <path d="M19.14 12.94c.04-.31.06-.62.06-.94s-.02-.63-.06-.94l2.03-1.58a.5.5 0 0 0 .12-.64l-1.92-3.32a.5.5 0 0 0-.6-.22l-2.39.96a7.03 7.03 0 0 0-1.62-.94l-.36-2.54A.5.5 0 0 0 13.9 2h-3.8a.5.5 0 0 0-.5.42l-.36 2.54c-.58.24-1.12.56-1.62.94l-2.39-.96a.5.5 0 0 0-.6.22L2.71 8.48a.5.5 0 0 0 .12.64l2.03 1.58c-.04.31-.06.62-.06.94s.02.63.06.94l-2.03 1.58a.5.5 0 0 0-.12.64l1.92 3.32c.12.22.38.3.6.22l2.39-.96c.5.38 1.04.7 1.62.94l.36 2.54c.04.24.25.42.5.42h3.8c.25 0 .46-.18.5-.42l.36-2.54c.58-.24 1.12-.56 1.62-.94l2.39.96c.22.08.48 0 .6-.22l1.92-3.32a.5.5 0 0 0-.12-.64l-2.03-1.58zM12 15.5a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7z" />
    </svg>
  );
}

function decodeJwtPayload(token) {
  if (typeof token !== 'string' || !token) {
    return null;
  }

  try {
    const parts = token.split('.');
    if (parts.length < 2) {
      return null;
    }

    const encodedPayload = parts[1].replace(/-/g, '+').replace(/_/g, '/');
    const paddedPayload = encodedPayload + '='.repeat((4 - (encodedPayload.length % 4)) % 4);
    return JSON.parse(window.atob(paddedPayload));
  } catch (error) {
    return null;
  }
}

function toDisplayName(value) {
  const normalized = String(value || '').trim().replace(/[._-]+/g, ' ');
  if (!normalized) {
    return '';
  }

  return normalized
    .split(/\s+/)
    .filter(Boolean)
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
    .join(' ');
}

function readLoggedInDisplayName() {
  const token = readAuthToken();
  const payload = decodeJwtPayload(token);
  if (!payload || typeof payload !== 'object') {
    return '';
  }

  const tokenName = typeof payload.name === 'string' ? payload.name.trim() : '';
  if (tokenName) {
    return toDisplayName(tokenName);
  }

  const email = typeof payload.email === 'string' ? payload.email.trim() : '';
  if (!email) {
    return '';
  }

  const localPart = email.split('@')[0] || '';
  return toDisplayName(localPart);
}

function readJwtExpiryTimeMs(token) {
  const payload = decodeJwtPayload(token);
  if (!payload || typeof payload !== 'object') {
    return null;
  }

  const rawExp = payload.exp;
  const expSeconds = typeof rawExp === 'string' ? Number.parseInt(rawExp, 10) : rawExp;
  if (!Number.isFinite(expSeconds) || expSeconds <= 0) {
    return null;
  }

  return Math.trunc(expSeconds * 1000);
}

function readJwtRoleIds(token) {
  const payload = decodeJwtPayload(token);
  if (!payload || typeof payload !== 'object') {
    return [];
  }

  const claimsRoles = payload && payload.claims && payload.claims.roles;
  const scopeRoles = payload && payload.scope && payload.scope.roles;
  const source = Array.isArray(claimsRoles)
    ? claimsRoles
    : (Array.isArray(scopeRoles) ? scopeRoles : []);

  return Array.from(
    new Set(
      source
        .map((value) => Number.parseInt(value, 10))
        .filter((value) => Number.isFinite(value))
    )
  );
}

function canAccessModule(moduleKey, roleIds) {
  if (moduleKey === 'securities') {
    return Array.isArray(roleIds) && roleIds.includes(100);
  }

  return true;
}

function PublicMenuBar({ route, navigate, currentTheme, isThemeMenuOpen, onToggleThemeMenu, onCloseThemeMenu, onSelectTheme, themeButtonRef, themeMenuRef }) {
  const isOverviewRoute = route.type === 'landing';
  const isLoginRoute = route.type === 'auth' && route.view === 'login';
  const isRegisterRoute = route.type === 'auth' && route.view === 'register';

  return (
    <header className="topbar">
      <div className="brand">
        <AppBrandTitle />
        <span className="brand-subtitle">A Portfolio Manager</span>
      </div>
      <nav className="nav-links">
        <a className={isOverviewRoute ? 'primary-btn' : 'nav-pill'} href="/" onClick={(event) => { event.preventDefault(); navigate('/'); }}>Overview</a>
        <a className={isLoginRoute ? 'primary-btn' : 'nav-pill'} href="/auth/login" onClick={(event) => { event.preventDefault(); navigate('/auth/login'); }}>Login</a>
        <a className={isRegisterRoute ? 'primary-btn' : 'nav-pill'} href="/auth/register" onClick={(event) => { event.preventDefault(); navigate('/auth/register'); }}>Register</a>
        <ThemePicker
          currentTheme={currentTheme}
          isThemeMenuOpen={isThemeMenuOpen}
          onToggleMenu={onToggleThemeMenu}
          onCloseMenu={onCloseThemeMenu}
          onSelectTheme={onSelectTheme}
          themeButtonRef={themeButtonRef}
          themeMenuRef={themeMenuRef}
        />
      </nav>
    </header>
  );
}

function LoggedInMenuBar({ route, navigate, onSignOut, currentTheme, isThemeMenuOpen, onToggleThemeMenu, onCloseThemeMenu, onSelectTheme, themeButtonRef, themeMenuRef, loggedInDisplayName, loggedInModules }) {
  return (
    <header className="topbar">
      <div className="brand">
        <AppBrandTitle />
        {loggedInDisplayName ? (
          <a
            className="brand-subtitle brand-subtitle-link"
            href="/account-settings"
            title="Edit Account Settings"
            onClick={(event) => { event.preventDefault(); navigate('/account-settings'); }}
          >   
            <CogIcon />         
            <span>{loggedInDisplayName}</span>
            
          </a>
        ) : null}
      </div>
      <nav className="nav-links">
        {loggedInModules.map((moduleRoute) => (
          <a
            key={moduleRoute.key}
            className={route.moduleKey === moduleRoute.key ? 'primary-btn' : 'nav-pill'}
            href={moduleRoute.path}
            onClick={(event) => {
              event.preventDefault();
              navigate(moduleRoute.path);
            }}
          >
            {moduleRoute.label}
          </a>
        ))}
        <button className="secondary-btn" type="button" onClick={onSignOut}>Sign out</button>
        <ThemePicker
          currentTheme={currentTheme}
          isThemeMenuOpen={isThemeMenuOpen}
          onToggleMenu={onToggleThemeMenu}
          onCloseMenu={onCloseThemeMenu}
          onSelectTheme={onSelectTheme}
          themeButtonRef={themeButtonRef}
          themeMenuRef={themeMenuRef}
        />
      </nav>
    </header>
  );
}

function AuthPage({ route, navigate }) {
  if (route.view === 'login' && typeof LoginPage === 'function') {
    return <LoginPage route={route} navigate={navigate} />;
  }

  if (route.view === 'register' && typeof RegisterPage === 'function') {
    return <RegisterPage route={route} navigate={navigate} />;
  }

  const viewMeta = {
    login: { title: 'Log in', subtitle: 'Welcome back to your finance workspace.', cta: 'Login' },
    register: { title: 'Register', subtitle: 'Create your secure account in minutes.', cta: 'Register Account' },
    'change-password': { title: 'Change password', subtitle: 'Update your credential with confidence.', cta: 'Save password' },
    'reset-password': { title: 'Reset password', subtitle: 'We can help you get back in quickly.', cta: 'Send reset link' }
  };
  const meta = viewMeta[route.view];
  const [status, setStatus] = React.useState(null);

  React.useEffect(() => {
    setStatus(null);
  }, [route.view]);

  const handleSubmit = (event) => {
    event.preventDefault();
    const fallbackMessage = typeof getRegisterFallbackMessage === 'function'
      ? getRegisterFallbackMessage(route.view)
      : null;
    const message = fallbackMessage || getValidationMessage('A Validation Issue occurred.', VALIDATION_CODES.email);
    setStatus({ type: 'error', message });
  };

  return (
    <div className="content auth-shell">
      <section className="auth-card">
        <div className="auth-header">
          <div>
            <h2 style={{ margin: 0 }}>{meta.title}</h2>
            <p className="muted" style={{ margin: '0.3rem 0 0' }}>{meta.subtitle}</p>
          </div>
          <button className="secondary-btn" onClick={() => navigate('/')}>Back to Overview</button>
        </div>

        <form className="form-grid" style={{ marginTop: '1rem' }} onSubmit={handleSubmit}>
          {route.view === 'change-password' && (!status || status.type !== 'success') && (
            <div className="field">
              <label>New password</label>
              <input type="password" placeholder="Choose a new password" />
            </div>
          )}
          {status && (
            <div className={`status-message ${status.type}`} role="status">
              <span>{status.message}</span>
            </div>
          )}
          {(!status || status.type !== 'success') && (
            <button className="primary-btn" type="submit" disabled={isSubmitting}>{isSubmitting ? 'Working...' : meta.cta}</button>
          )}
        </form>
      </section>

      <section className="panel-card">
        <h3 style={{ marginTop: 0 }}>Demo Version</h3>
        <ul>
          <li>The Demo allows customers to register, login and provides basic Portfolio management capabilities.</li>
          <li>There is no customer billing in the demo as it is not intended to be marketed to customers.</li>
          <li>The API used to source stock information will be a free or cheap version with limitations that would not support customers beyond a demo.</li>
        </ul>
        <p className="muted">The demo will create a default portfolio which cannot be edited. Multiple portfolios will not be supported.</p>
      </section>
    </div>
  );
}

function App() {
  const [route, setRoute] = React.useState(() => resolveRoute(window.location.pathname));
  const [theme, setTheme] = React.useState(initialTheme);
  const [isThemeMenuOpen, setIsThemeMenuOpen] = React.useState(false);

  const themeButtonRef = React.useRef(null);
  const themeMenuRef = React.useRef(null);

  React.useEffect(() => {
    const handleRoute = () => setRoute(resolveRoute(window.location.pathname));
    window.addEventListener('popstate', handleRoute);
    return () => {
      window.removeEventListener('popstate', handleRoute);
    };
  }, []);

  React.useEffect(() => {
    applyTheme(theme);
    try {
      window.localStorage.setItem('portfolio-theme', theme);
    } catch (error) {
      console.warn('Could not persist theme preference.', error);
    }
  }, [theme]);

  React.useEffect(() => {
    const handleOutsideClick = (event) => {
      if (themeMenuRef.current && themeMenuRef.current.contains(event.target)) {
        return;
      }
      if (themeButtonRef.current && themeButtonRef.current.contains(event.target)) {
        return;
      }
      setIsThemeMenuOpen(false);
    };

    const handleEscape = (event) => {
      if (event.key === 'Escape') {
        setIsThemeMenuOpen(false);
      }
    };

    document.addEventListener('mousedown', handleOutsideClick);
    document.addEventListener('keydown', handleEscape);
    return () => {
      document.removeEventListener('mousedown', handleOutsideClick);
      document.removeEventListener('keydown', handleEscape);
    };
  }, []);

  React.useEffect(() => {
    setIsThemeMenuOpen(false);
  }, [theme]);

  React.useEffect(() => {
    if (route.type === 'module' && !readAuthToken()) {
      window.history.replaceState({}, '', '/auth/login');
      setRoute(resolveRoute('/auth/login'));
    }
  }, [route]);

  React.useEffect(() => {
    let timerId = null;

    const enforceTokenExpiry = () => {
      const token = readAuthToken();
      if (!token) {
        return;
      }

      const expiresAtMs = readJwtExpiryTimeMs(token);
      if (!Number.isFinite(expiresAtMs)) {
        return;
      }

      const remainingMs = expiresAtMs - Date.now();
      if (remainingMs <= 0) {
        clearSessionStorage();
        if (route.type === 'module') {
          window.history.replaceState({}, '', '/auth/login');
          setRoute(resolveRoute('/auth/login'));
        }
        return;
      }

      // Browser timers cap delay around 24.8 days, so schedule in chunks for long-lived tokens.
      const maxTimerDelayMs = 2147483647;
      timerId = window.setTimeout(enforceTokenExpiry, Math.min(remainingMs, maxTimerDelayMs));
    };

    enforceTokenExpiry();

    return () => {
      if (timerId != null) {
        window.clearTimeout(timerId);
      }
    };
  }, [route.type]);

  const navigate = (nextPath) => {
    const nextRoute = resolveRoute(nextPath);
    if (nextRoute.type === 'module' && !readAuthToken()) {
      window.history.pushState({}, '', '/auth/login');
      setRoute(resolveRoute('/auth/login'));
      return;
    }

    window.history.pushState({}, '', nextPath);
    setRoute(nextRoute);
  };

  const handleSignOut = () => {
    clearSessionStorage();
    navigate('/auth/login');
  };

  const currentTheme = THEME_OPTIONS.find((item) => item.value === theme) || THEME_OPTIONS[0];
  const loggedInDisplayName = readLoggedInDisplayName();
  const roleIds = React.useMemo(() => readJwtRoleIds(readAuthToken()), [route.type, route.moduleKey, route.view]);
  const loggedInModules = React.useMemo(
    () => LOGGED_IN_MODULES.filter((moduleRoute) => canAccessModule(moduleRoute.key, roleIds)),
    [roleIds]
  );

  React.useEffect(() => {
    if (route.type !== 'module') {
      return;
    }

    if (!canAccessModule(route.moduleKey, roleIds)) {
      window.history.replaceState({}, '', '/portfolios');
      setRoute(resolveRoute('/portfolios'));
    }
  }, [route, roleIds]);

  return (
    <div className="app-shell">
      {route.type === 'module' ? (
        <LoggedInMenuBar
          route={route}
          navigate={navigate}
          onSignOut={handleSignOut}
          currentTheme={currentTheme}
          isThemeMenuOpen={isThemeMenuOpen}
          onToggleThemeMenu={() => setIsThemeMenuOpen((current) => !current)}
          onCloseThemeMenu={() => setIsThemeMenuOpen(false)}
          onSelectTheme={setTheme}
          themeButtonRef={themeButtonRef}
          themeMenuRef={themeMenuRef}
          loggedInDisplayName={loggedInDisplayName}
          loggedInModules={loggedInModules}
        />
      ) : (
        <PublicMenuBar
          route={route}
          navigate={navigate}
          currentTheme={currentTheme}
          isThemeMenuOpen={isThemeMenuOpen}
          onToggleThemeMenu={() => setIsThemeMenuOpen((current) => !current)}
          onCloseThemeMenu={() => setIsThemeMenuOpen(false)}
          onSelectTheme={setTheme}
          themeButtonRef={themeButtonRef}
          themeMenuRef={themeMenuRef}
        />
      )}

      {route.type === 'auth' ? (
        <AuthPage route={route} navigate={navigate} />
      ) : route.type === 'module' ? (
        <LoggedInModulePage route={route} navigate={navigate} />
      ) : (
        <PublicPage navigate={navigate} />
      )}
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
