import { createContext, useContext, useMemo, useState } from "react";
import type React from "react";
import {
  accommodationLabels as nbAccommodationLabels,
  categoryTooltipTexts as nbCategoryTooltipTexts,
  delayedSymptomLabels as nbDelayedSymptomLabels,
  limitationLabels as nbLimitationLabels,
  negativeScale as nbNegativeScale,
  positiveScale as nbPositiveScale,
  recoveryLabels as nbRecoveryLabels,
  statusLabels as nbStatusLabels,
  taskCompletionLabels as nbTaskCompletionLabels,
  taskTypeLabels as nbTaskTypeLabels,
  tooltipTexts as nbTooltipTexts,
  worseLabels as nbWorseLabels
} from "./labels";
import type {
  Accommodation,
  DelayedSymptom,
  Limitation,
  RecoveryStatus,
  ReportStatus,
  ScaleValue,
  TaskCompletion,
  TaskType,
  VerificationStatus,
  WorseThanBefore
} from "./types";
import {
  ukAccommodationLabels,
  ukCategoryTooltipTexts,
  ukDelayedSymptomLabels,
  ukLimitationLabels,
  ukNegativeScale,
  ukPositiveScale,
  ukRecoveryLabels,
  ukStatusLabels,
  ukTaskCompletionLabels,
  ukTaskTypeLabels,
  ukTooltipTexts,
  ukWorseLabels
} from "./labels.uk";
import { uk } from "./i18n.uk";

export type Language = "nb-NO" | "en" | "uk-UA";

const LANGUAGE_KEY = "arbeidspuls.language";

export type TranslationTree = { [key: string]: string | TranslationTree };

export const supportedLanguages = [
  { code: "nb-NO", nativeName: "Norsk", flag: "🇳🇴" },
  { code: "en", nativeName: "English", flag: "🇬🇧" },
  { code: "uk-UA", nativeName: "Українська", flag: "🇺🇦" }
] as const satisfies ReadonlyArray<{ code: Language; nativeName: string; flag: string }>;

