export const managerialLevels = [
  "Manager de proximite",
  "Manager de managers",
  "CODIR / Direction",
] as const;

export type ManagerialLevel = (typeof managerialLevels)[number];

export const AUTODIAGNOSTIC_ANSWER_VALUES = ["A", "B", "C", "D"] as const;

export type AutodiagnosticAnswerValue =
  (typeof AUTODIAGNOSTIC_ANSWER_VALUES)[number];

export type AutodiagnosticDraftAnswerValue = "" | AutodiagnosticAnswerValue;

export type AutodiagnosticSectionId =
  | "posture"
  | "pilotage"
  | "animation"
  | "communication"
  | "developpement"
  | "leadership";

export const autodiagnosticSectionIds = [
  "posture",
  "pilotage",
  "animation",
  "communication",
  "developpement",
  "leadership",
] as const;

export type DiagnosticOption = {
  value: AutodiagnosticAnswerValue;
  text: string;
};

export type DiagnosticQuestion = {
  id: string;
  number: number;
  context: string[];
  options: DiagnosticOption[];
};

export type DiagnosticSection = {
  id: AutodiagnosticSectionId;
  kicker: string;
  title: string;
  shortTitle: string;
  description: string;
  strengthsCopy: string;
  attentionCopy: string;
  questions: DiagnosticQuestion[];
};

export type AutodiagnosticAnswers = Record<string, AutodiagnosticDraftAnswerValue>;

export type CompletedAutodiagnosticAnswers = Record<string, AutodiagnosticAnswerValue>;

export type AutodiagnosticSectionScore = {
  id: AutodiagnosticSectionId;
  title: string;
  score: number;
};

export type AutodiagnosticResult = {
  managerialLevel: ManagerialLevel;
  globalScore: number;
  overallLabel: string;
  summary: string;
  strengths: string[];
  attentionPoints: string[];
  sectionScores: AutodiagnosticSectionScore[];
};

const ANSWER_SCORE_MAP: Record<AutodiagnosticAnswerValue, number> = {
  A: 25,
  B: 50,
  C: 75,
  D: 100,
};

const MANAGERIAL_LEVEL_WEIGHTS: Record<
  ManagerialLevel,
  Record<AutodiagnosticSectionId, number>
> = {
  "Manager de proximite": {
    posture: 20,
    pilotage: 15,
    animation: 15,
    communication: 40,
    developpement: 5,
    leadership: 5,
  },
  "Manager de managers": {
    posture: 10,
    pilotage: 10,
    animation: 15,
    communication: 25,
    developpement: 20,
    leadership: 20,
  },
  "CODIR / Direction": {
    posture: 5,
    pilotage: 5,
    animation: 10,
    communication: 25,
    developpement: 15,
    leadership: 40,
  },
};

