declare const window: Window & typeof globalThis;

const { port, hostname } = window.location;
let protocol = 'https';

declare global {
  interface SpiffworkflowFrontendJsenvObject {
    [key: string]: string;
  }
  interface Window {
    spiffworkflowFrontendJsenv: SpiffworkflowFrontendJsenvObject;
  }
}

let spiffEnvironment = '';
let appRoutingStrategy = 'subdomain_based';
let backendBaseUrl = null;
let documentationUrl = null;
if ('spiffworkflowFrontendJsenv' in window) {
  if ('APP_ROUTING_STRATEGY' in window.spiffworkflowFrontendJsenv) {
    appRoutingStrategy = window.spiffworkflowFrontendJsenv.APP_ROUTING_STRATEGY;
  }
  if ('ENVIRONMENT_IDENTIFIER' in window.spiffworkflowFrontendJsenv) {
    spiffEnvironment = window.spiffworkflowFrontendJsenv.ENVIRONMENT_IDENTIFIER;
  }
  if ('BACKEND_BASE_URL' in window.spiffworkflowFrontendJsenv) {
    backendBaseUrl = window.spiffworkflowFrontendJsenv.BACKEND_BASE_URL;
  }
  if ('DOCUMENTATION_URL' in window.spiffworkflowFrontendJsenv) {
    documentationUrl = window.spiffworkflowFrontendJsenv.DOCUMENTATION_URL;
  }
}

if (!backendBaseUrl) {
  let hostAndPortAndPathPrefix;
  if (appRoutingStrategy === 'subdomain_based') {
    hostAndPortAndPathPrefix = `api.${hostname}`;
  } else if (appRoutingStrategy === 'path_based') {
    hostAndPortAndPathPrefix = `${hostname}/api`;
  } else {
    throw new Error(`Invalid app routing strategy: ${appRoutingStrategy}`);
  }

  if (/^\d+\./.test(hostname) || hostname === 'localhost') {
    let serverPort = 7000;
    if (!Number.isNaN(Number(port))) {
      serverPort = Number(port) - 1;
    }
    hostAndPortAndPathPrefix = `${hostname}:${serverPort}`;
    protocol = 'http';

    if (spiffEnvironment === '') {
      // using destructuring on an array where we only want the first element
      // seems super confusing for non-javascript devs to read so let's NOT do that.
      // eslint-disable-next-line prefer-destructuring
      spiffEnvironment = hostname.split('.')[0];
    }
  }

  backendBaseUrl = `${protocol}://${hostAndPortAndPathPrefix}/v1.0`;
}

if (!backendBaseUrl.endsWith('/v1.0')) {
  backendBaseUrl += '/v1.0';
}

const BACKEND_BASE_URL = backendBaseUrl;
const DOCUMENTATION_URL = documentationUrl;

const PROCESS_STATUSES = [
  'complete',
  'error',
  'not_started',
  'running',
  'suspended',
  'terminated',
  'user_input_required',
  'waiting',
];

// with time: yyyy-MM-dd HH:mm:ss
let generalDateFormat = 'yyyy-MM-dd';
if (
  'spiffworkflowFrontendJsenv' in window &&
  'DATE_FORMAT' in window.spiffworkflowFrontendJsenv
) {
  generalDateFormat = window.spiffworkflowFrontendJsenv.DATE_FORMAT;
}

const splitDateFormat = generalDateFormat.split('-');

// https://date-fns.org/v3.0.6/docs/format
const supportedDateFormatTypes = {
  yyyy: '2024',
  MM: '01',
  MMM: 'Jan',
  MMMM: 'January',
  dd: '01',
};
const unsupportedFormatTypes = splitDateFormat.filter(
  (x) => !Object.keys(supportedDateFormatTypes).includes(x),
);
const formattedSupportedDateTypes: string[] = [];
Object.entries(supportedDateFormatTypes).forEach(([key, value]) => {
  formattedSupportedDateTypes.push(`${key}: ${value}`);
});
if (unsupportedFormatTypes.length > 0) {
  throw new Error(
    `Given SPIFFWORKFLOW_FRONTEND_RUNTIME_CONFIG_DATE_FORMAT is not supported. Given: ${generalDateFormat} with invalid options: ${unsupportedFormatTypes.join(
      ', ',
    )}. Valid options are: ${formattedSupportedDateTypes.join(', ')}`,
  );
}
const carbonDateFormat = generalDateFormat
  .replace(/\byyyy\b/, 'Y')
  .replace(/\bMM\b/, 'm')
  .replace(/\bMMM\b/, 'M')
  .replace(/\bMMMM\b/, 'F')
  .replace(/\bdd\b/, 'd');
const DATE_TIME_FORMAT = `${generalDateFormat} HH:mm:ss`;
const TIME_FORMAT_HOURS_MINUTES = 'HH:mm';
const DATE_FORMAT = generalDateFormat;
const DATE_FORMAT_CARBON = carbonDateFormat;
const DATE_FORMAT_FOR_DISPLAY = generalDateFormat.toLowerCase();
const DATE_RANGE_DELIMITER = ':::';

const SPIFF_ENVIRONMENT = spiffEnvironment;
export {
  DATE_TIME_FORMAT,
  TIME_FORMAT_HOURS_MINUTES,
  DATE_FORMAT,
  DATE_FORMAT_CARBON,
  DATE_FORMAT_FOR_DISPLAY,
  DATE_RANGE_DELIMITER,
  BACKEND_BASE_URL,
  DOCUMENTATION_URL,
  PROCESS_STATUSES,
  SPIFF_ENVIRONMENT,
};
