import { useEffect, useState } from 'react';
import {
  clearPreviewRuntimeTokenFromUrl,
  isPreviewRuntime,
  readPreviewRuntimeTokenFromUrl,
} from './previewRuntime';

export const TOKEN_ACCESS_STORAGE_KEY = 'work-app.token-access.registered-token';
export const TOKEN_ACCESS_SYNC_EVENT = 'work-app:token-access-changed';
export const ALLOWED_REGISTRATION_TOKEN =
  import.meta.env.VITE_ALLOWED_REGISTRATION_TOKEN?.trim() || 'usr_7f3a9c2d8e1b4a6f';
const PREVIEW_RUNTIME_TOKEN_STORAGE_KEY = 'work-app.preview-runtime.registered-token';
const PREVIEW_APP_ORIGIN = 'https://preview.sm-home.cloud';
const TOKEN_STORAGE_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;

let previewRuntimeTokenMemory = '';

function removeStorageToken(storage: Storage | null, key: string) {
  try {
    storage?.removeItem(key);
  } catch {
    // Ignore storage access errors in restricted preview runtimes.
  }
}

function getRegisteredTokenStorage() {
  if (typeof window === 'undefined') {
    return null;
  }

  return {
    primaryStorage: window.localStorage,
    legacyStorage: window.sessionStorage,
  };
}

function getPreviewRuntimeTokenStorage() {
  if (typeof window === 'undefined') {
    return null;
  }

  return {
    primaryStorage: window.localStorage,
    legacyStorage: window.sessionStorage,
  };
}

function normalizeToken(value: string | null | undefined) {
  return value?.trim() ?? '';
}

function readStorageToken(storage: Storage | null, key: string) {
  try {
    return normalizeToken(storage?.getItem(key));
  } catch {
    return '';
  }
}

function writeStorageToken(storage: Storage | null, key: string, token: string) {
  try {
    if (token) {
      storage?.setItem(key, token);
    } else {
      storage?.removeItem(key);
    }
  } catch {
    // Ignore storage access errors in restricted preview runtimes.
  }
}

function readCookieToken(key: string) {
  if (typeof document === 'undefined') {
    return '';
  }

  const encodedKey = `${encodeURIComponent(key)}=`;
  const cookieEntry = document.cookie
    .split(';')
    .map((entry) => entry.trim())
    .find((entry) => entry.startsWith(encodedKey));

  if (!cookieEntry) {
    return '';
  }

  return normalizeToken(decodeURIComponent(cookieEntry.slice(encodedKey.length)));
}

function writeCookieToken(key: string, token: string) {
  if (typeof document === 'undefined') {
    return;
  }

  const encodedKey = encodeURIComponent(key);

  if (!token) {
    document.cookie = `${encodedKey}=; path=/; max-age=0; SameSite=Lax`;
    return;
  }

  document.cookie = `${encodedKey}=${encodeURIComponent(token)}; path=/; max-age=${TOKEN_STORAGE_COOKIE_MAX_AGE_SECONDS}; SameSite=Lax`;
}