export const autodiagnosticSections: DiagnosticSection[] = [
  {
    id: "posture",
    kicker: "Bloc 1",
    title: "Posture & identite manageriale",
    shortTitle: "Posture",
    description:
      "Rapport au cadre, autorite percue et facon d'assumer votre role de manager.",
    strengthsCopy:
      "Votre posture manageriale apporte du cadre et de la lisibilite dans les situations sensibles.",
    attentionCopy:
      "Votre posture manageriale gagnerait a renforcer le cadre pose et la facon d'assumer votre role.",
    questions: [
      {
        id: "situation-1",
        number: 1,
        context: [
          "Un collaborateur experimente remet regulierement en question tes decisions en reunion. L'equipe commence a reagir.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu le recadres en reunion pour poser une limite claire" },
          { value: "B", text: "Tu laisses faire en considerant que cela favorise le debat" },
          { value: "C", text: "Tu echanges avec lui en tete-a-tete pour comprendre ce qui se joue" },
          { value: "D", text: "Tu ajustes ta maniere de presenter tes decisions pour limiter les reactions" },
        ],
      },
      {
        id: "situation-2",
        number: 2,
        context: [
          "Un collaborateur de ton equipe prend des decisions sans t'en informer, mais les resultats sont globalement bons.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu lui rappelles le cadre et les regles de fonctionnement" },
          { value: "B", text: "Tu laisses faire tant que les resultats sont au rendez-vous" },
          { value: "C", text: "Tu echanges avec lui pour comprendre sa logique" },
          { value: "D", text: "Tu ajustes progressivement le niveau d'autonomie attendu" },
        ],
      },
      {
        id: "situation-3",
        number: 3,
        context: [
          "Dans une periode de forte incertitude, ton equipe te sollicite beaucoup pour obtenir des reponses que tu n'as pas.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu attends d'avoir des informations fiables avant de t'exprimer" },
          { value: "B", text: "Tu partages les informations dont tu disposes" },
          { value: "C", text: "Tu expliques clairement les zones d'incertitude" },
          { value: "D", text: "Tu aides l'equipe a avancer malgre le manque de visibilite" },
        ],
      },
    ],
  },
  {
    id: "pilotage",
    kicker: "Bloc 2",
    title: "Pilotage & organisation de l'activite",
    shortTitle: "Pilotage",
    description:
      "Capacite a arbitrer, remettre du cadre et donner des reperes quand les priorites bougent.",
    strengthsCopy:
      "Votre pilotage donne des reperes utiles et aide a arbitrer avec recul quand les priorites evoluent.",
    attentionCopy:
      "Votre pilotage peut gagner en arbitrage, en priorisation et en cadre pour stabiliser l'action.",
    questions: [
      {
        id: "situation-4",
        number: 4,
        context: [
          "Ton equipe travaille sur plusieurs sujets en parallele.",
          "Un client interne insiste pour traiter son besoin en priorite, alors qu'un autre sujet, moins visible, a un impact important sur un projet strategique.",
          "Ton equipe commence a se disperser et chacun defend ses priorites.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu arbitres rapidement en donnant la priorite au demandeur le plus pressant" },
          { value: "B", text: "Tu demandes a chacun de te remonter ses contraintes pour decider" },
          { value: "C", text: "Tu reunis l'equipe pour clarifier collectivement les priorites" },
          { value: "D", text: "Tu reprends les enjeux globaux et reorganises les priorites en consequence" },
        ],
      },
      {
        id: "situation-5",
        number: 5,
        context: [
          "Un projet dont tu as la responsabilite prend du retard.",
          "Tu realises que certaines difficultes etaient connues dans l'equipe mais n'ont pas ete remontees.",
          "Le client commence a s'impatienter.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu rappelles les engagements et les delais a tenir" },
          { value: "B", text: "Tu demandes des explications aux personnes concernees" },
          { value: "C", text: "Tu echanges avec l'equipe pour comprendre ce qui n'a pas ete partage" },
          { value: "D", text: "Tu ajustes l'organisation et les points de suivi pour eviter que cela se reproduise" },
        ],
      },
      {
        id: "situation-6",
        number: 6,
        context: [
          "Depuis plusieurs semaines, les priorites evoluent regulierement en fonction des demandes de la direction.",
          "Ton equipe exprime de la confusion et a du mal a s'organiser.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu transmets les changements de priorites au fur et a mesure" },
          { value: "B", text: "Tu demandes plus de stabilite a ta hierarchie" },
          { value: "C", text: "Tu aides l'equipe a distinguer l'essentiel du secondaire" },
          { value: "D", text: "Tu mets en place des reperes pour fonctionner malgre les changements" },
        ],
      },
    ],
  },
  {
    id: "animation",
    kicker: "Bloc 3",
    title: "Animation & engagement",
    shortTitle: "Animation",
    description:
      "Qualite des interactions collectives, climat d'equipe et implication durable dans l'action.",
    strengthsCopy:
      "Vous creez de bonnes conditions d'animation collective et favorisez une implication durable de l'equipe.",
    attentionCopy:
      "L'animation collective peut etre renforcee pour mieux engager chacun et traiter les signaux faibles.",
    questions: [
      {
        id: "situation-7",
        number: 7,
        context: [
          "Lors de tes reunions d'equipe, certaines personnes participent activement, tandis que d'autres restent en retrait, sans forcement exprimer leurs idees.",
          "Tu sens que certaines decisions ne sont pas pleinement partagees.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu poursuis la reunion en t'appuyant sur les plus actifs" },
          { value: "B", text: "Tu sollicites directement les personnes plus discretes" },
          { value: "C", text: "Tu modifies le format pour favoriser la participation de chacun" },
          { value: "D", text: "Tu travailles avec l'equipe sur les regles de fonctionnement en reunion" },
        ],
      },
      {
        id: "situation-8",
        number: 8,
        context: [
          "Deux membres de ton equipe ont des tensions recurrentes.",
          "Ils continuent a travailler ensemble, mais l'ambiance se degrade et cela commence a impacter le reste de l'equipe.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu les laisses gerer entre eux tant que le travail avance" },
          { value: "B", text: "Tu interviens pour clarifier les roles et les responsabilites" },
          { value: "C", text: "Tu organises un echange entre eux pour apaiser la situation" },
          { value: "D", text: "Tu cherches a comprendre ce qui alimente la tension et ajustes le fonctionnement" },
        ],
      },
      {
        id: "situation-9",
        number: 9,
        context: [
          "Depuis quelque temps, tu constates une baisse d'engagement dans ton equipe : moins d'initiatives, moins d'energie dans les projets.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu rappelles les objectifs et les attendus" },
          { value: "B", text: "Tu echanges avec l'equipe pour recueillir leur ressenti" },
          { value: "C", text: "Tu proposes de nouvelles modalites de travail" },
          { value: "D", text: "Tu observes les signaux faibles et ajustes ton management en consequence" },
        ],
      },
    ],
  },
  {
    id: "communication",
    kicker: "Bloc 4",
    title: "Communication & relation",
    shortTitle: "Communication",
    description:
      "Facon de gerer les malentendus, les desaccords et les perceptions individuelles.",
    strengthsCopy:
      "Votre communication relationnelle aide a clarifier les perceptions et a maintenir des echanges constructifs.",
    attentionCopy:
      "Votre communication relationnelle peut etre consolidee pour mieux traiter les malentendus et les tensions.",
    questions: [
      {
        id: "situation-10",
        number: 10,
        context: [
          "Lors d'un entretien, tu fais un retour a un collaborateur sur un point d'amelioration.",
          "Il se ferme et te repond :",
          "\"J'ai l'impression que ce que je fais n'est jamais suffisant.\"",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu reformules ton message pour etre plus clair" },
          { value: "B", text: "Tu precises ton intention pour eviter les malentendus" },
          { value: "C", text: "Tu explores avec lui ce qui le fait reagir ainsi" },
          { value: "D", text: "Tu l'invites a analyser lui-meme la situation" },
        ],
      },
      {
        id: "situation-11",
        number: 11,
        context: [
          "Un desaccord avec un collaborateur prend de l'ampleur.",
          "Le ton monte, et tu sens que l'echange devient moins constructif.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu recentres la discussion sur des elements factuels" },
          { value: "B", text: "Tu mets fin a l'echange pour eviter que cela degenere" },
          { value: "C", text: "Tu prends du recul avant de reprendre la discussion" },
          { value: "D", text: "Tu cherches a comprendre les enjeux derriere le desaccord" },
        ],
      },
      {
        id: "situation-12",
        number: 12,
        context: [
          "Un collaborateur interprete regulierement tes messages de maniere negative, malgre tes efforts pour etre clair.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu reformules tes messages pour etre plus precis" },
          { value: "B", text: "Tu lui expliques ton intention" },
          { value: "C", text: "Tu echanges avec lui sur sa maniere de percevoir les situations" },
          { value: "D", text: "Tu ajustes ta communication en fonction de lui" },
        ],
      },
    ],
  },
  {
    id: "developpement",
    kicker: "Bloc 5",
    title: "Developpement",
    shortTitle: "Developpement",
    description:
      "Posture d'accompagnement, niveau d'exigence et capacite a faire grandir les collaborateurs.",
    strengthsCopy:
      "Vous creez des conditions favorables au developpement des collaborateurs et a leur progression dans la duree.",
    attentionCopy:
      "Le developpement des collaborateurs peut etre davantage structure pour faire progresser l'equipe.",
    questions: [
      {
        id: "situation-13",
        number: 13,
        context: [
          "Un collaborateur vient te voir avec un probleme operationnel.",
          "Tu sais que tu pourrais lui donner la solution immediatement, et le sujet est urgent.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu lui donnes la solution pour aller plus vite" },
          { value: "B", text: "Tu lui proposes des pistes de reflexion" },
          { value: "C", text: "Tu lui poses des questions pour l'aider a trouver lui-meme" },
          { value: "D", text: "Tu lui demandes de revenir avec une proposition" },
        ],
      },
      {
        id: "situation-14",
        number: 14,
        context: [
          "Un collaborateur realise correctement ses missions, mais sans reelle progression.",
          "Tu as le sentiment qu'il pourrait faire davantage.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu augmentes le niveau d'exigence" },
          { value: "B", text: "Tu lui donnes des axes d'amelioration" },
          { value: "C", text: "Tu echanges avec lui sur ses marges de progression" },
          { value: "D", text: "Tu l'accompagnes dans la recherche de ses propres leviers" },
        ],
      },
      {
        id: "situation-15",
        number: 15,
        context: [
          "Un collaborateur a particulierement bien reussi une mission importante.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu le felicites rapidement" },
          { value: "B", text: "Tu valorises son travail aupres de l'equipe" },
          { value: "C", text: "Tu lui expliques ce qui a bien fonctionne" },
          { value: "D", text: "Tu l'amenes a analyser lui-meme les facteurs de reussite" },
        ],
      },
    ],
  },
  {
    id: "leadership",
    kicker: "Bloc 6",
    title: "Leadership & transformation",
    shortTitle: "Leadership",
    description:
      "Capacite a orienter, embarquer et agir quand le contexte change ou reste incomplet.",
    strengthsCopy:
      "Votre leadership aide a donner une direction claire et a embarquer le collectif dans le changement.",
    attentionCopy:
      "Votre leadership peut etre renforce pour mieux orienter, embarquer et agir dans l'incertitude.",
    questions: [
      {
        id: "situation-16",
        number: 16,
        context: [
          "Un changement d'organisation est en cours.",
          "Ton equipe exprime des doutes et certaines resistances.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu expliques les raisons du changement" },
          { value: "B", text: "Tu donnes plus de contexte" },
          { value: "C", text: "Tu prends le temps d'ecouter les reactions" },
          { value: "D", text: "Tu impliques l'equipe dans la mise en oeuvre" },
        ],
      },
      {
        id: "situation-17",
        number: 17,
        context: [
          "Certains collaborateurs montrent une resistance passive (peu d'implication, remise en question implicite).",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu rappelles les objectifs" },
          { value: "B", text: "Tu accompagnes individuellement les personnes" },
          { value: "C", text: "Tu cherches a comprendre les freins" },
          { value: "D", text: "Tu mobilises le collectif autour du changement" },
        ],
      },
      {
        id: "situation-18",
        number: 18,
        context: [
          "Tu dois prendre une decision importante avec peu de visibilite et des informations incompletes.",
          "Les equipes attendent une orientation.",
          "Que fais-tu ?",
        ],
        options: [
          { value: "A", text: "Tu reportes la decision en attendant plus d'informations" },
          { value: "B", text: "Tu prends une decision rapide" },
          { value: "C", text: "Tu consultes quelques avis avant de decider" },
          { value: "D", text: "Tu prends une decision en assumant l'incertitude" },
        ],
      },
    ],
  },
];

