import { Path, resolvePath } from 'react-router-dom';
import { URLPreset } from 'ontime-types';

/**
 * Validates a preset against defined parameters
 * Used in the context of form validation
 */
export function validateUrlPresetPath(preset: string): { message: string; isValid: boolean } {
  if (preset === '' || preset == null) {
    return { isValid: false, message: 'Path cannot be empty' };
  }

  if (preset.includes('http') || preset.includes('https') || preset.includes('www')) {
    return { isValid: false, message: 'Path should not include http, https, www' };
  }

  if (preset.includes('127.0.0.1') || preset.includes('localhost') || preset.includes('0.0.0.0')) {
    return { isValid: false, message: 'Path should not include hostname' };
  }

  if (preset.includes('editor')) {
    // no editor
    return { isValid: false, message: 'No path to editor page allowed' };
  }

  return { isValid: true, message: 'ok' };
}

/**
 * Utility removes trailing slash from a string
 */
function removeTrailingSlash(text: string): string {
  return text.replace(/\/$/, '');
}

/**
 * Checks whether the current location corresponds to a preset and returns the new path if necessary
 */
export function getRouteFromPreset(location: Path, urlPresets: URLPreset[]): string | null {
  // current url is the pathname without the leading slash
  const currentURL = location.pathname.substring(1);
  const searchParams = new URLSearchParams(location.search);

  // check if we have token or locked in the search params
  const locked = searchParams.get('locked');
  const token = searchParams.get('token');

  // we need to check if the whole url is an alias
  const foundPreset = urlPresets.find((preset) => preset.alias === removeTrailingSlash(currentURL) && preset.enabled);
  if (foundPreset) {
    // if so, we can redirect to the preset path
    return generatePathFromPreset(foundPreset.pathAndParams, foundPreset.alias, locked, token);
  }

  // if the current url is not an alias, we check if the alias is in the search parameters
  const presetOnPage = searchParams.get('alias');
  if (!presetOnPage) {
    return null;
  }

  const currentPath = `${location.pathname}${location.search}`.substring(1);

  for (const preset of urlPresets) {
    // if the page has a known enabled alias, we check if we need to redirect
    if (preset.alias === presetOnPage && preset.enabled) {
      const newPath = generatePathFromPreset(preset.pathAndParams, preset.alias, locked, token);
      if (!arePathsEquivalent(currentPath, newPath)) {
        // if current path is out of date
        // return new path so we can redirect
        return newPath;
      }
    }
  }
  return null;
}

/**
 * Handles generating a path and search parameters from a preset
 */
export function generatePathFromPreset(pathAndParams: string, alias: string, locked: string | null, token: string | null ): string {
  const path = resolvePath(pathAndParams);
  const searchParams = new URLSearchParams(path.search);

  // save the alias so we have a reference to it being a preset and can update if necessary
  searchParams.set('alias', alias);

  // maintain params from the URL search feature
  if (locked) {
    searchParams.set('locked', locked);
  }

  if (token) {
    searchParams.set('token', token);
  }

  // return path concatenated without the leading slash
  return `${path.pathname}?${searchParams}`.substring(1);
}

/**
 * Utility checks if two paths are equivalent
 * Considers the edge cases for url sharing where a path may contain extra arguments from the alias
 * - token
 * - locked
 */
export function arePathsEquivalent(currentPath: string, newPath: string): boolean {
  const currentUrl = new URL(currentPath, document.location.origin);
  const newUrl = new URL(newPath, document.location.origin);
  
  // check path
  if (currentUrl.pathname !== newUrl.pathname) {
    return false
  }

  // check search params
  // if the params match, we dont need further checks
  if (currentUrl.searchParams.toString() === newUrl.searchParams.toString()) {
    return true
  }

  // if there is no match, we check the edge cases for the url sharing feature
  currentUrl.searchParams.delete('token');
  currentUrl.searchParams.delete('locked');

  return currentUrl.searchParams.toString() === newUrl.searchParams.toString();
}