function bootstrapRegisteredAccessToken() {
  if (typeof window === 'undefined') {
    return;
  }

  const tokenFromUrl = readPreviewRuntimeTokenFromUrl();
  const registeredTokenStorage = getRegisteredTokenStorage();
  const storedToken = readStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
  const legacyStoredToken = readStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
  const cookieStoredToken = readCookieToken(TOKEN_ACCESS_STORAGE_KEY);

  if (isPreviewRuntime()) {
    const previewRuntimeTokenStorage = getPreviewRuntimeTokenStorage();
    const cookieStoredPreviewToken = readCookieToken(PREVIEW_RUNTIME_TOKEN_STORAGE_KEY);

    if (!tokenFromUrl) {
      const storedPreviewToken = readStorageToken(
        previewRuntimeTokenStorage?.primaryStorage ?? null,
        PREVIEW_RUNTIME_TOKEN_STORAGE_KEY,
      );

      if (storedPreviewToken) {
        previewRuntimeTokenMemory = storedPreviewToken;
        writeCookieToken(PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, storedPreviewToken);
        removeStorageToken(previewRuntimeTokenStorage?.legacyStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY);
        return;
      }

      const legacyStoredPreviewToken = readStorageToken(
        previewRuntimeTokenStorage?.legacyStorage ?? null,
        PREVIEW_RUNTIME_TOKEN_STORAGE_KEY,
      );

      if (legacyStoredPreviewToken) {
        previewRuntimeTokenMemory = legacyStoredPreviewToken;
        writeStorageToken(
          previewRuntimeTokenStorage?.primaryStorage ?? null,
          PREVIEW_RUNTIME_TOKEN_STORAGE_KEY,
          legacyStoredPreviewToken,
        );
        writeCookieToken(PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, legacyStoredPreviewToken);
        removeStorageToken(previewRuntimeTokenStorage?.legacyStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY);
        return;
      }

      if (cookieStoredPreviewToken) {
        previewRuntimeTokenMemory = cookieStoredPreviewToken;
        writeStorageToken(
          previewRuntimeTokenStorage?.primaryStorage ?? null,
          PREVIEW_RUNTIME_TOKEN_STORAGE_KEY,
          cookieStoredPreviewToken,
        );
        removeStorageToken(previewRuntimeTokenStorage?.legacyStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY);
        return;
      }

      if (window.location.origin === PREVIEW_APP_ORIGIN) {
        previewRuntimeTokenMemory = ALLOWED_REGISTRATION_TOKEN;
        writeStorageToken(
          previewRuntimeTokenStorage?.primaryStorage ?? null,
          PREVIEW_RUNTIME_TOKEN_STORAGE_KEY,
          ALLOWED_REGISTRATION_TOKEN,
        );
        writeCookieToken(PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, ALLOWED_REGISTRATION_TOKEN);
        removeStorageToken(previewRuntimeTokenStorage?.legacyStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY);
      }
      return;
    }

    previewRuntimeTokenMemory = tokenFromUrl;
    writeStorageToken(previewRuntimeTokenStorage?.primaryStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, tokenFromUrl);
    writeCookieToken(PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, tokenFromUrl);
    removeStorageToken(previewRuntimeTokenStorage?.legacyStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY);
    clearPreviewRuntimeTokenFromUrl();
    return;
  }

  if (!tokenFromUrl) {
    if (!storedToken && legacyStoredToken) {
      writeStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY, legacyStoredToken);
      writeCookieToken(TOKEN_ACCESS_STORAGE_KEY, legacyStoredToken);
      removeStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
      return;
    }

    if (!storedToken && cookieStoredToken) {
      writeStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY, cookieStoredToken);
      removeStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
      return;
    }

    if (window.location.origin === PREVIEW_APP_ORIGIN && storedToken !== ALLOWED_REGISTRATION_TOKEN) {
      writeStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY, ALLOWED_REGISTRATION_TOKEN);
      writeCookieToken(TOKEN_ACCESS_STORAGE_KEY, ALLOWED_REGISTRATION_TOKEN);
      removeStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
    }
    return;
  }

  writeStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY, tokenFromUrl);
  writeCookieToken(TOKEN_ACCESS_STORAGE_KEY, tokenFromUrl);
  removeStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
  clearPreviewRuntimeTokenFromUrl();
}

bootstrapRegisteredAccessToken();

export function isAllowedRegistrationToken(token: string | null | undefined) {
  return normalizeToken(token) === ALLOWED_REGISTRATION_TOKEN;
}