const sectionMap = new Map(
  autodiagnosticSections.map((section) => [section.id, section] as const),
);

export const autodiagnosticQuestions = autodiagnosticSections.flatMap(
  (section) => section.questions,
);

export const autodiagnosticQuestionIds = autodiagnosticQuestions.map(
  (question) => question.id,
);

export function isManagerialLevel(value: unknown): value is ManagerialLevel {
  return typeof value === "string" && managerialLevels.includes(value as ManagerialLevel);
}

export function isAutodiagnosticAnswerValue(
  value: unknown,
): value is AutodiagnosticAnswerValue {
  return (
    typeof value === "string" &&
    AUTODIAGNOSTIC_ANSWER_VALUES.includes(value as AutodiagnosticAnswerValue)
  );
}

export function createEmptyAutodiagnosticAnswers(): AutodiagnosticAnswers {
  return Object.fromEntries(
    autodiagnosticQuestionIds.map((questionId) => [questionId, ""]),
  ) as AutodiagnosticAnswers;
}

export function normalizeAutodiagnosticAnswers(
  value: unknown,
): AutodiagnosticAnswers {
  const nextAnswers = createEmptyAutodiagnosticAnswers();

  if (!value || typeof value !== "object") {
    return nextAnswers;
  }

  for (const questionId of autodiagnosticQuestionIds) {
    const candidate = Reflect.get(value, questionId);

    if (isAutodiagnosticAnswerValue(candidate)) {
      nextAnswers[questionId] = candidate;
    }
  }

  return nextAnswers;
}

