"use client";

import { useEffect, useState } from "react";
import { useUser } from "@/hooks/use-user-context";
import {
  UserEvaluation,
  Team,
  SkillLevel,
  UserProfile,
  CategoryEvaluation,
} from "@/lib/types";
import {
  updateSkillLevel as updateSkillLevelAction,
  updateSkillMentorStatus as updateSkillMentorStatusAction,
  updateSkillLearningStatus as updateSkillLearningStatusAction,
  addSkillToEvaluation as addSkillToEvaluationAction,
  removeSkillFromEvaluation as removeSkillFromEvaluationAction,
} from "@/lib/evaluation-actions";
import { createEmptyEvaluation } from "@/lib/evaluation-utils";

interface EvaluationClientWrapperProps {
  userEvaluation: UserEvaluation | null;
  teams: Team[];
  children: React.ReactNode;
  skillCategories?: any[]; // Ajouter les catégories pour créer une évaluation vide
}

export function EvaluationClientWrapper({
  userEvaluation,
  teams,
  children,
  skillCategories = [],
}: EvaluationClientWrapperProps) {
  const { userInfo, setUserInfo } = useUser();

  // État local pour l'UI optimiste - commence avec les données SSR
  const [currentEvaluation, setCurrentEvaluation] =
    useState<UserEvaluation | null>(userEvaluation);

  // Met à jour l'état local quand les props changent (SSR)
  useEffect(() => {
    if (userEvaluation) {
      setCurrentEvaluation(userEvaluation);
    } else if (skillCategories.length > 0) {
      // Créer une évaluation vide si aucune n'existe, pour que l'UI puisse fonctionner
      const emptyEvaluation: UserEvaluation = {
        profile: { firstName: "", lastName: "", teamId: "" }, // Profile temporaire
        evaluations: createEmptyEvaluation(skillCategories),
        lastUpdated: new Date().toISOString(),
      };
      setCurrentEvaluation(emptyEvaluation);
    }
  }, [userEvaluation, skillCategories]);

  // Fonctions avec UI optimiste
  const updateSkillLevel = async (
    category: string,
    skillId: string,
    level: SkillLevel
  ) => {
    if (!currentEvaluation) return;

    // Sauvegarder l'état actuel pour le rollback
    const previousEvaluation = currentEvaluation;

    try {
      // Optimistic UI update - mettre à jour immédiatement l'interface
      const updatedEvaluations = currentEvaluation.evaluations.map(
        (catEval) => {
          if (catEval.category === category) {
            const existingSkill = catEval.skills.find(
              (s) => s.skillId === skillId
            );
            const updatedSkills = existingSkill
              ? catEval.skills.map((skill) =>
                  skill.skillId === skillId ? { ...skill, level } : skill
                )
              : [
                  ...catEval.skills,
                  { skillId, level, canMentor: false, wantsToLearn: false },
                ];

            return {
              ...catEval,
              skills: updatedSkills,
            };
          }
          return catEval;
        }
      );

      const newEvaluation: UserEvaluation = {
        ...currentEvaluation,
        evaluations: updatedEvaluations,
        lastUpdated: new Date().toISOString(),
      };

      setCurrentEvaluation(newEvaluation);

      // Appel API en arrière-plan
      await updateSkillLevelAction(category, skillId, level);
    } catch (error) {
      console.error("Failed to update skill level:", error);
      // Rollback optimiste en cas d'erreur
      setCurrentEvaluation(previousEvaluation);
    }
  };

  const updateSkillMentorStatus = async (
    category: string,
    skillId: string,
    canMentor: boolean
  ) => {
    if (!currentEvaluation) return;

    const previousEvaluation = currentEvaluation;

    try {
      const updatedEvaluations = currentEvaluation.evaluations.map(
        (catEval) => {
          if (catEval.category === category) {
            const updatedSkills = catEval.skills.map((skill) =>
              skill.skillId === skillId ? { ...skill, canMentor } : skill
            );

            return {
              ...catEval,
              skills: updatedSkills,
            };
          }
          return catEval;
        }
      );

      const newEvaluation: UserEvaluation = {
        ...currentEvaluation,
        evaluations: updatedEvaluations,
        lastUpdated: new Date().toISOString(),
      };

      setCurrentEvaluation(newEvaluation);
      await updateSkillMentorStatusAction(category, skillId, canMentor);
    } catch (error) {
      console.error("Failed to update skill mentor status:", error);
      setCurrentEvaluation(previousEvaluation);
    }
  };

  const updateSkillLearningStatus = async (
    category: string,
    skillId: string,
    wantsToLearn: boolean
  ) => {
    if (!currentEvaluation) return;

    const previousEvaluation = currentEvaluation;

    try {
      const updatedEvaluations = currentEvaluation.evaluations.map(
        (catEval) => {
          if (catEval.category === category) {
            const updatedSkills = catEval.skills.map((skill) =>
              skill.skillId === skillId ? { ...skill, wantsToLearn } : skill
            );

            return {
              ...catEval,
              skills: updatedSkills,
            };
          }
          return catEval;
        }
      );

      const newEvaluation: UserEvaluation = {
        ...currentEvaluation,
        evaluations: updatedEvaluations,
        lastUpdated: new Date().toISOString(),
      };

      setCurrentEvaluation(newEvaluation);
      await updateSkillLearningStatusAction(category, skillId, wantsToLearn);
    } catch (error) {
      console.error("Failed to update skill learning status:", error);
      setCurrentEvaluation(previousEvaluation);
    }
  };

  const addSkillToEvaluation = async (category: string, skillId: string) => {
    if (!currentEvaluation) return;

    const previousEvaluation = currentEvaluation;

    try {
      // 1. Mise à jour optimiste de l'UI (immédiate)
      let updatedEvaluations: CategoryEvaluation[] =
        currentEvaluation.evaluations.map((catEval) => {
          if (catEval.category === category) {
            // Si la compétence n'est pas déjà ajoutée
            if (!catEval.selectedSkillIds.includes(skillId)) {
              return {
                ...catEval,
                selectedSkillIds: [...catEval.selectedSkillIds, skillId],
                skills: [
                  ...catEval.skills,
                  {
                    skillId,
                    level: "never" as SkillLevel,
                    canMentor: false,
                    wantsToLearn: false,
                  },
                ],
              };
            }
          }
          return catEval;
        });

      // Si la catégorie n'existe pas encore, la créer
      if (
        !updatedEvaluations.find(
          (evaluation) => evaluation.category === category
        )
      ) {
        const newCategoryEvaluation: CategoryEvaluation = {
          category,
          selectedSkillIds: [skillId],
          skills: [
            {
              skillId,
              level: "never",
              canMentor: false,
              wantsToLearn: false,
            },
          ],
        };
        updatedEvaluations = [...updatedEvaluations, newCategoryEvaluation];
      }

      const newEvaluation: UserEvaluation = {
        ...currentEvaluation,
        evaluations: updatedEvaluations,
        lastUpdated: new Date().toISOString(),
      };

      // 2. Mettre à jour l'état local immédiatement
      setCurrentEvaluation(newEvaluation);

      // 3. Persister côté serveur (en arrière-plan)
      await addSkillToEvaluationAction(category, skillId);
    } catch (error) {
      console.error("❌ Failed to add skill:", error);
      // En cas d'erreur, rollback l'état local
      setCurrentEvaluation(previousEvaluation);
    }
  };

  const addMultipleSkillsToEvaluation = async (
    category: string,
    skillIds: string[]
  ) => {
    if (!currentEvaluation || skillIds.length === 0) return;

    const previousEvaluation = currentEvaluation;

    try {
      // 1. Mise à jour optimiste de l'UI (immédiate)
      const updatedEvaluations: CategoryEvaluation[] =
        currentEvaluation.evaluations.map((catEval) => {
          if (catEval.category === category) {
            // Filtrer seulement les compétences qui ne sont pas déjà sélectionnées
            const newSkillIds = skillIds.filter(
              (skillId) => !catEval.selectedSkillIds.includes(skillId)
            );

            if (newSkillIds.length > 0) {
              return {
                ...catEval,
                selectedSkillIds: [...catEval.selectedSkillIds, ...newSkillIds],
                skills: [
                  ...catEval.skills,
                  ...newSkillIds.map((skillId) => ({
                    skillId,
                    level: "never" as SkillLevel,
                    canMentor: false,
                    wantsToLearn: false,
                  })),
                ],
              };
            }
          }
          return catEval;
        });

      const newEvaluation: UserEvaluation = {
        ...currentEvaluation,
        evaluations: updatedEvaluations,
        lastUpdated: new Date().toISOString(),
      };

      // 2. Mettre à jour l'état local immédiatement
      setCurrentEvaluation(newEvaluation);

      // 3. Persister côté serveur (en arrière-plan)
      await Promise.all(
        skillIds.map((skillId) => addSkillToEvaluationAction(category, skillId))
      );
    } catch (error) {
      console.error("❌ Failed to add multiple skills:", error);
      // En cas d'erreur, rollback l'état local
      setCurrentEvaluation(previousEvaluation);
    }
  };

  const removeSkillFromEvaluation = async (
    category: string,
    skillId: string
  ) => {
    if (!currentEvaluation) return;

    const previousEvaluation = currentEvaluation;

    try {
      const updatedEvaluations = currentEvaluation.evaluations.map(
        (catEval) => {
          if (catEval.category === category) {
            return {
              ...catEval,
              selectedSkillIds: catEval.selectedSkillIds.filter(
                (id) => id !== skillId
              ),
              skills: catEval.skills.filter(
                (skill) => skill.skillId !== skillId
              ),
            };
          }
          return catEval;
        }
      );

      const newEvaluation: UserEvaluation = {
        ...currentEvaluation,
        evaluations: updatedEvaluations,
        lastUpdated: new Date().toISOString(),
      };

      setCurrentEvaluation(newEvaluation);
      await removeSkillFromEvaluationAction(category, skillId);
    } catch (error) {
      console.error("Failed to remove skill from evaluation:", error);
      setCurrentEvaluation(previousEvaluation);
    }
  };

  // Update user info in navigation when user evaluation is loaded
  useEffect(() => {
    if (currentEvaluation) {
      const teamName =
        teams.find((t) => t.id === currentEvaluation.profile.teamId)?.name ||
        "";
      setUserInfo({
        firstName: currentEvaluation.profile.firstName,
        lastName: currentEvaluation.profile.lastName,
        teamName,
      });
    } else {
      setUserInfo(null);
    }
  }, [currentEvaluation, teams, setUserInfo]);

  // Provide evaluation functions to children through React context or props
  return (
    <EvaluationProvider
      currentEvaluation={currentEvaluation}
      updateSkillLevel={updateSkillLevel}
      updateSkillMentorStatus={updateSkillMentorStatus}
      updateSkillLearningStatus={updateSkillLearningStatus}
      addSkillToEvaluation={addSkillToEvaluation}
      addMultipleSkillsToEvaluation={addMultipleSkillsToEvaluation}
      removeSkillFromEvaluation={removeSkillFromEvaluation}
    >
      {children}
    </EvaluationProvider>
  );
}