const nb = {
  common: {
    cancel: "Avbryt",
    close: "Lukk",
    copied: "Kopiert",
    delete: "Slett",
    save: "Lagre",
    notSelected: "Ikke valgt",
    notProvided: "Ikke oppgitt",
    notCalculated: "Ikke beregnet",
    unknownWorkplace: "Ukjent arbeidssted"
  },
  app: {
    eyebrow: "Lokal egenvurdering",
    title: "Arbeidspuls",
    evaluator: "Veileder",
    navLabel: "Hovednavigasjon"
  },
  nav: {
    register: "Registrer",
    followup: "Oppfølging",
    overview: "Oversikt",
    privacy: "Personvern"
  },
  demo: {
    enter: "Demo",
    exit: "Forlat demo",
    label: "Demodata",
    notice: "Du er i demo-modus. Data her er adskilt fra dine faktiske rapporter, og eksport/import gjelder bare demodata."
  },
  footer: {
    norwegian: "Norsk",
    english: "English",
    ukrainian: "Українська",
    switchToNorwegian: "Bytt språk til norsk",
    switchToEnglish: "Switch language to English",
    switchToUkrainian: "Bytt språk til ukrainsk",
    developedBy: "Utviklet av Rolfsvaag Datateknikk med",
    heart: "hjerte",
    languageChoice: "Språkvalg",
    sourceCode: "Kildekode v.{version}",
    commercialLicense: "Særlisens"
  },
  feedback: {
    button: "Tilbakemelding",
    buttonAria: "Send anonym tilbakemelding",
    title: "Send tilbakemelding",
    stepOne: "1 av 2: Beskriv tilbakemeldingen",
    stepTwo: "2 av 2: Bekreft offentlig innsending",
    intro: "Tilbakemeldingen opprettes som offentlig issue hvis den blir godkjent av valideringen.",
    typeLabel: "Type",
    typeBug: "Feil eller problem",
    typeFeature: "Forslag til forbedring",
    typeDocs: "Dokumentasjon eller tekst",
    typeTask: "Generell oppgave",
    typeOther: "Annet",
    questionsNotice: "Spørsmål bør sendes direkte til prosjektansvarlig, ikke som offentlig prosjektfeedback.",
    areaLabel: "Område",
    technicalAreas: "Tekniske kategorier",
    areaReporting: "Registrering av rapport",
    areaFollowup: "Oppfølging",
    areaGraph: "Oversikt og graf",
    areaAdvisor: "Veiledervisning",
    areaImportExport: "Import, eksport og deling",
    areaI18n: "Språk og oversettelse",
    areaPrivacy: "Personvern og lokal lagring",
    areaUi: "Utseende og brukervennlighet",
    areaAccessibility: "Tilgjengelighet",
    areaLegal: "Juridisk eller lisens",
    areaApi: "API",
    areaBackend: "Backend/server",
    areaDeployment: "Drift og deploy",
    areaPwa: "Installasjon som app/PWA",
    areaSecurity: "Sikkerhet",
    areaPerformance: "Ytelse",
    legalNotice: "Særlisens eller kommersiell bruk må tas direkte med prosjektansvarlig.",
    commercialLicenseLink: "Les om særlisens og kommersiell bruk.",
    messageLabel: "Beskrivelse",
    messagePlaceholder: "Beskriv hva som skjedde, hva du forventet, eller hva du foreslår.",
    validationTitle: "Krav til beskrivelsen",
    validationMinChars: "Skriv minst 30 tegn.",
    validationMaxChars: "Maks 4000 tegn.",
    validationMinWords: "Skriv minst 5 ord.",
    validationMinLetters: "Skriv minst 15 bokstaver.",
    validationMeaningful: "Teksten må inneholde meningsfullt innhold, ikke bare tall eller symboler.",
    validationRepetition: "Teksten kan ikke bestå av gjentakelser.",
    validationContact: "Fjern e-post, telefonnummer, IP-adresse eller lange tallsekvenser.",
    validationType: "Velg nøyaktig én type.",
    validationArea: "Velg minst ett område.",
    publicNotice:
      "Tilbakemeldinger kan bli opprettet som offentlige saker i prosjektets issue-liste. Ikke skriv sensitive opplysninger, rapportinnhold, navn på personer eller organisasjoner, e-post, telefonnummer eller annen informasjon som kan identifisere deg eller andre.",
    purposeNotice: "Tilbakemeldingen brukes kun til å forbedre Arbeidspuls.",
    consent:
      "Jeg bekrefter at tilbakemeldingen ikke inneholder sensitiv eller identifiserbar informasjon, og at innholdet kan behandles, lagres og vises offentlig som ordinær prosjektfeedback.",
    back: "Tilbake",
    continue: "Fortsett",
    submit: "Send inn",
    submitWaiting: "Send inn ({secondsLeft})",
    cancel: "Avbryt",
    success: "Takk. Tilbakemeldingen er sendt inn.",
    fakeSuccess: "Takk. Tilbakemeldingen er mottatt.",
    disabled: "Tilbakemelding er ikke aktivert.",
    error: "Tilbakemeldingen kunne ikke sendes. Prøv igjen senere.",
    tooFast: "Vent litt før du sender inn skjemaet.",
    urlWarning: "URL-er er tillatt, men fjern sensitive lenker eller query-parametre."
  },
  deleteModal: {
    title: "Bekreft sletting",
    body: "Du er i ferd med å slette: {itemName}. Denne handlingen kan ikke angres.",
    waiting: "Slett ({secondsLeft})",
    ready: "Slett"
  },
  register: {
    intro: "Fyll ut hovedfeltene. Valgfrie detaljer kan legges til ved behov.",
    workSession: "Arbeidsøkt",
    workplace: "Arbeidssted",
    workAbility: "Arbeidsevne akkurat nå",
    energyLevel: "Energinivå",
    mentalClarity: "Mental klarhet / konsentrasjon",
    symptomBurden: "Symptombelastning",
    effortStrain: "Anstrengelse / belastning",
    optional: "Valgfritt",
    startTime: "Starttid",
    endTime: "Sluttid",
    continueQuestion: "Kan du fortsette?",
    chooseBestNow: "Velg det som passer best akkurat nå.",
    optionalDetails: "Valgfrie detaljer",
    physicalEnergy: "Fysisk energi",
    mentalEnergy: "Mental energi",
    productivity: "Opplevd produktivitet",
    taskCompletion: "Hvor mye fikk du gjort?",
    taskTypes: "Arbeidet innebar",
    limitations: "Hva begrenset deg mest?",
    accommodations: "Hva hjalp?",
    note: "Kort kommentar",
    missing: "Mangler: {fields}.",
    saved: "Rapport lagret lokalt.",
    saveReport: "Lagre rapport",
    oneEqualsFiveEquals: "1 = {low}, 5 = {high}."
  },
  followup: {
    intro: "Brukes neste dag eller senere for å fange forsinket reaksjon.",
    worseQuestion: "Er du verre enn før arbeidsøkten?",
    chooseOne: "Velg ett svar.",
    connectReport: "Knytt til rapport",
    delayedSymptoms: "Forsinkede symptomer",
    recovery: "Restitusjon",
    missingWorse: "Velg om du er verre enn før arbeidsøkten.",
    saved: "Oppfølging lagret lokalt.",
    saveFollowup: "Lagre oppfølging",
    orphan: "Oppfølging uten valgt hovedrapport",
    worsePrefix: "verre",
    latestOnly: "Oppfølging kan bare opprettes for nyeste rapport."
  },
  edit: {
    edit: "Rediger",
    reportIntro: "Rediger rapporten. Redigering er bare mulig innen 24 timer etter opprettelse.",
    followupIntro: "Rediger oppfølgingen. Redigering er bare mulig innen 24 timer etter opprettelse.",
    saveChanges: "Lagre endringer",
    saved: "Endringer lagret lokalt.",
    cancelEdit: "Avbryt redigering",
    expired: "Redigering er bare mulig innen 24 timer etter opprettelse."
  },
  overview: {
    noReports: "Ingen rapporter er lagret ennå.",
    report: "Rapport",
    followup: "Oppfølging",
    closeReport: "Lukk rapportvisning",
    trend: "Trend",
    explainTrend: "Forklar trendgraf",
    trendTooltip: "Grafen bruker normaliserte 0-100-verdier. Høyere verdi betyr bedre funksjon eller lavere belastning.",
    minimumTwo: "Minst to rapporter i valgt periode trengs for graf.",
    average: "Normalisert snitt i perioden",
    chartLabel: "Tidsbasert trendgraf for rapporter",
    dashedLine: "Striplet linje betyr at det er 3 dager eller mer mellom rapportene.",
    from: "Fra",
    to: "Til",
    fromDate: "Fra dato",
    toDate: "Til dato",
    datePlaceholder: "dd/mm/åååå",
    all: "Alt",
    week: "1 uke",
    month: "1 måned",
    threeMonths: "3 måneder",
    sixMonths: "6 måneder",
    year: "1 år",
    threeYears: "3 år",
    fiveYears: "5 år"
  },
  privacy: {
    warning: "Rapportene kan inneholde sensitive helseopplysninger. Arbeidspuls lagrer data lokalt som standard, med valgfri kryptert engangsdeling når du selv velger Send via e-post.",
    demoWarning: "Demo-modus bruker egen lokal lagring. Disse rapportene er testdata og blandes ikke med faktiske rapporter.",
    exportJson: "Eksporter JSON",
    exportEmail: "Send via e-post",
    exportRangeTitle: "Eksporter data",
    exportRangeIntro: "Velg eventuelt en periode for eksporten. Hvis ingen datoer velges, eksporteres all lokal data.",
    fromDate: "Fra dato",
    toDate: "Til dato",
    allDataDefault: "Standard: all data eksporteres.",
    exportInvalidRange: "Fra-dato kan ikke være etter til-dato.",
    exportSensitiveNotice: "Eksportfilen kan inneholde sensitive helse- og funksjonsopplysninger. Del den bare med personer som skal ha tilgang.",
    emailExportTitle: "Send data via e-post",
    recipientEmail: "Mottakers e-post",
    recipientPlaceholder: "veileder@example.com",
    openEmail: "Åpne e-post",
    invalidEmail: "Skriv inn en gyldig e-postadresse.",
    emailSubject: "Arbeidspuls-rapportdata for gjennomgang",
    emailShared: "Sikker deling er opprettet.",
    manualAttachmentRequired: "Kopier teksten manuelt hvis e-postklienten ikke åpnet riktig.",
    limitPeriod: "Begrens periode",
    allDataSelected: "All data er valgt som standard.",
    emailClientNotice: "For automatisk åpning må en e-postklient være satt opp på enheten din. Hvis dette ikke fungerer, får du en tekst du kan kopiere og lime inn manuelt.",
    serverStorageConsent: "Jeg forstår at valgt data midlertidig lagres kryptert og uleselig på Arbeidspuls-serveren for å opprette en engangslenke. Data slettes etter første vellykkede import eller etter 7 dager.",
    serverStorageConsentRequired: "Du må godkjenne midlertidig kryptert serverlagring før lenken opprettes.",
    createEmail: "Opprett e-post",
    emailLinkCreated: "E-postklient er forsøkt åpnet. Bruk copy-paste-teksten hvis den ikke ble fylt ut riktig.",
    emailLinkFailed: "Kunne ikke opprette sikker deling.",
    copyPasteBackupTitle: "Manuell e-posttekst",
    copyPasteBackupIntro: "Hvis e-postklienten ikke åpnet eller fylte inn teksten riktig, kopier mottaker, emne og tekst manuelt.",
    emailSubjectLabel: "Emne",
    emailBodyLabel: "E-posttekst",
    secureEmailBody:
      "Hei\n\nJeg deler Arbeidspuls-data med deg for gjennomgang.\n\nÅpne denne engangslenken for å hente og importere dataene i veiledervisning:\n{shareUrl}\n\nLenken kan brukes én gang og utløper automatisk etter 7 dager.\n\nSlik gjør du:\n1. Åpne lenken.\n2. Trykk på \"Hent og importer\".\n3. Se graf, rapporter og oppfølginger i veiledervisning.\n4. Du kan legge til egne notater ved behov.\n\nDataene lagres lokalt i din nettleser/enhet etter import. Arbeidspuls-serveren lagrer kun en midlertidig kryptert og uleselig kopi frem til dataene er hentet, eller i maksimalt 7 dager.\n\nArbeidspuls\n{appUrl}\n",
    importBackup: "Importer sikkerhetskopi",
    deleteAll: "Slett alle lokale data",
    importHelp: "Importer tidligere eksportert JSON hvis du har byttet enhet eller mistet lokale data. Importerte data lagres lokalt i denne nettleseren.",
    importFrom: "Importer data fra {fileName}",
    importStats:
      "Nye rapporter: {reports}. Nye oppfølginger: {followups}. Duplikater hoppet over: {duplicates}. Konflikter: {conflicts}.",
    demoImportWarning: "Importen inneholder {count} demodata-oppføringer og kan bare importeres i demo-modus.",
    cancelImport: "Avbryt import",
    importData: "Importer data",
    baseCopy:
      "Appen samler ikke inn navn, fødselsnummer eller kontaktinformasjon. Data lagres lokalt som standard. Ved Send via e-post krypteres valgt eksport i nettleseren før midlertidig opplasting. Fritekst er valgfritt og bør bare brukes når det er nødvendig.",
    storageTitle: "Hvor lagres dataene?",
    storageBody:
      "Rapportene lagres lokalt i nettleseren på enheten du bruker, i localStorage. Hvis du velger Send via e-post, lastes bare kryptert og uleselig delingsdata midlertidig opp til Arbeidspuls-serveren.",
    backupTitle: "Backup og enhetsbytte",
    backupBody:
      "Fordi dataene lagres lokalt, kan de gå tapt hvis du bytter enhet, sletter nettleserdata, bruker en annen nettleser eller tilbakestiller enheten. Eksporter JSON-fil jevnlig hvis du vil ta vare på rapportene.",
    sharingTitle: "Deling med veileder",
    sharingBody:
      "Hvis en veileder eller annen person skal gjennomgå rapportene, kan du eksportere en lokal JSON-fil eller bruke Send via e-post. E-postdeling lager en kryptert engangslenke der nøkkelen ligger i lenkefragmentet og aldri sendes til serveren.",
    sensitiveTitle: "Sensitive opplysninger",
    sensitiveBody:
      "Rapportene kan inneholde helse- og funksjonsrelatert informasjon. Del JSON-filer eller engangslenker bare med personer som faktisk skal ha tilgang. Krypterte delinger slettes etter første vellykkede import eller automatisk etter 7 dager.",
    exportIntegrity: "Eksport inkluderer lokal integritetskontroll der rapportene har verifiseringsdata.",
    deleteAllName: "alle lokale rapporter"
  },
  share: {
    title: "Arbeidspuls-deling",
    intro: "Du har åpnet en engangsdeling av Arbeidspuls-data.",
    activeImportNotice: "Delingen hentes ikke før du trykker på knappen. Data dekrypteres og importeres lokalt i veiledervisningen.",
    fetchAndImport: "Hent og importer",
    fetching: "Henter...",
    openAdvisor: "Åpne veiledervisning",
    alreadyDeleted: "Denne delingen er allerede hentet eller slettet.",
    expired: "Denne delingen er automatisk slettet fordi den er mer enn 7 dager gammel.",
    requestNewShare: "Be avsenderen opprette en ny deling hvis du fortsatt trenger tilgang.",
    missingKey: "Lenken mangler dekrypteringsnøkkel. Be avsenderen sende hele lenken på nytt.",
    missingConfirmToken: "Lenken mangler bekreftelseskode. Be avsenderen sende hele lenken på nytt.",
    decryptFailed: "Kunne ikke dekryptere delingen. Lenken kan være ufullstendig eller feil.",
    notFound: "Delingen finnes ikke.",
    imported: "Import fullført. Nye oppføringer: {reports}. Duplikater hoppet over: {skipped}."
  },
  evaluator: {
    eyebrow: "Veileder",
    title: "Veiledergjennomgang",
    backToApp: "Til appen",
    importJson: "Importer JSON",
    importHelp: "Velg en eksport fra appen. Data lagres lokalt i denne nettleseren.",
    displayName: "Navn/identifikator",
    optionalImportName: "Valgfritt ved import",
    connectExisting: "Knytt til eksisterende person",
    autoMatch: "Opprett ny eller bruk automatisk match",
    chooseJson: "Velg JSON-fil",
    exportBackup: "Eksporter veilederdata",
    importBackup: "Importer veilederbackup",
    importedBackup: "Veilederbackup er importert.",
    demoDataWarning: "Denne importen inneholder demodata. Ikke bruk den som faktisk bruker-/helsegrunnlag.",
    importStart: "Importer en JSON-fil for å starte gjennomgang.",
    saveName: "Lagre navn",
    deletePerson: "Slett bruker og rapporter",
    deletePersonTitle: "Sletter denne brukeren, importerte rapporter, oppfølginger og veiledernotater etter bekreftelse.",
    reportCount: "{count} rapporter",
    personNote: "Generelt notat for bruker",
    personNoteHelp: "Dette notatet gjelder personen som helhet, ikke én enkelt rapport.",
    saveNote: "Lagre notat",
    changedAt: "Sist endret: {time}",
    searchReports: "Søk i rapporter",
    newest: "Nyeste først",
    oldest: "Eldste først",
    noSelectedTitle: "Ingen rapport valgt",
    noSelectedBody: "Velg en rapport fra listen for å se detaljer, oppfølginger og notater.",
    details: "Vis detaljer",
    reportDetails: "Rapportdetaljer",
    followupDetails: "Oppfølgingsdetaljer",
    closeDetails: "Lukk detaljer",
    reportNote: "Notat til rapport",
    followupNote: "Notat til oppfølging",
    noteHelp: "Veiledernotatet lagres lokalt og endrer ikke importerte rapportdata.",
    deleteNote: "Slett notat",
    validationError: "Valideringsfeil",
    comment: "Kommentar",
    evaluatorNote: "Veiledernotat",
    followupNoteBadge: "Oppfølgingsnotat",
    hasFollowup: "Har oppfølging",
    hasComment: "Har brukerkommentar",
    hasEvaluatorNote: "Har veiledernotat",
    scoreValues: "Scoreverdier",
    importReadError: "Importfilen kunne ikke leses.",
    importMatched: "Importen ble knyttet til eksisterende bruker.",
    importCreated: "Opprettet ny bruker.",
    importFailed: "Import feilet.",
    backupFailed: "Backup kunne ikke importeres.",
    demoBackupWarning: "ADVARSEL: Backupen inneholder {count} demodata-oppføringer.",
    importResult: "{action} {added} nye rapporter, {skipped} duplikater hoppet over.",
    demoImportResultWarning: "ADVARSEL: Importen inneholder {count} demodata-oppføringer.",
    verificationWarning: "Noen rapporter kunne ikke verifiseres."
  },
  details: {
    summary: "Kort oppsummering",
    coreValues: "Kjerneverdier",
    details: "Detaljer",
    userComment: "Kommentar fra bruker",
    followups: "Oppfølginger",
    technical: "Teknisk informasjon",
    rawData: "Rådata",
    integrity: "Integritetskontroll",
    dataMode: "Datamodus",
    time: "Tidspunkt",
    workTime: "Arbeidstid",
    status: "Status",
    totalScore: "Totalscore",
    functionLevel: "Funksjonsnivå",
    description: "Beskrivelse",
    important: "Viktig",
    workAbility: "Arbeidsevne",
    energy: "Energinivå",
    physicalEnergy: "Fysisk energi",
    mentalEnergy: "Mental energi",
    mentalClarity: "Mental klarhet",
    symptoms: "Symptombelastning",
    strain: "Anstrengelse",
    productivity: "Produktivitet",
    taskCompletion: "Hvor mye fikk du gjort?",
    taskTypes: "Arbeidet innebar",
    limitations: "Begrenset av",
    accommodations: "Hva hjalp",
    comment: "Kommentar",
    noComment: "Ingen kommentar",
    noOptionalDetails: "Ingen valgfrie detaljer oppgitt.",
    technicalDescription: "Avansert informasjon for kontroll, feilsøking og verifisering.",
    rawDescription: "Full JSON-visning for feilsøking eller teknisk kontroll.",
    copyRaw: "Kopier rådata",
    reportId: "Rapport-ID",
    followupId: "Oppfølgings-ID",
    connectedReport: "Tilknyttet rapport",
    created: "Opprettet",
    updated: "Oppdatert",
    reportDate: "Rapportdato",
    reportTime: "Rapporttid",
    integrityStatus: "Integritetsstatus",
    explanation: "Forklaring",
    algorithm: "Algoritme",
    signed: "Signert",
    payloadHash: "Payload-hash",
    type: "Type",
    canonicalization: "Canonicalization",
    scoreUnavailable: "Totalscore mangler eller kan ikke beregnes.",
    worse: "Verre enn før",
    delayedSymptoms: "Forsinkede symptomer",
    recovery: "Restitusjon",
    outOfFive: "{value} av 5",
    worseValue: "Verre: {value}",
    recoveryValue: "Restitusjon: {value}"
  },
  danger: {
    title: "Faresone",
    deleteEntryHelp: "Dette sletter rapporten eller oppfølgingen fra lokal lagring i denne nettleseren.",
    deleteReport: "Slett rapport",
    deleteFollowup: "Slett oppfølging",
    reportName: "rapport",
    followupName: "oppfølging"
  },
  graphModal: {
    open: "Åpne graf i fullskjerm",
    title: "Grafanalyse",
    close: "Lukk graf",
    timeRange: "Tidsrom",
    visibleLines: "Synlige linjer",
    visibleHelp: "Trykk én gang for delvis synlig, to ganger for skjult.",
    snapHelp: "Hold musepekeren over grafen for å se nøyaktige rapportverdier.",
    noReports: "Ingen rapporter i valgt tidsrom.",
    noPoint: "Ingen rapportpunkt valgt",
    noPointHelp: "Hold musepekeren nær et punkt for å se faktiske rapportverdier.",
    nearestReport: "Nærmeste rapport",
    chartLabel: "Fullskjerm trendgraf for rapporter",
    workTime: "Arbeidstid",
    workTimeLegend: "Skyggefelt viser registrert arbeidstid",
    workTimeTooltip: "Registrert arbeidstid",
    followupResponse: "Oppfølgingsrespons",
    followupResponseHelp: "Viser oppfølginger på faktisk tidspunkt og visualiserer ettereffekt etter arbeidsøkten.",
    followupResponseDisclaimer: "Dette er en visuell ettereffektindikator, ikke en ny totalscore.",
    noFollowups: "Ingen oppfølginger for valgt rapport.",
    followupDelay: "Forsinkelse: {hours} timer",
    followupEffect: "Ettereffekt: {score}% fra rapportens {parent}%",
    metricTotalScore: "Totalscore",
    metricWorkAbility: "Arbeidsevne",
    metricEnergy: "Energi",
    metricClarity: "Klarhet",
    metricSymptoms: "Symptomer",
    metricStrain: "Belastning",
    metricTotalScoreShort: "T",
    metricWorkAbilityShort: "A",
    metricEnergyShort: "E",
    metricClarityShort: "K",
    metricSymptomsShort: "S",
    metricStrainShort: "B"
  },
  scoring: {
    disclaimer:
      "Totalscoren er normalisert slik at 75 % omtrent tilsvarer et forventet/godt rapportert funksjonsnivå, mens 100 % tilsvarer særdeles høyt funksjonsnivå. Scoren er en intern funksjonsindikator for oversikt og trend, ikke en medisinsk fasit.",
    periodLabel: "Periodens arbeidsevnevurdering",
    periodEmpty: "Ingen data i valgt periode",
    periodTooltip:
      "Dette er en normalisert vurdering basert på hovedrapportene i den valgte tidsrammen. 75 % regnes omtrent som forventet/godt rapportert funksjonsnivå. Vurderingen er støtte for oversikt og trend, ikke medisinsk fasit.",
    exceptionallyHigh: "Særdeles høyt funksjonsnivå",
    expected: "Forventet funksjonsnivå",
    moderatelyReduced: "Moderat redusert funksjon",
    significantlyReduced: "Betydelig redusert funksjon",
    veryLow: "Svært lav funksjon",
    exceptionallyHighShort: "Særdeles høyt",
    expectedShort: "Forventet",
    moderatelyReducedShort: "Moderat redusert",
    significantlyReducedShort: "Betydelig redusert",
    veryLowShort: "Svært lav"
  },
  verification: {
    valid: "Integritet OK",
    modified: "Mulig endret",
    missing: "Mangler lokal hash",
    unsupported: "Verifisering støttes ikke",
    error: "Feil ved verifisering",
    invalidLabel: "Varsel: rapporten kunne ikke verifiseres"
  }
} as const;

