import { loadCalculators, type CalculatorDef } from './calculatorLoader';

const domainDefinitions: Record<string, { summary: string; context: string }> = {
  length: {
    summary: 'describes the linear or spatial distance between two points.',
    context: 'Use it when explaining how far apart objects are, how long surfaces run, or how tall structures rise.',
  },
  weight: {
    summary: 'quantifies mass or the gravitational force exerted on an object.',
    context: 'Apply these units when comparing loads, weights on a scale, or quantities of matter.',
  },
  temperature: {
    summary: 'captures thermal energy along a fixed scale such as Celsius, Fahrenheit, or Kelvin.',
    context: 'They help compare how warm or cold something is and how heat flows between systems.',
  },
  volume: {
    summary: 'measures three-dimensional capacity inside containers or spaces.',
    context: 'Useful for describing liquids, gases, or any amount of space you can fill.',
  },
  fluids: {
    summary: 'captures flow rates, flux densities, and transport-related metrics.',
    context: 'Reach for these units when comparing pumps, pipes, or any movement of liquids, gases, or charged particles across an area.',
  },
  area: {
    summary: 'tracks two-dimensional surface coverage.',
    context: 'Helpful when sizing plots of land, floor space, or sheets of material.',
  },
  speed: {
    summary: 'expresses how quickly an object changes position relative to time.',
    context: 'Speed and velocity units tell you how fast you are moving across a distance or around a path.',
  },
  pressure: {
    summary: 'quantifies the amount of force applied over a specific unit of area.',
    context: 'Essential when working with gases, fluids, or loads pressing onto a surface.',
  },
  energy: {
    summary: 'represents the capacity to do work or release heat.',
    context: 'Energy units compare calories, joules, or BTUs when tracking work, heat, or stored energy.',
  },
  magnetism: {
    summary: 'captures magnetic intensity, flux, and field density.',
    context: 'Use these units when comparing magnets, coils, or magnetic flux through areas and materials.',
  },
  power: {
    summary: 'measures the rate at which energy is transferred or converted.',
    context: 'Use them to compare engines, appliances, or systems that deliver energy over time.',
  },
  data: {
    summary: 'counts digital information in bytes, bits, or other storage grains.',
    context: 'Data units help you compare file sizes, bandwidth, and storage capacity.',
  },
  time: {
    summary: 'denotes duration, intervals, or counts of ticks such as seconds, minutes, and hours.',
    context: 'These units frame anything that changes over time or requires scheduling.',
  },
  angle: {
    summary: 'measures rotation between two rays or the sweep of a circle.',
    context: 'Angle units are useful for describing turns, sweeps, bearings, and geometric layouts.',
  },
  'number-systems': {
    summary: 'names positional numeral systems such as binary, decimal, or hexadecimal.',
    context: 'They specify the base used to represent integers and guide how digits are interpreted.',
  },
  radiation: {
    summary: 'records ionizing emissions or the absorbed dose from radioactive sources.',
    context: 'Radiation units show how much exposure, decay, or energy deposition is happening.',
  },
  electrical: {
    summary: 'covers electrical quantities like current, voltage, resistance, and capacitance.',
    context: 'They keep circuit values aligned so you can balance loads, voltages, and energy transfer.',
  },
  force: {
    summary: 'describes pushes, pulls, or torque applied to an object.',
    context: 'Force units help you quantify mechanical effort, tension, or rotation in machines and systems.',
  },
  light: {
    summary: 'relates to luminous intensity, illuminance, or optical flux.',
    context: 'Use them to describe brightness, how much light reaches a surface, or the output of a lamp.',
  },
  other: {
    summary: 'covers specialized metrics that do not neatly fit the standard categories.',
    context: 'That includes frequencies, compound conversions, and other domain-specific scales such as RPM or wavelength.',
  },
};

const canonicalLabelAliases: Record<string, string> = {
  pascals: 'Pascal',
  gills: 'Gill',
  newtons: 'Newton',
};

const normalizeLabel = (label?: string): string | undefined => {
  if (!label) return undefined;
  const trimmed = label.trim();
  if (!trimmed) return undefined;
  const alias = canonicalLabelAliases[trimmed.toLowerCase()];
  return alias ?? trimmed;
};

const categoryPriority = [...Object.keys(domainDefinitions)];