export function isAutodiagnosticComplete(
  answers: AutodiagnosticAnswers,
): answers is CompletedAutodiagnosticAnswers {
  return autodiagnosticQuestionIds.every((questionId) =>
    isAutodiagnosticAnswerValue(answers[questionId]),
  );
}

function calculateSectionScore(
  section: DiagnosticSection,
  answers: CompletedAutodiagnosticAnswers,
) {
  const total = section.questions.reduce(
    (score, question) => score + ANSWER_SCORE_MAP[answers[question.id]],
    0,
  );

  return Math.round(total / section.questions.length);
}

function getOverallLabel(globalScore: number) {
  if (globalScore >= 85) {
    return "Posture a fort impact";
  }

  if (globalScore >= 70) {
    return "Pratique solide";
  }

  if (globalScore >= 55) {
    return "Base utile a consolider";
  }

  return "Fondations a renforcer";
}

function joinTitles(titles: string[]) {
  if (titles.length === 0) {
    return "";
  }

  if (titles.length === 1) {
    return titles[0];
  }

  return `${titles[0]} et ${titles[1]}`;
}

export function calculateAutodiagnosticResult(
  managerialLevel: ManagerialLevel,
  answers: CompletedAutodiagnosticAnswers,
): AutodiagnosticResult {
  const sectionScores = autodiagnosticSections.map((section) => ({
    id: section.id,
    title: section.shortTitle,
    score: calculateSectionScore(section, answers),
  }));

  const weights = MANAGERIAL_LEVEL_WEIGHTS[managerialLevel];
  const globalScore = Math.round(
    sectionScores.reduce(
      (total, section) => total + section.score * (weights[section.id] / 100),
      0,
    ),
  );

  const sortedSections = [...sectionScores].sort((left, right) => {
    if (right.score !== left.score) {
      return right.score - left.score;
    }

    return left.title.localeCompare(right.title, "fr");
  });

  const strongestSections = sortedSections.slice(0, 2);
  const weakestSections = [...sortedSections]
    .reverse()
    .slice(0, 2)
    .sort((left, right) => left.score - right.score);

  const strengths = strongestSections.map((section) => {
    const source = sectionMap.get(section.id);
    return source ? source.strengthsCopy : `${section.title} constitue un point d'appui actuel.`;
  });

  const attentionPoints = weakestSections.map((section) => {
    const source = sectionMap.get(section.id);
    return source
      ? source.attentionCopy
      : `${section.title} merite un travail plus structure dans la suite du parcours.`;
  });

  const overallLabel = getOverallLabel(globalScore);
  const summary =
    `Pour le niveau ${managerialLevel}, votre autodiagnostic fait ressortir une ${overallLabel.toLowerCase()}. ` +
    `Vos appuis principaux se situent sur ${joinTitles(
      strongestSections.map((section) => section.title.toLowerCase()),
    )}, tandis que vos priorites de progression concernent ${joinTitles(
      weakestSections.map((section) => section.title.toLowerCase()),
    )}.`;

  return {
    managerialLevel,
    globalScore,
    overallLabel,
    summary,
    strengths,
    attentionPoints,
    sectionScores,
  };
}