const en: TranslationTree = {
  common: {
    cancel: "Cancel",
    close: "Close",
    copied: "Copied",
    delete: "Delete",
    save: "Save",
    notSelected: "Not selected",
    notProvided: "Not provided",
    notCalculated: "Not calculated",
    unknownWorkplace: "Unknown workplace"
  },
  app: { eyebrow: "Local self-assessment", title: "Arbeidspuls", evaluator: "Advisor", navLabel: "Main navigation" },
  nav: { register: "Register", followup: "Follow-up", overview: "Overview", privacy: "Privacy" },
  demo: {
    enter: "Demo",
    exit: "Exit demo",
    label: "Demo data",
    notice: "You are in demo mode. This data is separate from real reports, and export/import only applies to demo data."
  },
  footer: {
    norwegian: "Norsk",
    english: "English",
    ukrainian: "Українська",
    switchToNorwegian: "Bytt språk til norsk",
    switchToEnglish: "Switch language to English",
    switchToUkrainian: "Switch language to Ukrainian",
    developedBy: "Developed by Rolfsvaag Datateknikk with",
    heart: "heart",
    languageChoice: "Language choice",
    sourceCode: "Source code v.{version}",
    commercialLicense: "Commercial license"
  },
  feedback: {
    button: "Feedback",
    buttonAria: "Send anonymous feedback",
    title: "Send feedback",
    stepOne: "1 of 2: Describe the feedback",
    stepTwo: "2 of 2: Confirm public submission",
    intro: "Feedback is created as a public issue if it passes validation.",
    typeLabel: "Type",
    typeBug: "Bug or problem",
    typeFeature: "Improvement suggestion",
    typeDocs: "Documentation or text",
    typeTask: "General task",
    typeOther: "Other",
    questionsNotice: "Questions should be sent directly to the project owner, not as public project feedback.",
    areaLabel: "Area",
    technicalAreas: "Technical categories",
    areaReporting: "Report registration",
    areaFollowup: "Follow-up",
    areaGraph: "Overview and graph",
    areaAdvisor: "Advisor view",
    areaImportExport: "Import, export and sharing",
    areaI18n: "Language and translation",
    areaPrivacy: "Privacy and local storage",
    areaUi: "Layout and usability",
    areaAccessibility: "Accessibility",
    areaLegal: "Legal or licensing",
    areaApi: "API",
    areaBackend: "Backend/server",
    areaDeployment: "Deployment",
    areaPwa: "Install as app/PWA",
    areaSecurity: "Security",
    areaPerformance: "Performance",
    legalNotice: "Special licensing or commercial use must be handled directly with the project owner.",
    commercialLicenseLink: "Read about special licensing and commercial use.",
    messageLabel: "Description",
    messagePlaceholder: "Describe what happened, what you expected, or what you suggest.",
    validationTitle: "Description requirements",
    validationMinChars: "Write at least 30 characters.",
    validationMaxChars: "Maximum 4000 characters.",
    validationMinWords: "Write at least 5 words.",
    validationMinLetters: "Write at least 15 letters.",
    validationMeaningful: "The text must contain meaningful content, not only numbers or symbols.",
    validationRepetition: "The text cannot consist of repetitions.",
    validationContact: "Remove email, phone number, IP address or long number sequences.",
    validationType: "Choose exactly one type.",
    validationArea: "Choose at least one area.",
    publicNotice:
      "Feedback may be created as public issues in the project's issue list. Do not enter sensitive information, report content, names of people or organizations, email addresses, phone numbers or other information that can identify you or others.",
    purposeNotice: "The feedback is only used to improve Arbeidspuls.",
    consent:
      "I confirm that the feedback does not contain sensitive or identifiable information, and that the content may be processed, stored and displayed publicly as ordinary project feedback.",
    back: "Back",
    continue: "Continue",
    submit: "Submit",
    submitWaiting: "Submit ({secondsLeft})",
    cancel: "Cancel",
    success: "Thank you. The feedback has been submitted.",
    fakeSuccess: "Thank you. The feedback has been received.",
    disabled: "Feedback is not enabled.",
    error: "The feedback could not be submitted. Try again later.",
    tooFast: "Wait a little before submitting the form.",
    urlWarning: "URLs are allowed, but remove sensitive links or query parameters."
  },
  deleteModal: {
    title: "Confirm deletion",
    body: "You are about to delete: {itemName}. This action cannot be undone.",
    waiting: "Delete ({secondsLeft})",
    ready: "Delete"
  },
  register: {
    intro: "Fill in the main fields. Optional details can be added if needed.",
    workSession: "Work session",
    workplace: "Workplace",
    workAbility: "Work ability right now",
    energyLevel: "Energy level",
    mentalClarity: "Mental clarity / concentration",
    symptomBurden: "Symptom burden",
    effortStrain: "Effort / strain",
    optional: "Optional",
    startTime: "Start time",
    endTime: "End time",
    continueQuestion: "Can you continue?",
    chooseBestNow: "Choose the option that fits best right now.",
    optionalDetails: "Optional details",
    physicalEnergy: "Physical energy",
    mentalEnergy: "Mental energy",
    productivity: "Perceived productivity",
    taskCompletion: "How much did you get done?",
    taskTypes: "Work involved",
    limitations: "What limited you most?",
    accommodations: "What helped?",
    note: "Short comment",
    missing: "Missing: {fields}.",
    saved: "Report saved locally.",
    saveReport: "Save report",
    oneEqualsFiveEquals: "1 = {low}, 5 = {high}."
  },
  followup: {
    intro: "Use this the next day or later to capture delayed reactions.",
    worseQuestion: "Are you worse than before the work session?",
    chooseOne: "Choose one answer.",
    connectReport: "Connect to report",
    delayedSymptoms: "Delayed symptoms",
    recovery: "Recovery",
    missingWorse: "Choose whether you are worse than before the work session.",
    saved: "Follow-up saved locally.",
    saveFollowup: "Save follow-up",
    orphan: "Follow-up without selected main report",
    worsePrefix: "worse",
    latestOnly: "Follow-up can only be created for the latest report."
  },
  edit: {
    edit: "Edit",
    reportIntro: "Edit the report. Editing is only available within 24 hours after creation.",
    followupIntro: "Edit the follow-up. Editing is only available within 24 hours after creation.",
    saveChanges: "Save changes",
    saved: "Changes saved locally.",
    cancelEdit: "Cancel editing",
    expired: "Editing is only available within 24 hours after creation."
  },
  overview: {
    noReports: "No reports have been saved yet.",
    report: "Report",
    followup: "Follow-up",
    closeReport: "Close report view",
    trend: "Trend",
    explainTrend: "Explain trend chart",
    trendTooltip: "The chart uses normalized 0-100 values. Higher value means better function or lower burden.",
    minimumTwo: "At least two reports in the selected period are needed for the chart.",
    average: "Normalized average for the period",
    chartLabel: "Time-based trend chart for reports",
    dashedLine: "A dashed line means there are 3 days or more between reports.",
    from: "From",
    to: "To",
    fromDate: "From date",
    toDate: "To date",
    datePlaceholder: "dd/mm/yyyy",
    all: "All",
    week: "1 week",
    month: "1 month",
    threeMonths: "3 months",
    sixMonths: "6 months",
    year: "1 year",
    threeYears: "3 years",
    fiveYears: "5 years"
  },
  privacy: {
    warning: "Reports may contain sensitive health information. Arbeidspuls stores data locally by default, with optional encrypted one-time sharing when you choose Send by email.",
    demoWarning: "Demo mode uses separate local storage. These reports are test data and are not mixed with real reports.",
    exportJson: "Export JSON",
    exportEmail: "Send by email",
    exportRangeTitle: "Export data",
    exportRangeIntro: "Optionally choose a date range for the export. If no dates are selected, all local data is exported.",
    fromDate: "From date",
    toDate: "To date",
    allDataDefault: "Default: all data is exported.",
    exportInvalidRange: "From date cannot be after to date.",
    exportSensitiveNotice: "The export file may contain sensitive health and function-related information. Only share it with people who should have access.",
    emailExportTitle: "Send data by email",
    recipientEmail: "Recipient email",
    recipientPlaceholder: "advisor@example.com",
    openEmail: "Open email",
    invalidEmail: "Enter a valid email address.",
    emailSubject: "Arbeidspuls report data for review",
    emailShared: "Secure share has been created.",
    manualAttachmentRequired: "Copy the text manually if the email client did not open correctly.",
    limitPeriod: "Limit date range",
    allDataSelected: "All data is selected by default.",
    emailClientNotice: "Automatic opening requires an email client to be configured on your device. If this does not work, you will get text you can copy and paste manually.",
    serverStorageConsent: "I understand that the selected data is temporarily stored encrypted and unreadable on the Arbeidspuls server to create a one-time link. The data is deleted after the first successful import or after 7 days.",
    serverStorageConsentRequired: "You must approve temporary encrypted server storage before the link is created.",
    createEmail: "Create email",
    emailLinkCreated: "The email client was opened if available. Use the copy-paste text if it was not filled in correctly.",
    emailLinkFailed: "Could not create secure share.",
    copyPasteBackupTitle: "Manual email text",
    copyPasteBackupIntro: "If the email client did not open or fill in the text correctly, copy the recipient, subject and text manually.",
    emailSubjectLabel: "Subject",
    emailBodyLabel: "Email text",
    secureEmailBody:
      "Hello\n\nI am sharing Arbeidspuls data with you for review.\n\nOpen this one-time link to fetch and import the data in advisor view:\n{shareUrl}\n\nThe link can be used once and expires automatically after 7 days.\n\nHow to proceed:\n1. Open the link.\n2. Press \"Fetch and import\".\n3. Review graphs, reports and follow-ups in advisor view.\n4. You can add your own notes if needed.\n\nThe data is stored locally in your browser/device after import. The Arbeidspuls server only stores a temporary encrypted and unreadable copy until the data is fetched, or for a maximum of 7 days.\n\nArbeidspuls\n{appUrl}\n",
    importBackup: "Import backup",
    deleteAll: "Delete all local data",
    importHelp: "Import previously exported JSON if you changed device or lost local data. Imported data is stored locally in this browser.",
    importFrom: "Import data from {fileName}",
    importStats: "New reports: {reports}. New follow-ups: {followups}. Duplicates skipped: {duplicates}. Conflicts: {conflicts}.",
    demoImportWarning: "The import contains {count} demo data entries and can only be imported in demo mode.",
    cancelImport: "Cancel import",
    importData: "Import data",
    baseCopy:
      "The app does not collect names, national identity numbers or contact information. Data is stored locally by default. With Send by email, the selected export is encrypted in the browser before temporary upload. Free text is optional and should only be used when needed.",
    storageTitle: "Where is the data stored?",
    storageBody:
      "Reports are stored locally in the browser on the device you use, in localStorage. If you choose Send by email, only encrypted and unreadable share data is temporarily uploaded to the Arbeidspuls server.",
    backupTitle: "Backup and device changes",
    backupBody:
      "Because the data is stored locally, it may be lost if you change device, delete browser data, use another browser or reset the device. Export a JSON file regularly if you want to keep the reports.",
    sharingTitle: "Sharing with an advisor",
    sharingBody:
      "If an advisor or another person will review the reports, you can export a local JSON file or use Send by email. Email sharing creates an encrypted one-time link where the key is in the URL fragment and is never sent to the server.",
    sensitiveTitle: "Sensitive information",
    sensitiveBody:
      "Reports may contain health and function-related information. Only share JSON files or one-time links with people who should have access. Encrypted shares are deleted after the first successful import or automatically after 7 days.",
    exportIntegrity: "Export includes local integrity checks where reports have verification data.",
    deleteAllName: "all local reports"
  },
  share: {
    title: "Arbeidspuls share",
    intro: "You have opened a one-time share of Arbeidspuls data.",
    activeImportNotice: "The share is not fetched until you press the button. Data is decrypted and imported locally in the advisor view.",
    fetchAndImport: "Fetch and import",
    fetching: "Fetching...",
    openAdvisor: "Open advisor view",
    alreadyDeleted: "This share has already been fetched or deleted.",
    expired: "This share was automatically deleted because it is more than 7 days old.",
    requestNewShare: "Ask the sender to create a new share if you still need access.",
    missingKey: "The link is missing its decryption key. Ask the sender to send the full link again.",
    missingConfirmToken: "The link is missing its confirmation code. Ask the sender to send the full link again.",
    decryptFailed: "Could not decrypt the share. The link may be incomplete or incorrect.",
    notFound: "The share does not exist.",
    imported: "Import complete. New entries: {reports}. Duplicates skipped: {skipped}."
  },
  evaluator: {
    eyebrow: "Advisor",
    title: "Advisor review",
    backToApp: "Back to app",
    importJson: "Import JSON",
    importHelp: "Choose an export from the app. Data is stored locally in this browser.",
    displayName: "Name/identifier",
    optionalImportName: "Optional when importing",
    connectExisting: "Connect to existing person",
    autoMatch: "Create new or use automatic match",
    chooseJson: "Choose JSON file",
    exportBackup: "Export advisor data",
    importBackup: "Import advisor backup",
    importedBackup: "Advisor backup has been imported.",
    demoDataWarning: "This import contains demo data. Do not use it as real user or health information.",
    importStart: "Import a JSON file to start reviewing.",
    saveName: "Save name",
    deletePerson: "Delete user and reports",
    deletePersonTitle: "Deletes this user, imported reports, follow-ups and advisor notes after confirmation.",
    reportCount: "{count} reports",
    personNote: "General note for user",
    personNoteHelp: "This note applies to the person as a whole, not one specific report.",
    saveNote: "Save note",
    changedAt: "Last changed: {time}",
    searchReports: "Search reports",
    newest: "Newest first",
    oldest: "Oldest first",
    noSelectedTitle: "No report selected",
    noSelectedBody: "Choose a report from the list to see details, follow-ups and notes.",
    details: "Show details",
    reportDetails: "Report details",
    followupDetails: "Follow-up details",
    closeDetails: "Close details",
    reportNote: "Report note",
    followupNote: "Follow-up note",
    noteHelp: "The advisor note is stored locally and does not change imported report data.",
    deleteNote: "Delete note",
    validationError: "Validation error",
    comment: "Comment",
    evaluatorNote: "Advisor note",
    followupNoteBadge: "Follow-up note",
    hasFollowup: "Has follow-up",
    hasComment: "Has user comment",
    hasEvaluatorNote: "Has advisor note",
    scoreValues: "Score values",
    importReadError: "The import file could not be read.",
    importMatched: "The import was connected to an existing user.",
    importCreated: "A new user was created.",
    importFailed: "Import failed.",
    backupFailed: "The backup could not be imported.",
    demoBackupWarning: "WARNING: The backup contains {count} demo data entries.",
    importResult: "{action} {added} new reports, {skipped} duplicates skipped.",
    demoImportResultWarning: "WARNING: The import contains {count} demo data entries.",
    verificationWarning: "Some reports could not be verified."
  },
  details: {
    summary: "Short summary",
    coreValues: "Core values",
    details: "Details",
    userComment: "User comment",
    followups: "Follow-ups",
    technical: "Technical information",
    rawData: "Raw data",
    integrity: "Integrity check",
    dataMode: "Data mode",
    time: "Time",
    workTime: "Work time",
    status: "Status",
    totalScore: "Total score",
    functionLevel: "Function level",
    description: "Description",
    important: "Important",
    workAbility: "Work ability",
    energy: "Energy level",
    physicalEnergy: "Physical energy",
    mentalEnergy: "Mental energy",
    mentalClarity: "Mental clarity",
    symptoms: "Symptom burden",
    strain: "Effort/strain",
    productivity: "Productivity",
    taskCompletion: "How much did you get done?",
    taskTypes: "Work involved",
    limitations: "Limited by",
    accommodations: "What helped",
    comment: "Comment",
    noComment: "No comment",
    noOptionalDetails: "No optional details provided.",
    technicalDescription: "Advanced information for control, troubleshooting and verification.",
    rawDescription: "Full JSON view for troubleshooting or technical control.",
    copyRaw: "Copy raw data",
    reportId: "Report ID",
    followupId: "Follow-up ID",
    connectedReport: "Connected report",
    created: "Created",
    updated: "Updated",
    reportDate: "Report date",
    reportTime: "Report time",
    integrityStatus: "Integrity status",
    explanation: "Explanation",
    algorithm: "Algorithm",
    signed: "Signed",
    payloadHash: "Payload hash",
    type: "Type",
    canonicalization: "Canonicalization",
    scoreUnavailable: "The total score is missing or could not be calculated.",
    worse: "Worse than before",
    delayedSymptoms: "Delayed symptoms",
    recovery: "Recovery",
    outOfFive: "{value} of 5",
    worseValue: "Worse: {value}",
    recoveryValue: "Recovery: {value}"
  },
  danger: {
    title: "Danger zone",
    deleteEntryHelp: "This deletes the report or follow-up from local storage in this browser.",
    deleteReport: "Delete report",
    deleteFollowup: "Delete follow-up",
    reportName: "report",
    followupName: "follow-up"
  },
  graphModal: {
    open: "Open chart fullscreen",
    title: "Chart analysis",
    close: "Close chart",
    timeRange: "Time range",
    visibleLines: "Visible lines",
    visibleHelp: "Tap once for partially visible, twice for hidden.",
    snapHelp: "Hover over the chart to see exact report values.",
    noReports: "No reports in selected period.",
    noPoint: "No report point selected",
    noPointHelp: "Hover near a point to see actual report values.",
    nearestReport: "Nearest report",
    chartLabel: "Fullscreen trend chart for reports",
    workTime: "Work time",
    workTimeLegend: "Shaded areas show registered work time",
    workTimeTooltip: "Registered work time",
    followupResponse: "Follow-up response",
    followupResponseHelp: "Shows follow-ups at their actual time and visualizes after-effect from the work session.",
    followupResponseDisclaimer: "This is a visual after-effect indicator, not a new total score.",
    noFollowups: "No follow-ups for the selected report.",
    followupDelay: "Delay: {hours} hours",
    followupEffect: "After-effect: {score}% from report {parent}%",
    metricTotalScore: "Total score",
    metricWorkAbility: "Work ability",
    metricEnergy: "Energy",
    metricClarity: "Clarity",
    metricSymptoms: "Symptoms",
    metricStrain: "Strain",
    metricTotalScoreShort: "T",
    metricWorkAbilityShort: "A",
    metricEnergyShort: "E",
    metricClarityShort: "C",
    metricSymptomsShort: "S",
    metricStrainShort: "S"
  },
  scoring: {
    disclaimer:
      "The total score is normalized so that 75% roughly corresponds to an expected/good reported function level, while 100% corresponds to an exceptionally high function level. The score is an internal function indicator for overview and trend, not a medical conclusion.",
    periodLabel: "Period work ability assessment",
    periodEmpty: "No data in selected period",
    periodTooltip:
      "This is a normalized assessment based on the main reports in the selected time range. 75% is roughly considered an expected/good reported function level. The assessment supports overview and trend, not a medical conclusion.",
    exceptionallyHigh: "Exceptionally high function level",
    expected: "Expected function level",
    moderatelyReduced: "Moderately reduced function",
    significantlyReduced: "Significantly reduced function",
    veryLow: "Very low function",
    exceptionallyHighShort: "Exceptionally high",
    expectedShort: "Expected",
    moderatelyReducedShort: "Moderately reduced",
    significantlyReducedShort: "Significantly reduced",
    veryLowShort: "Very low"
  },
  verification: {
    valid: "Integrity OK",
    modified: "Possibly changed",
    missing: "Missing local hash",
    unsupported: "Verification is not supported",
    error: "Verification error",
    invalidLabel: "Warning: the report could not be verified"
  }
};

