<?php

namespace App\Controller\Api;

use App\Entity\EquipementFamille;
use App\Entity\Groupe;
use App\Entity\GroupeType;
use App\Entity\MomentPassage;
use App\Entity\Planning;
use App\Entity\PlanningHistoriqueModification;
use App\Entity\PlanningAction;
use App\Entity\PlanningInitiativeDetail;
use App\Entity\PlanningInitiativeType;
use App\Entity\TypePlanification;
use App\Entity\Utilisateur;
use App\Utils\Functions;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;

/**
 * Class ApiInterventionController
 *
 * @Route("/api/planning")
 */
class ApiPlanningController extends AbstractController
{

    /**
     * @Route("/config/{token_mobilite}", methods="GET", name="planning_config")
     * @Entity("utilisateur", expr="repository.findOneBy({'token_mobilite': token_mobilite})")
     */
    public function configAction(?Utilisateur $utilisateur, SerializerInterface $serializer, Request $request)
    {
        if (!$utilisateur) {
            return new JsonResponse(['message' => 'Utilisateur non trouvé'], JsonResponse::HTTP_NOT_FOUND);
        }
        $em = $this->getDoctrine()->getManager();
        $site = $utilisateur->getAgence()->getSite();
        $momentPassage = $em->getRepository(MomentPassage::class)->findAll();
        $typePlanification = $em->getRepository(TypePlanification::class)->findAll();
        $groupePole = $em->getRepository(Groupe::class)->findBy(['groupe_type' => GroupeType::ID_POLE, 'site' => $site]);
        $responsables = $em->getRepository(Utilisateur::class)->getUtilisateursResponsable([$site]);
        $techs = $em->getRepository(Utilisateur::class)->getUtilisateursAgent([$site]);
        $equipementFamille = $em->getRepository(EquipementFamille::class)->findAll();
        return new JsonResponse(["moment_passage" => Functions::getSerialisedEntities($momentPassage, $serializer, 'api'),
            "type_planification" => Functions::getSerialisedEntities($typePlanification, $serializer, 'api'),
            "groupe_pole" => Functions::getSerialisedEntities($groupePole, $serializer, 'planning'),
            "responsables" => Functions::getSerialisedEntities($responsables, $serializer, 'planning'),
            "agents" => Functions::getSerialisedEntities($techs, $serializer, 'planning'),
            "qualifications" => Functions::getSerialisedEntities($equipementFamille, $serializer, 'api')
        ], 201);
    }

    /**
     * @Route("/list/{token_mobilite}", methods="POST", name="list")
     * @Entity("utilisateur", expr="repository.findOneBy({'token_mobilite': token_mobilite})")
     */
    public function listAction(?Utilisateur $utilisateur, SerializerInterface $serializer, Request $request)
    {
        if (!$utilisateur) {
            return new JsonResponse(['message' => 'Utilisateur non trouvé'], JsonResponse::HTTP_NOT_FOUND);
        }

        $rawContent = $request->getContent();
        $jsonFile_decoded = json_decode($rawContent);

        $agents = $jsonFile_decoded->agents;
        $em = $this->getDoctrine()->getManager();
        $planifications = [];
        foreach ($agents as $codeAgent) {
            $agent = $em->getRepository(Utilisateur::class)->find($codeAgent);
            $listePlanification = $em->getRepository(Planning::class)->getPlanificationByAgent($agent);
            $planifications[$agent->getId()] = $listePlanification;
        }
        $datasPlanifications = Functions::getSerialisedEntities($planifications, $serializer, 'planning');
        return new JsonResponse(["planifications" => $datasPlanifications], 201);
    }