export function normalizeAutodiagnosticResult(
  value: unknown,
): AutodiagnosticResult | null {
  if (!value || typeof value !== "object") {
    return null;
  }

  const managerialLevel = Reflect.get(value, "managerialLevel");
  const globalScore = Reflect.get(value, "globalScore");
  const overallLabel = Reflect.get(value, "overallLabel");
  const summary = Reflect.get(value, "summary");
  const strengths = Reflect.get(value, "strengths");
  const attentionPoints = Reflect.get(value, "attentionPoints");
  const rawSectionScores = Reflect.get(value, "sectionScores");

  if (
    !isManagerialLevel(managerialLevel) ||
    typeof globalScore !== "number" ||
    typeof overallLabel !== "string" ||
    typeof summary !== "string" ||
    !Array.isArray(strengths) ||
    !Array.isArray(attentionPoints) ||
    !Array.isArray(rawSectionScores)
  ) {
    return null;
  }

  const sectionScores = rawSectionScores
    .map((section) => {
      if (!section || typeof section !== "object") {
        return null;
      }

      const id = Reflect.get(section, "id");
      const title = Reflect.get(section, "title");
      const score = Reflect.get(section, "score");

      if (
        typeof id !== "string" ||
        !sectionMap.has(id as AutodiagnosticSectionId) ||
        typeof title !== "string" ||
        typeof score !== "number"
      ) {
        return null;
      }

      return {
        id: id as AutodiagnosticSectionId,
        title,
        score: Math.max(0, Math.min(100, Math.round(score))),
      } satisfies AutodiagnosticSectionScore;
    })
    .filter((section): section is AutodiagnosticSectionScore => section !== null);

  if (sectionScores.length !== autodiagnosticSections.length) {
    return null;
  }

  return {
    managerialLevel,
    globalScore: Math.max(0, Math.min(100, Math.round(globalScore))),
    overallLabel: overallLabel.trim(),
    summary: summary.trim(),
    strengths: strengths
      .filter((item): item is string => typeof item === "string")
      .slice(0, 2),
    attentionPoints: attentionPoints
      .filter((item): item is string => typeof item === "string")
      .slice(0, 2),
    sectionScores,
  };
}

export function buildAutodiagnosticPromptContext(
  result: AutodiagnosticResult,
) {
  const sectionLines = result.sectionScores.map(
    (section) => `- ${section.title.toLowerCase()}: ${section.score}/100`,
  );

  return [
    "Autodiagnostic manager:",
    `- niveau_managerial: ${result.managerialLevel}`,
    `- score_global: ${result.globalScore}/100`,
    `- lecture_globale: ${result.overallLabel}`,
    ...sectionLines,
    `- points_forts: ${result.strengths.join(" | ")}`,
    `- points_d_attention: ${result.attentionPoints.join(" | ")}`,
    `- synthese: ${result.summary}`,
  ].join("\n");
}