export const labelsByLanguage = {
  "nb-NO": {
    statusLabels: nbStatusLabels,
    taskTypeLabels: nbTaskTypeLabels,
    limitationLabels: nbLimitationLabels,
    accommodationLabels: nbAccommodationLabels,
    taskCompletionLabels: nbTaskCompletionLabels,
    worseLabels: nbWorseLabels,
    delayedSymptomLabels: nbDelayedSymptomLabels,
    recoveryLabels: nbRecoveryLabels,
    positiveScale: nbPositiveScale,
    negativeScale: nbNegativeScale,
    tooltipTexts: nbTooltipTexts,
    categoryTooltipTexts: nbCategoryTooltipTexts
  },
  en: {
    statusLabels: {
      kan_fortsette: "Can continue",
      trenger_pause: "Needs a break",
      trenger_enklere_oppgave: "Needs an easier task",
      bør_stoppe: "Wants to stop",
      onsker_a_stoppe: "Wants to stop",
      ønsker_å_stoppe: "Wants to stop"
    } satisfies Record<ReportStatus, string>,
    taskTypeLabels: {
      sitting: "Sitting",
      standing: "Standing",
      walking: "Walking",
      lifting: "Lifting",
      computer_work: "Computer work",
      concentration: "Concentration",
      multitasking: "Multitasking",
      talking_social: "Talking/social",
      noise: "Noise",
      bright_light: "Bright light",
      time_pressure: "Time pressure"
    } satisfies Record<TaskType, string>,
    limitationLabels: {
      fatigue: "Fatigue",
      brain_fog: "Brain fog",
      pain: "Pain",
      headache_migraine: "Headache/migraine",
      dizziness: "Dizziness",
      nausea: "Nausea",
      sensory_overload: "Sensory overload",
      stress_anxiety: "Stress/anxiety",
      weakness: "Weakness",
      sleepiness: "Sleepiness",
      other: "Other"
    } satisfies Record<Limitation, string>,
    accommodationLabels: {
      extra_breaks: "Extra breaks",
      sitting_down: "Sitting down",
      quiet_room: "Quiet room",
      reduced_pace: "Reduced pace",
      shorter_task: "Shorter task",
      help_from_others: "Help from others",
      remote_work: "Remote work",
      task_switching: "Task switching",
      nothing_helped: "Nothing helped"
    } satisfies Record<Accommodation, string>,
    taskCompletionLabels: {
      nesten_ingenting: "Almost nothing",
      litt: "A little",
      delvis: "Partly",
      som_forventet: "As expected",
      mer_enn_forventet: "More than expected"
    } satisfies Record<TaskCompletion, string>,
    worseLabels: {
      nei: "No",
      litt: "A little",
      moderat: "Moderate",
      mye: "A lot"
    } satisfies Record<WorseThanBefore, string>,
    delayedSymptomLabels: {
      fatigue: "Fatigue",
      pain: "Pain",
      brain_fog: "Brain fog",
      flu_like: "Flu-like feeling",
      headache: "Headache",
      dizziness: "Dizziness",
      sleep_disruption: "Sleep disruption",
      sensory_sensitivity: "Light/sound sensitivity"
    } satisfies Record<DelayedSymptom, string>,
    recoveryLabels: {
      tilbake_til_baseline: "Back to usual level",
      samme_dag: "Same day",
      en_dag: "One day",
      to_tre_dager: "Two-three days",
      fire_pluss_dager: "Four+ days",
      ikke_tilbake_til_baseline: "Not back yet"
    } satisfies Record<RecoveryStatus, string>,
    positiveScale: {
      1: "Very low",
      2: "Low",
      3: "Medium",
      4: "Good",
      5: "Very good"
    } satisfies Record<ScaleValue, string>,
    negativeScale: {
      1: "Little/none",
      2: "Mild",
      3: "Moderate",
      4: "High",
      5: "Very high"
    } satisfies Record<ScaleValue, string>,
    tooltipTexts: {
      work_ability: "How well you feel you can function in the work situation right now, regardless of whether you actually get everything done.",
      energy_level: "Overall perceived energy. If you do not separate physical and mental energy, this is used for both.",
      physical_energy: "Bodily energy, endurance and physical capacity.",
      mental_energy: "Mental endurance, ability to stay focused over time and tolerate cognitive load.",
      mental_clarity: "How clearly you think, and how easy it is to concentrate, remember, understand and follow along.",
      symptom_burden: "How much symptoms bother or limit you, such as pain, headache, dizziness, nausea or sensory overload.",
      effort_strain: "How much it costs to complete the activity. This is about effort/strain, not only symptom intensity.",
      symptom_vs_effort: "Symptom burden is about how many symptoms you have. Effort/strain is about how hard you must push yourself to complete the activity.",
      total_score_percent: "A calculated function indicator from 0 to 100 based on reported answers. This is not a medically validated test score.",
      workplace: "Workplace or context for the session. The field is prefilled from the previous report when available.",
      work_time: "Start and end time for the work session. The fields can be changed before saving the report."
    },
    categoryTooltipTexts: {
      A: "Work ability",
      E: "Energy",
      K: "Mental clarity/concentration",
      S: "Symptom burden",
      B: "Effort/strain",
      T: "Total score"
    }
  },
  "uk-UA": {
    statusLabels: ukStatusLabels,
    taskTypeLabels: ukTaskTypeLabels,
    limitationLabels: ukLimitationLabels,
    accommodationLabels: ukAccommodationLabels,
    taskCompletionLabels: ukTaskCompletionLabels,
    worseLabels: ukWorseLabels,
    delayedSymptomLabels: ukDelayedSymptomLabels,
    recoveryLabels: ukRecoveryLabels,
    positiveScale: ukPositiveScale,
    negativeScale: ukNegativeScale,
    tooltipTexts: ukTooltipTexts,
    categoryTooltipTexts: ukCategoryTooltipTexts
  }
} as const;