const specificDefinitions: Array<[RegExp, string]> = [
  [/\bwatts?\b|\bkilowatts?\b|\bmegawatts?\b|\bhorsepower\b/i, 'measures the rate at which energy is transferred or converted. It is used for engines, appliances, electrical loads, and heat-transfer rates.'],
  [/\bcalories?\b|\bjoules?\b|\bbtu\b|\bkilocalories?\b|\btherms?\b|\bwatt hours?\b|\bkilowatt hours?\b/i, 'measures energy, heat, or work. These units are used for food energy, physics calculations, heating systems, and stored electricity.'],
  [/\bvolts?\b/i, 'measures electric potential difference. Voltage describes the electrical pressure that pushes current through a circuit.'],
  [/\bamps?\b|\bamperes?\b/i, 'measures electric current. Current describes how much electric charge flows through a circuit each second.'],
  [/\bohms?\b/i, 'measures electrical resistance. Resistance describes how strongly a component opposes current flow.'],
  [/\bfarads?\b/i, 'measures capacitance. Capacitance describes how much electric charge a component can store for a given voltage.'],
  [/\bhenr(y|ies)\b/i, 'measures inductance. Inductance describes how strongly a circuit resists changes in current.'],
  [/\bpascal|bar|psi|atmosphere|mmhg|torr|inches of water|inches of mercury/i, 'measures pressure, or force applied over an area. Pressure units are common in fluids, gases, weather, vacuum systems, and mechanical specifications.'],
  [/\bcubic\b|\bliters?\b|\bgallons?\b|\bcups?\b|\bpints?\b|\bquarts?\b|\bfluid\b|\bbushels?\b|\bpecks?\b|\bacre[- ]feet\b|\bacre[- ]foot\b/i, 'measures volume or capacity. Volume units describe liquids, gases, containers, flow totals, and three-dimensional space.'],
  [/\bsquare\b|\bacres?\b|\bhectares?\b|\bares?\b|\bbarns?\b|\bsections?\b|\btownships?\b/i, 'measures area or surface coverage. Area units are used for land, floors, materials, and two-dimensional spaces.'],
  [/\bmeters per second\b|\bmiles per hour\b|\bkilometers per hour\b|\bfeet per second\b|\bknots?\b|\bmach\b|\brpm\b/i, 'measures speed, velocity, or rotation rate. These units describe motion over distance or repeated turns over time.'],
  [/\bseconds?\b|\bminutes?\b|\bhours?\b|\bdays?\b|\bweeks?\b|\bmonths?\b|\byears?\b/i, 'measures time or duration. Time units describe intervals, schedules, rates, and elapsed periods.'],
  [/\bdegrees?\b|\bradians?\b|\bgradians?\b|\barcminutes?\b|\barcseconds?\b/i, 'measures angle or rotation. Angle units describe turns, bearings, geometry, and circular motion.'],
  [/\bgrams?\b|\bkilograms?\b|\bpounds?\b|\bounces?\b|\bcarats?\b|\btons?\b|\bdaltons?\b|\bamu\b/i, 'measures mass or weight. These units are used for materials, ingredients, shipping weights, laboratory quantities, and scientific mass scales.'],
  [/\bbytes?\b|\bbits?\b|\bnibbles?\b|\bkilobytes?\b|\bmegabytes?\b|\bgigabytes?\b|\bterabytes?\b|\bkibibytes?\b|\bmebibytes?\b|\bgibibytes?\b/i, 'measures digital information or storage size. Data units are used for files, memory, transfer sizes, and storage devices.'],
  [/\bbinary\b|\boctal\b|\bdecimal\b|\bhex\b|\bhexadecimal\b|\bascii\b/i, 'is a representation format for numbers or text. These systems define how values are encoded, displayed, or interpreted.'],
  [/\bbecquerel|curie|gray|rad|sievert|rem|roentgen|rutherford/i, 'measures radioactivity, absorbed dose, or exposure. Radiation units describe decay rates, ionizing energy, and biological dose effects.'],
];

const buildDefinition = (label: string, categoryKey: string): string => {
  if (!label) return '';
  const specific = specificDefinitions.find(([pattern]) => pattern.test(label));
  if (specific) return `${label} ${specific[1]}`;

  const domain = domainDefinitions[categoryKey] || domainDefinitions.other;
  const description = [domain.summary, domain.context].filter(Boolean).join(' ');
  return `${label} ${description}`;
};

// Lazily built definitions cache
let definitions: Record<string, Record<string, string>> | null = null;
let buildPromise: Promise<void> | null = null;

async function ensureBuilt(): Promise<Record<string, Record<string, string>>> {
  if (definitions) return definitions;
  if (buildPromise) {
    await buildPromise;
    return definitions!;
  }

  buildPromise = loadCalculators().then(calculators => {
    const defs: Record<string, Record<string, string>> = {};
    calculators.forEach(calc => {
      const { category, labels } = calc;
      Object.values(labels).forEach(label => {
        const normalized = normalizeLabel(label);
        if (!normalized) return;
        const bucket = defs[normalized] || {};
        const text = buildDefinition(normalized, category);
        bucket[category] = text;
        defs[normalized] = bucket;
      });
    });
    definitions = defs;
  });

  await buildPromise;
  return definitions!;
}

const findByPriority = (entries: Record<string, string>, preferred?: string): string | undefined => {
  if (!entries) return undefined;
  if (preferred && entries[preferred]) return entries[preferred];
  for (const category of categoryPriority) {
    if (entries[category]) return entries[category];
  }
  const fallback = Object.values(entries).filter(Boolean);
  return fallback.length ? fallback[0] : undefined;
};

export async function getDefinition(label: string, category?: string): Promise<string | undefined> {
  const normalized = normalizeLabel(label);
  if (!normalized) return undefined;
  const defs = await ensureBuilt();
  const entries = defs[normalized];
  return findByPriority(entries, category);
}