export function getRegisteredAccessToken() {
  if (typeof window === 'undefined') {
    return '';
  }

  if (isPreviewRuntime()) {
    const previewRuntimeTokenStorage = getPreviewRuntimeTokenStorage();
    const previewToken =
      readStorageToken(previewRuntimeTokenStorage?.primaryStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY) ||
      readStorageToken(previewRuntimeTokenStorage?.legacyStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY) ||
      previewRuntimeTokenMemory;

    if (!previewToken && window.location.origin === PREVIEW_APP_ORIGIN) {
      previewRuntimeTokenMemory = ALLOWED_REGISTRATION_TOKEN;
      writeStorageToken(
        previewRuntimeTokenStorage?.primaryStorage ?? null,
        PREVIEW_RUNTIME_TOKEN_STORAGE_KEY,
        ALLOWED_REGISTRATION_TOKEN,
      );
      writeCookieToken(PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, ALLOWED_REGISTRATION_TOKEN);
      removeStorageToken(previewRuntimeTokenStorage?.legacyStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY);
      return ALLOWED_REGISTRATION_TOKEN;
    }

    if (previewToken) {
      writeStorageToken(previewRuntimeTokenStorage?.primaryStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, previewToken);
      writeCookieToken(PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, previewToken);
      removeStorageToken(previewRuntimeTokenStorage?.legacyStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY);
    }

    return previewToken;
  }

  const registeredTokenStorage = getRegisteredTokenStorage();
  const storedToken = readStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
  const cookieStoredToken = readCookieToken(TOKEN_ACCESS_STORAGE_KEY);

  if (storedToken) {
    writeCookieToken(TOKEN_ACCESS_STORAGE_KEY, storedToken);
    removeStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
  } else {
    const legacyStoredToken = readStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);

    if (legacyStoredToken) {
      writeStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY, legacyStoredToken);
      writeCookieToken(TOKEN_ACCESS_STORAGE_KEY, legacyStoredToken);
      removeStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
      return legacyStoredToken;
    }

    if (cookieStoredToken) {
      writeStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY, cookieStoredToken);
      removeStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
      return cookieStoredToken;
    }
  }

  if (window.location.origin === PREVIEW_APP_ORIGIN && storedToken !== ALLOWED_REGISTRATION_TOKEN) {
    writeStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY, ALLOWED_REGISTRATION_TOKEN);
    writeCookieToken(TOKEN_ACCESS_STORAGE_KEY, ALLOWED_REGISTRATION_TOKEN);
    removeStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
    return ALLOWED_REGISTRATION_TOKEN;
  }

  return storedToken;
}

export function hasRegisteredAccessTokenAccess() {
  return isAllowedRegistrationToken(getRegisteredAccessToken());
}

export function setRegisteredAccessToken(token: string | null | undefined) {
  if (typeof window === 'undefined') {
    return;
  }

  const normalizedToken = normalizeToken(token);

  if (isPreviewRuntime()) {
    const previewRuntimeTokenStorage = getPreviewRuntimeTokenStorage();
    previewRuntimeTokenMemory = normalizedToken;
    writeStorageToken(previewRuntimeTokenStorage?.primaryStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, normalizedToken);
    writeCookieToken(PREVIEW_RUNTIME_TOKEN_STORAGE_KEY, normalizedToken);
    removeStorageToken(previewRuntimeTokenStorage?.legacyStorage ?? null, PREVIEW_RUNTIME_TOKEN_STORAGE_KEY);
  } else {
    const registeredTokenStorage = getRegisteredTokenStorage();
    writeStorageToken(registeredTokenStorage?.primaryStorage ?? null, TOKEN_ACCESS_STORAGE_KEY, normalizedToken);
    writeCookieToken(TOKEN_ACCESS_STORAGE_KEY, normalizedToken);
    removeStorageToken(registeredTokenStorage?.legacyStorage ?? null, TOKEN_ACCESS_STORAGE_KEY);
  }

  window.dispatchEvent(new CustomEvent(TOKEN_ACCESS_SYNC_EVENT));
}

export function useTokenAccess() {
  const [registeredToken, setRegisteredToken] = useState(() => getRegisteredAccessToken());

  useEffect(() => {
    if (typeof window === 'undefined') {
      return undefined;
    }

    const syncRegisteredToken = () => {
      setRegisteredToken(getRegisteredAccessToken());
    };

    window.addEventListener('storage', syncRegisteredToken);
    window.addEventListener(TOKEN_ACCESS_SYNC_EVENT, syncRegisteredToken);

    return () => {
      window.removeEventListener('storage', syncRegisteredToken);
      window.removeEventListener(TOKEN_ACCESS_SYNC_EVENT, syncRegisteredToken);
    };
  }, []);

  return {
    registeredToken,
    hasAccess: isAllowedRegistrationToken(registeredToken),
  };
}