type I18nContextValue = {
  language: Language;
  setLanguage: (language: Language) => void;
  labels: (typeof labelsByLanguage)[Language];
  t: (key: string, params?: Record<string, string | number>) => string;
  locale: string;
};

const I18nContext = createContext<I18nContextValue | null>(null);

export function I18nProvider({ children }: { children: React.ReactNode }) {
  const [language, setLanguageState] = useState<Language>(() => readStoredLanguage());
  const value = useMemo<I18nContextValue>(() => {
    const setLanguage = (next: Language) => {
      localStorage.setItem(LANGUAGE_KEY, next);
      setLanguageState(next);
    };
    return {
      language,
      setLanguage,
      labels: labelsByLanguage[language],
      t: (key, params) => interpolate(readTranslation(language, key), params),
      locale: localeForLanguage(language)
    };
  }, [language]);

  return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>;
}

export function useI18n() {
  const context = useContext(I18nContext);
  if (!context) throw new Error("useI18n must be used inside I18nProvider");
  return context;
}

export function translateVerificationStatus(status: VerificationStatus | undefined, t: I18nContextValue["t"]) {
  if (!status) return t("common.notProvided");
  return t(`verification.${status}`);
}

export function translateScoreBand(
  band: { label: string; short_label: string; description: string } | null | undefined,
  t: I18nContextValue["t"],
  mode: "label" | "short" = "label"
) {
  if (!band) return t("common.notCalculated");
  const key = scoreBandKeyFromNorwegianLabel(band.label);
  if (!key) return mode === "short" ? band.short_label : band.label;
  if (mode === "short") return t(`scoring.${key}Short`);
  return t(`scoring.${key}`);
}

