import type { FeatureFilters, FeatureMeta } from '../types';
import type { VariantFilterConfig } from './variant-filter';

export const QUALIFICATIONS_FILTER_NAME = 'Qualifications';
export const QUALIFICATIONS_FILTER_KEY_PREFIX = `${QUALIFICATIONS_FILTER_NAME}:`;

/**
 * The Census 2021 "highest level of qualification" bands (TS067). They sum to
 * 100% per neighbourhood and render as a single stacked "Qualifications"
 * composition in the area pane (see STACKED_GROUPS["Neighbours"] in consts.ts).
 * In the filter browser they fold into one "Qualifications" filter whose
 * dropdown selects a band — including "% Degree or higher" — rather than seven
 * separate sliders.
 */
export const QUALIFICATION_FEATURE_NAMES = [
  '% No qualifications',
  '% Some GCSEs',
  '% Good GCSEs',
  '% Apprenticeship',
  '% A-levels',
  '% Degree or higher',
  '% Other qualifications',
] as const;

const QUALIFICATION_FEATURE_NAME_SET = new Set<string>(QUALIFICATION_FEATURE_NAMES);

export function isQualificationFeatureName(name: string): boolean {
  return QUALIFICATION_FEATURE_NAME_SET.has(name);
}

export function isQualificationFilterName(name: string): boolean {
  return isQualificationFeatureName(name) || name.startsWith(QUALIFICATIONS_FILTER_KEY_PREFIX);
}

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

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

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

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

export function getQualificationFeatureName(name: string): string | null {
  if (isQualificationFeatureName(name)) return name;
  return parseQualificationFilterKey(name);
}

export function replaceQualificationFilterKeySelection(key: string, featureName: string): string {
  const id = getQualificationFilterKeyId(key) ?? '0';
  return createQualificationFilterKey(featureName, id);
}

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

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

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

  return changed ? next : filters;
}

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

  return {
    name: QUALIFICATIONS_FILTER_NAME,
    type: 'numeric',
    group: 'Neighbours',
    min: sourceFeature?.min ?? 0,
    max: sourceFeature?.max ?? 100,
    step: 1,
    description:
      'Share of residents (16+) by highest qualification, from no qualifications to a degree or higher',
    detail:
      'Filter by one Census 2021 (TS067) highest-qualification band at a time, e.g. the percentage of residents whose highest qualification is a degree or higher.',
    source: 'census-2021',
    suffix: '%',
  };
}

export function clampQualificationRange(
  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))];
}

export const QUALIFICATION_VARIANT_CONFIG: VariantFilterConfig = {
  filterName: QUALIFICATIONS_FILTER_NAME,
  featureNames: QUALIFICATION_FEATURE_NAMES,
  dropdownLabelKey: 'filters.qualificationLevel',
  getFilterMeta: getQualificationFilterMeta,
  getDefaultFeatureName: getDefaultQualificationFeatureName,
  getFeatureName: getQualificationFeatureName,
  replaceFilterKeySelection: replaceQualificationFilterKeySelection,
  clampRange: clampQualificationRange,
};