    /**
     * Modifier un planning
     * @Route("/update/{id}/{token_mobilite}", methods="PUT", name="update")
     * @Entity("utilisateur", expr="repository.findOneBy({'token_mobilite': token_mobilite})")
     */
    public function updateAction($id, ?Utilisateur $utilisateur, Request $request, SerializerInterface $serializer)
    {
        if (!$utilisateur) {
            return new JsonResponse(['message' => 'Utilisateur non trouvé'], JsonResponse::HTTP_NOT_FOUND);
        }

        $em = $this->getDoctrine()->getManager();
        $planning = $em->getRepository(Planning::class)->find($id);

        if (!$planning) {
            return new JsonResponse(['message' => 'Planning non trouvé'], JsonResponse::HTTP_NOT_FOUND);
        }
        $data = json_decode($request->getContent());
        if (!$data) {
            return new JsonResponse(['message' => 'Données invalides ou manquantes'], JsonResponse::HTTP_BAD_REQUEST);
        }
        // Mise à jour dynamique de tous les champs présents dans la requête
        $modifs = [];
        foreach ($data->planning as $field => $value) {
            // Conversion snake_case en camelCase
            $camelField = preg_replace_callback('/_([a-z])/', function ($matches) {
                return strtoupper($matches[1]);
            }, $field);
            $setter = 'set' . ucfirst($camelField);
            $getter = 'get' . ucfirst($camelField);
            if (method_exists($planning, $setter) && method_exists($planning, $getter)) {
                $reflection = new \ReflectionMethod($planning, $setter);
                $params = $reflection->getParameters();
                $currentValue = $planning->$getter();
                $newValue = $value;
                $isDifferent = false;
                if (is_object($value) && count($params) > 0) {
                    $paramType = $params[0]->getType();
                    if ($paramType && !$paramType->isBuiltin()) {
                        $entityClass = $paramType->getName();
                        if (isset($value->id)) {
                            $entity = $em->getRepository($entityClass)->find($value->id);
                            $newValue = $entity;
                        }
                    }
                    $isDifferent = $currentValue->getId() !== $newValue->getId();
                }else if (count($params) > 0 && $params[0]->getType() && $params[0]->getType()->getName() === 'DateTimeInterface') {
                    $newValue = new \DateTime($value);
                    $isDifferent = $currentValue->format('Y-m-d H:i:s') !== $newValue->format('Y-m-d H:i:s');

                }else {
                    $isDifferent = $currentValue !== $newValue;
                }      
                if ($isDifferent) {
                    $planning->$setter($newValue);
                    $modifs[] = $field;
                }
            }
        }
        $lastModif = $planning->getLastPlanningHistoriqueModification();
        if (count($modifs) === 0){
            if((!isset($data->actions->planning_initiative_type) && !isset($data->actions->planning_initiative_detail))
                || ((isset($data->actions->planning_initiative_type) && $data->actions->planning_initiative_type->id == $lastModif->getPlanningInitiativeType()->getId())
                    && (isset($data->actions->planning_initiative_detail) && $data->actions->planning_initiative_detail->id == $lastModif->getPlanningInitiativeDetail()->getId()))) {
                return new JsonResponse([
                    'message' => 'Aucune modification n\'a été effectuée. Veuillez vérifier les données.'
                ], JsonResponse::HTTP_BAD_REQUEST);
            }
        } else {
            $em->persist($planning);
            $em->flush();
        }

        // Historisation de la modification uniquement s'il y a eu modif
        $historique = new PlanningHistoriqueModification();
        $historique->setPlanning($planning);
        $historique->setUtilisateur($utilisateur);
        $historique->setDateAction(new \DateTime());
        $historique->setMemo('Modification via API');
        $planningAction = $em->getRepository(PlanningAction::class)->find(15); // Déplacement à l'initiative du SAV
        if ($planningAction) {
            $historique->setPlanningAction($planningAction);
        }
        if ($planning->getEquipement()) {
            $historique->setEquipement($planning->getEquipement());
        }
        if ($planning->getUtilisateurAgent()) {
            $historique->setUtilisateurAgent($planning->getUtilisateurAgent());
        }
        if ($planning->getTypePlanificationInit()) {
            $historique->setTypePlanification($planning->getTypePlanificationInit());
        }
        if ($planning->getDate()) {
            $historique->setDate($planning->getDate());
        }
        if ($planning->getMomentPassage()) {
            $historique->setMomentPassage($planning->getMomentPassage());
        }
        // Récupérer les valeurs depuis le json
        if (isset($data->actions->planning_initiative_type) && isset($data->actions->planning_initiative_type->id)) {
            $initiativeType = $em->getRepository(PlanningInitiativeType::class)->find($data->actions->planning_initiative_type->id);
            if ($initiativeType) {
                $historique->setPlanningInitiativeType($initiativeType);
                $modifs[] = 'planning_initiative_type';
            }
        }
        if (isset($data->actions->planning_initiative_detail) && isset($data->actions->planning_initiative_detail->id)) {
            $initiativeDetail = $em->getRepository(PlanningInitiativeDetail::class)->find($data->actions->planning_initiative_detail->id);
            if ($initiativeDetail) {
                $historique->setPlanningInitiativeDetail($initiativeDetail);
                $modifs[] = 'planning_initiative_detail';
            }
        }
        $em->persist($historique);
        $em->flush();

        $serializedPlanning = Functions::getSerialisedEntities($planning, $serializer, 'planning');
        return new JsonResponse([
            'message' => 'Planning modifié',
            'modifications' => $modifs,
            'planning' => $serializedPlanning
        ], 201);
    }
    
}