export function translateScoreBandDescription(band: { label: string; description: string } | null | undefined, language: Language) {
  if (!band || language === "nb-NO") return band?.description;
  const key = scoreBandKeyFromNorwegianLabel(band.label);
  const descriptions: Record<Exclude<Language, "nb-NO">, Record<string, string>> = {
    en: {
      exceptionallyHigh: "The report suggests very good function in the current work situation, above what can normally be expected.",
      expected: "The report is within an expected/good function level for the current work situation.",
      moderatelyReduced: "The report suggests a noticeable reduction in work ability, energy, symptom burden or sustainability.",
      significantlyReduced: "The report suggests clearly limited function and/or high strain when completing the activity.",
      veryLow: "The report suggests very low current function, high strain or that the activity may not be sustainable."
    },
    "uk-UA": {
      exceptionallyHigh: "Звіт свідчить про дуже добрий рівень функціонування в поточній робочій ситуації, вищий за звичайно очікуваний.",
      expected: "Звіт відповідає очікуваному або доброму рівню функціонування в поточній робочій ситуації.",
      moderatelyReduced: "Звіт свідчить про помітне зниження працездатності, енергії, переносимості симптомів або витривалості.",
      significantlyReduced: "Звіт свідчить про суттєво обмежене функціонування та/або високе навантаження під час виконання роботи.",
      veryLow: "Звіт свідчить про дуже низький поточний рівень функціонування, високе навантаження або нестійкість такої діяльності."
    }
  };
  return key ? descriptions[language][key] : band.description;
}

