(function initPortfolioSelection(global) {
  function clearAuthSession() {
    try {
      window.sessionStorage.removeItem('portfolio-auth-token');
      window.sessionStorage.removeItem('portfolio-linked-portfolios');
    } catch (error) {
      // Ignore session storage errors.
    }
  }

  function handleUnauthorizedApiResponse() {
    clearAuthSession();
    window.location.assign('/auth/login');
  }

  function readPortfoliosFromSessionCache() {
    try {
      const raw = window.sessionStorage.getItem('portfolio-linked-portfolios');
      if (!raw) {
        return null;
      }
      const parsed = JSON.parse(raw);
      if (Array.isArray(parsed)) {
        return parsed;
      }
      if (parsed && Array.isArray(parsed.portfolios)) {
        return parsed.portfolios;
      }
      return null;
    } catch (error) {
      return null;
    }
  }

  function writePortfoliosToSessionCache(portfolios) {
    try {
      // Accept either an array of portfolios or an object with cache metadata.
      if (portfolios && typeof portfolios === 'object' && !Array.isArray(portfolios) && Array.isArray(portfolios.portfolios)) {
        window.sessionStorage.setItem('portfolio-linked-portfolios', JSON.stringify(portfolios));
      } else {
        window.sessionStorage.setItem('portfolio-linked-portfolios', JSON.stringify(portfolios));
      }
    } catch (error) {
      // Ignore session cache errors.
    }
  }

  function readAccountBaseCurrencyFromSessionCache() {
    try {
      const raw = window.sessionStorage.getItem('portfolio-linked-portfolios');
      if (!raw) return null;
      const parsed = JSON.parse(raw);
      if (!parsed) return null;
      if (parsed && typeof parsed === 'object' && parsed.accountBaseCurrency) {
        return String(parsed.accountBaseCurrency).toUpperCase();
      }
      return null;
    } catch (error) {
      return null;
    }
  }

  function readAccountBenchmarkBaseCurrencyFromSessionCache() {
    try {
      const raw = window.sessionStorage.getItem('portfolio-linked-portfolios');
      if (!raw) return null;
      const parsed = JSON.parse(raw);
      if (!parsed) return null;
      if (parsed && typeof parsed === 'object' && parsed.accountBenchmarkBaseCurrency) {
        return String(parsed.accountBenchmarkBaseCurrency).toUpperCase();
      }
      return null;
    } catch (error) {
      return null;
    }
  }

  function getPrimaryCurrencyForSelection(selectionValue) {
    const allValue = 'All';
    const portfolios = readPortfoliosFromSessionCache() || [];
    const accountCurrency = readAccountBaseCurrencyFromSessionCache();

    if (!selectionValue || String(selectionValue).toLowerCase() === String(allValue).toLowerCase()) {
      return accountCurrency || null;
    }

    const selectedId = Number.parseInt(selectionValue, 10);
    if (!Number.isFinite(selectedId)) return accountCurrency || null;
    const found = portfolios.find((p) => Number.parseInt(p.id, 10) === selectedId);
    return found && found.baseCurrency ? String(found.baseCurrency).toUpperCase() : accountCurrency || null;
  }

  function getPrimaryBenchmarkCurrencyForSelection(selectionValue) {
    const allValue = 'All';
    const portfolios = readPortfoliosFromSessionCache() || [];
    const accountBenchmarkCurrency = readAccountBenchmarkBaseCurrencyFromSessionCache();

    if (!selectionValue || String(selectionValue).toLowerCase() === String(allValue).toLowerCase()) {
      return accountBenchmarkCurrency || null;
    }

    const selectedId = Number.parseInt(selectionValue, 10);
    if (!Number.isFinite(selectedId)) return accountBenchmarkCurrency || null;
    const found = portfolios.find((p) => Number.parseInt(p.id, 10) === selectedId);
    return found && found.benchmarkBaseCurrency ? String(found.benchmarkBaseCurrency).toUpperCase() : accountBenchmarkCurrency || null;
  }

  function readSessionToken() {
    try {
      return window.sessionStorage.getItem('portfolio-auth-token');
    } catch (error) {
      return null;
    }
  }

  function getAuthorizedJsonHeaders() {
    const token = readSessionToken();
    const headers = { Accept: 'application/json' };
    if (token) {
      headers.Authorization = `Bearer ${token}`;
    }
    return headers;
  }

  function usePortfolios(options) {
    const settings = options || {};
    const [portfolios, setPortfolios] = React.useState(() => readPortfoliosFromSessionCache() || []);
    const [isLoading, setIsLoading] = React.useState(false);

    React.useEffect(() => {
      let active = true;

      async function loadPortfolios() {
        const cached = readPortfoliosFromSessionCache();
        if (cached && cached.length > 0) {
          if (active) {
            setPortfolios(cached);
          }
          return;
        }

        setIsLoading(true);
        try {
          const response = await fetch('/api/portfolios', {
            method: 'GET',
            headers: getAuthorizedJsonHeaders()
          });

          if (response.status === 401 || response.status === 403) {
            if (typeof settings.onUnauthorized === 'function') {
              settings.onUnauthorized(response);
            } else {
              handleUnauthorizedApiResponse();
            }
            return;
          }

          if (!response.ok) {
            throw new Error('Portfolio list request failed.');
          }

          const payload = await response.json();
          const items = Array.isArray(payload.portfolios) ? payload.portfolios : [];
          const accountBase = payload && payload.accountBaseCurrency ? payload.accountBaseCurrency : null;
          const accountBenchmarkBase = payload && payload.accountBenchmarkBaseCurrency ? payload.accountBenchmarkBaseCurrency : null;
          if (active) {
            setPortfolios(items);
            writePortfoliosToSessionCache({
              portfolios: items,
              accountBaseCurrency: accountBase,
              accountBenchmarkBaseCurrency: accountBenchmarkBase
            });
          }
        } catch (error) {
          if (typeof settings.onError === 'function') {
            settings.onError(error);
          }
        } finally {
          if (active) {
            setIsLoading(false);
          }
        }
      }

      if (settings.loadOnMount === false) {
        return () => {
          active = false;
        };
      }

      loadPortfolios();
      return () => {
        active = false;
      };
    }, []);

    return {
      portfolios,
      setPortfolios,
      isLoading,
      readPortfoliosFromSessionCache,
      writePortfoliosToSessionCache
    };
  }

  function PortfolioSelectField({
    portfolios,
    value,
    onChange,
    label,
    showLabel,
    includeAll,
    allLabel,
    allValue,
    placeholder,
    errorMessage
  }) {
    const resolvedLabel = label || 'Portfolio';
    const resolvedPlaceholder = placeholder || 'Select portfolio';
    const resolvedAllLabel = allLabel || 'All Portfolios';
    const resolvedAllValue = allValue || 'All';
    const showAll = Boolean(includeAll);
    const shouldShowLabel = showLabel !== false;

    return (
      <label className={`field ${errorMessage ? 'invalid' : ''}`.trim()}>
        {shouldShowLabel ? <span>{resolvedLabel}</span> : null}
        <select value={value} onChange={(event) => onChange(event.target.value)}>
          {showAll ? <option value={resolvedAllValue}>{resolvedAllLabel}</option> : <option value="">{resolvedPlaceholder}</option>}
          {(portfolios || []).map((portfolio) => (
            <option key={portfolio.id} value={String(portfolio.id)}>{portfolio.name}</option>
          ))}
        </select>
        {errorMessage ? <span className="error-message">{errorMessage}</span> : null}
      </label>
    );
  }

  global.PortfolioSelection = {
    usePortfolios,
    PortfolioSelectField,
    readPortfoliosFromSessionCache,
    writePortfoliosToSessionCache,
    readAccountBaseCurrencyFromSessionCache,
    readAccountBenchmarkBaseCurrencyFromSessionCache,
    getPrimaryCurrencyForSelection,
    getPrimaryBenchmarkCurrencyForSelection,
    getAuthorizedJsonHeaders,
    handleUnauthorizedApiResponse
  };
})(window);