// Simple context provider for evaluation functions
import { createContext, useContext } from "react";

interface EvaluationContextType {
  currentEvaluation: UserEvaluation | null;
  updateSkillLevel: (categoryId: string, skillId: string, level: any) => void;
  updateSkillMentorStatus: (
    categoryId: string,
    skillId: string,
    canMentor: boolean
  ) => void;
  updateSkillLearningStatus: (
    categoryId: string,
    skillId: string,
    wantsToLearn: boolean
  ) => void;
  addSkillToEvaluation: (categoryId: string, skillId: string) => void;
  addMultipleSkillsToEvaluation: (
    categoryId: string,
    skillIds: string[]
  ) => void;
  removeSkillFromEvaluation: (categoryId: string, skillId: string) => void;
}

const EvaluationContext = createContext<EvaluationContextType | undefined>(
  undefined
);

function EvaluationProvider({
  children,
  currentEvaluation,
  updateSkillLevel,
  updateSkillMentorStatus,
  updateSkillLearningStatus,
  addSkillToEvaluation,
  addMultipleSkillsToEvaluation,
  removeSkillFromEvaluation,
}: {
  children: React.ReactNode;
} & EvaluationContextType) {
  return (
    <EvaluationContext.Provider
      value={{
        currentEvaluation,
        updateSkillLevel,
        updateSkillMentorStatus,
        updateSkillLearningStatus,
        addSkillToEvaluation,
        addMultipleSkillsToEvaluation,
        removeSkillFromEvaluation,
      }}
    >
      {children}
    </EvaluationContext.Provider>
  );
}

export function useEvaluationContext() {
  const context = useContext(EvaluationContext);
  if (context === undefined) {
    throw new Error(
      "useEvaluationContext must be used within an EvaluationProvider"
    );
  }
  return context;
}