export function datePlaceholderForLanguage(language: Language) {
  return readTranslation(language, "overview.datePlaceholder");
}

export function localeForLanguage(language: Language) {
  if (language === "en") return "en-GB";
  return language;
}

export function readStoredLanguage(): Language {
  const stored = localStorage.getItem(LANGUAGE_KEY);
  return stored === "en" || stored === "nb-NO" || stored === "uk-UA" ? stored : "nb-NO";
}

function readTranslation(language: Language, key: string) {
  const translated = lookup(language === "en" ? en : language === "uk-UA" ? uk : nb, key);
  const fallback = lookup(nb, key);
  return typeof translated === "string" ? translated : typeof fallback === "string" ? fallback : key;
}

export function missingTranslationKeys(language: Exclude<Language, "nb-NO">) {
  const referenceKeys = flattenTranslationKeys(nb);
  const translatedKeys = new Set(flattenTranslationKeys(language === "en" ? en : uk));
  return referenceKeys.filter((key) => !translatedKeys.has(key));
}

function flattenTranslationKeys(tree: TranslationTree, prefix = ""): string[] {
  return Object.entries(tree).flatMap(([key, value]) => {
    const path = prefix ? `${prefix}.${key}` : key;
    return typeof value === "string" ? [path] : flattenTranslationKeys(value, path);
  });
}

function lookup(tree: TranslationTree, key: string): string | TranslationTree | undefined {
  return key.split(".").reduce<string | TranslationTree | undefined>((current, part) => {
    if (!current || typeof current === "string") return undefined;
    return current[part];
  }, tree);
}

function interpolate(template: string, params?: Record<string, string | number>) {
  if (!params) return template;
  return template.replace(/\{(\w+)\}/g, (_, key: string) => String(params[key] ?? `{${key}}`));
}

function scoreBandKeyFromNorwegianLabel(label: string) {
  if (label === "Særdeles høyt funksjonsnivå") return "exceptionallyHigh";
  if (label === "Forventet funksjonsnivå") return "expected";
  if (label === "Moderat redusert funksjon") return "moderatelyReduced";
  if (label === "Betydelig redusert funksjon") return "significantlyReduced";
  if (label === "Svært lav funksjon") return "veryLow";
  return null;
}
