import type { FeatureFilters, FeatureMeta } from '../types';

export const ETHNICITIES_FILTER_NAME = 'Ethnicities';
export const ETHNICITIES_FILTER_KEY_PREFIX = `${ETHNICITIES_FILTER_NAME}:`;

export const ETHNICITY_FEATURE_NAMES = [
  '% White',
  '% South Asian',
  '% East Asian',
  '% SE Asian',
  '% Black',
  '% Mixed',
  '% Other',
] as const;

const ETHNICITY_FEATURE_NAME_SET = new Set<string>(ETHNICITY_FEATURE_NAMES);

export function isEthnicityFeatureName(name: string): boolean {
  return ETHNICITY_FEATURE_NAME_SET.has(name);
}

export function isEthnicityFilterName(name: string): boolean {
  return isEthnicityFeatureName(name) || name.startsWith(ETHNICITIES_FILTER_KEY_PREFIX);
}

export function createEthnicityFilterKey(featureName: string, id: number | string): string {
  return `${ETHNICITIES_FILTER_KEY_PREFIX}${encodeURIComponent(featureName)}:${id}`;
}

export function getEthnicityFilterKeyId(name: string): string | null {
  if (!name.startsWith(ETHNICITIES_FILTER_KEY_PREFIX)) return null;
  const rest = name.substring(ETHNICITIES_FILTER_KEY_PREFIX.length);
  const lastColon = rest.lastIndexOf(':');
  return lastColon === -1 ? null : rest.substring(lastColon + 1);
}

export function parseEthnicityFilterKey(name: string): string | null {
  if (!name.startsWith(ETHNICITIES_FILTER_KEY_PREFIX)) return null;
  const rest = name.substring(ETHNICITIES_FILTER_KEY_PREFIX.length);
  const lastColon = rest.lastIndexOf(':');
  if (lastColon === -1) return null;

  const decoded = decodeURIComponent(rest.substring(0, lastColon));
  return isEthnicityFeatureName(decoded) ? decoded : null;
}

export function getEthnicityFeatureName(name: string): string | null {
  if (isEthnicityFeatureName(name)) return name;
  return parseEthnicityFilterKey(name);
}

export function replaceEthnicityFilterKeySelection(key: string, featureName: string): string {
  const id = getEthnicityFilterKeyId(key) ?? '0';
  return createEthnicityFilterKey(featureName, id);
}

export function getDefaultEthnicityFeatureName(features: FeatureMeta[]): string | null {
  return (
    ETHNICITY_FEATURE_NAMES.find((name) => features.some((feature) => feature.name === name)) ??
    null
  );
}

export function normalizeEthnicityFilters(filters: FeatureFilters): FeatureFilters {
  let changed = false;
  const next: FeatureFilters = {};

  for (const [name, value] of Object.entries(filters)) {
    if (isEthnicityFeatureName(name)) {
      next[createEthnicityFilterKey(name, Object.keys(next).length)] = value;
      changed = true;
      continue;
    }
    next[name] = value;
  }

  return changed ? next : filters;
}

export function getEthnicityFilterMeta(features: FeatureMeta[]): FeatureMeta {
  const sourceFeatureName = getDefaultEthnicityFeatureName(features);
  const sourceFeature = sourceFeatureName
    ? features.find((feature) => feature.name === sourceFeatureName)
    : undefined;

  return {
    name: ETHNICITIES_FILTER_NAME,
    type: 'numeric',
    group: 'Neighbours',
    min: sourceFeature?.min ?? 0,
    max: sourceFeature?.max ?? 100,
    step: 0.1,
    description: 'Population percentage by ethnic group',
    detail: 'Filter by one Census 2021 ethnicity percentage at a time.',
    source: 'ethnicity',
    suffix: '%',
  };
}

export function clampEthnicityRange(
  value: [number, number],
  feature?: FeatureMeta
): [number, number] {
  const min = feature?.histogram?.min ?? feature?.min ?? 0;
  const max = feature?.histogram?.max ?? feature?.max ?? Math.max(1, value[1]);
  return [Math.max(min, Math.min(value[0], max)), Math.max(min, Math.min(value[1], max))];
}
