<?php

namespace App\Controller\Api;

use App\Entity\AttestationEntretien;
use App\Entity\AttestationEntretienConseil;
use App\Entity\AttestationEntretienPointControle;
use App\Entity\ClassificationEnergetique;
use App\Entity\Conseil;
use App\Entity\EquipementMesure;
use App\Entity\InterventionStack;
use App\Utils\DateUtils;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
use App\Entity\FactureLigne;
use App\Entity\InterventionClasseEnergetique;
use App\Entity\InterventionTypeValidation;
use App\Entity\MotifDebitGaz;
use App\Entity\Observation;
use App\Entity\Planning;
use App\Entity\PointControle;
use App\Entity\Produit;
use App\Entity\TypeEnvoi;
use App\Entity\TypePlanification;
use App\Entity\TypeVisiteIntervention;
use App\Entity\Utilisateur;
use App\Entity\Intervention;
use App\Entity\Equipement;
use App\Entity\Anomalie;
use App\Entity\InterventionMedia;
use App\Entity\ContratPlage;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Post;
use App\Utils\Functions;
use Symfony\Component\HttpFoundation\JsonResponse;
use \DateTime;

/**
 * Class ApiInterventionController
 *
 * @Route("/api/intervention")
 */
class ApiInterventionController extends ApiGlobalController
{
    /**
     * Liste intervention J, J+1
     * @Route("/list/{token_mobilite}", methods={"GET"}, name="intervention_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);
        }

        $em = $this->getDoctrine()->getManager();
        $listePlanification = $em->getRepository(Planning::class)->getPlanificationByAgent($utilisateur, true);

        $plannings = [];
        foreach ($listePlanification as $planning) {
            // Récupérer l'intervention associée à ce planning via la relation
            $intervention = $planning->getIntervention();
            if ($intervention) {
                $this->completeDataIntervention($intervention);
            }
            $plannings[$planning->getDate()->format('Y-m-d H:i:s')][] = $planning;
        }
        $datasPlannings = Functions::getSerialisedEntities($plannings, $serializer, 'api');
        return new JsonResponse($datasPlannings, 201);
    }

    /**
     * historique intervention  pour un client
     * @Route("/historique/{id}/{token_mobilite}", methods="GET", name="historique")
     * @Entity("utilisateur", expr="repository.findOneBy({'token_mobilite': token_mobilite})")
     */
    public function historiqueAction(Equipement $equipement, ?Utilisateur $utilisateur, SerializerInterface $serializer)
    {
        if (!$utilisateur) {
            return new JsonResponse(['message' => 'Utilisateur non trouvé'], JsonResponse::HTTP_NOT_FOUND);
        }

        $em = $this->getDoctrine()->getManager();
        $listeInterventions = $em->getRepository(Intervention::class)->getInterventionByEquipement($equipement);
        $datasInterventions = Functions::getSerialisedEntities($listeInterventions, $serializer, 'api');

        return new JsonResponse(["interventions" => $datasInterventions], 201);
    }


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

        $em = $this->getDoctrine()->getManager();
        $anomalies = $em->getRepository(Anomalie::class)->findAll();
        $datasAnomalies = Functions::getSerialisedEntities($anomalies, $serializer, 'api');
        return new JsonResponse(["anomalies" => $datasAnomalies], 201);

    }


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

        $em = $this->getDoctrine()->getManager();
        $observations = $em->getRepository(Observation::class)->findAll();
        $datasObservations = Functions::getSerialisedEntities($observations, $serializer, 'api');
        return new JsonResponse(["observations" => $datasObservations], 201);

    }


    /**
     * Met à jour le status d'un rdv d'un tech
     *
     * @Route("/update_status/{token_mobilite}", methods="POST", name="update_status")
     * @Entity("utilisateur", expr="repository.findOneBy({'token_mobilite': token_mobilite})")
     */
    public function updateStatusAction(?Utilisateur $utilisateur, SerializerInterface $serializer, Request $request)
    {
        if (!$utilisateur) {
            return new JsonResponse(['message' => 'Utilisateur non trouvé'], JsonResponse::HTTP_NOT_FOUND);
        }

        $em = $this->getDoctrine()->getManager();
        $data = json_decode($request->getContent(), true);

        $em = $this->getDoctrine()->getManager();
        $intervOrigine = $em->getRepository(Intervention::class)->findOneById($data['idIntervention']);
        if ($intervOrigine == null || $intervOrigine->getPlanning()->getUtilisateurAgent() != $utilisateur) { //existe et est pour ce tech
            return new JsonResponse(['message' => 'Intervention non trouvée'], 403);
        }
        if (!$data['idStatut']) {
            return new JsonResponse(['message' => 'Statut non trouvé'], 403);
        }
        switch ($data['idStatut']) {
            case Intervention::STARTED:
                $intervOrigine->getPlanning()->setStatut(Intervention::STARTED);
                $intervOrigine->getPlanning()->setHeureDebutSpecifiee(DateUtils::millisec2date((int)$data['ts']));
                break;
            case Intervention::CANCELED:
                $intervOrigine->getPlanning()->setStatut(Intervention::CANCELED);
                $intervOrigine->getPlanning()->setHeureFinSpecifiee(DateUtils::millisec2date((int)$data['ts']));
                break;
        }
        $em->persist($intervOrigine);
        $em->flush();
        return new JsonResponse(['message' => 'OK'], 201);

    }

    /**
     * Enregistrement intervention
     *
     * @Route("/report/{token}", methods="POST", name="report")
     * @Entity("utilisateur", expr="repository.findOneBy({'token_mobilite': token_mobilite})")
     *
     */
    public function reportAction(?Utilisateur $utilisateur, SerializerInterface $serializer, Request $request)
    {
        if (!$utilisateur) {
            return new JsonResponse(['message' => 'Utilisateur non trouvé'], JsonResponse::HTTP_NOT_FOUND);
        }
        $em = $this->getDoctrine()->getManager();

        $item = $this->pushToStack($utilisateur, 'rdv_report', $request, 0);
        if ($item) {

            $rawContent = $request->getContent();
            $jsonFile_decoded = json_decode($rawContent);
            if(isset($jsonFile_decoded->debutRdv)) {
                $report = json_decode($rawContent, true);
                $intervention = $em->getRepository(Intervention::class)->find((int)$report['id']);

                if ($intervention == null || $intervention->getPlanning()->getUtilisateurAgent() != $utilisateur) { //verif existe et est pour ce tech
                    return new JsonResponse(['message' => 'Intervention non trouvée'], 403);
                }
                $equipement = $intervention->getEquipement();
                //modification dans le planning
                $planning = $intervention->getPlanning();
                $planning->setStatut(Intervention::FINISHED);
                $planning->setHeureDebutSpecifiee();
                $planning->setHeureFinSpecifiee();
                if ($intervention->getTypePlanification() != null) {
                    $typePlanificationInit = $em->getRepository(TypePlanification::class)->findOneById($planning->getTypePlanificationInit()->getId());
                    $planning->setTypePlanificationInit($typePlanificationInit);
                }
                $em->persist($planning);
                //modification client

                //modification intervention
                $typeEnvoiRapport = $em->getRepository(TypeEnvoi::class)->findOneById($intervention->getTypeEnvoiRapport()->getId());
                $typePlanification = null;
                $typeVisiteIntervention = null;
                if ($intervention->getTypePlanification() != null) {
                    $typePlanification = $em->getRepository(TypePlanification::class)->findOneById($intervention->getTypePlanification()->getId());
                }
                if ($intervention->getTypeVisiteIntervention() != null) {
                    $typeVisiteIntervention = $em->getRepository(TypeVisiteIntervention::class)->findOneById($intervention->getTypeVisiteIntervention()->getId());
                }
                $this->updateInterventionReport($intervention, $typeEnvoiRapport, $typePlanification, $typeVisiteIntervention, $report, $rawContent);
               // $intervOrigine = Intervention::update($intervOrigine, $intervModif, $typeEnvoiRapport, $typePlanification, $typeVisiteIntervention, );

                //ajout attestation entretien
                if ($intervModif->getEntretien() == true) {
                    $attestationEntretien = AttestationEntretien::create($intervModif->getAttestationEntretien());
                    $em->persist($attestationEntretien);
                    //conseil
                    $attestationConseils = $intervModif->getAttestationEntretien()->getAttestationEntretienConseils();
                    if ($attestationConseils != null) {
                        foreach ($attestationConseils as $attestationConseil) {
                            if ($attestationConseil->getConseil() != null) {
                                $conseil = $em->getRepository(Conseil::class)->findOneById($attestationConseil->getConseil()->getId());
                                $attestationEntretienConseil = AttestationEntretienConseil::create($attestationEntretien, $conseil);
                                $em->persist($attestationEntretienConseil);
                            }
                        }
                    }
                    //point contrôle
                    $attestationControles = $intervModif->getAttestationEntretien()->getAttestationEntretienPointControles();
                    if ($attestationControles != null) {
                        foreach ($attestationControles as $attestationControle) {
                            if ($attestationControle->getPointControle() != null) {
                                $pointControle = $em->getRepository(PointControle::class)->findOneById($attestationControle->getPointControle()->getId());
                                $motifDebitGaz = null;
                                if ($attestationControle->getMotifDebitGaz() != null) {
                                    $motifDebitGaz = $em->getRepository(MotifDebitGaz::class)->findOneById($attestationControle->getMotifDebitGaz()->getId());
                                }
                                $attestationEntretienPointControle = AttestationEntretienPointControle::create($attestationEntretien, $pointControle, $attestationControle->getValeur(), $motifDebitGaz);
                                $em->persist($attestationEntretienPointControle);
                            }
                        }
                    }
                    $intervOrigine->setAttestationEntretien($attestationEntretien);
                }

                //mesures
                if (count($intervModif->getEquipementMesures()) == 1) {
                    $equipementMesure = EquipementMesure::create($intervModif->getEquipementMesures()[0], $equipement, $intervOrigine);
                    $em->persist($equipementMesure);
                }

                //media
                foreach ($intervModif->getInterventionMedias() as $media) {
                    $interventionMedia = new InterventionMedia();
                    $photo64 = 'data:image/png;base64,' . $media->getMediaString();

                    $interventionMedia
                        ->setMedia($photo64)
                        ->setCommentaire($media->getCommentaire());
                    $intervOrigine->addInterventionMedia($interventionMedia);
                }

                //devis
                $validationAuto = $em->getRepository(InterventionTypeValidation::class)->findOneById(1);
                $dateJour = date('d/m/Y');
                //nécessite validation technique
                //OK : observations, anomalies, commentaire client, modification type intervention, qté co > 10
                // mode paiement, devis, intervention_retour = 41, piece affectation S
                //on contrôle que rien de tout cela n'est saisi pour faire la validation auto

                if ($intervModif->getObservations() == null && count($intervModif->getInterventionAnomalies()) == 0 && $intervModif->getCommentaireClient() == null && $intervModif->getTypePlanification() == null && $intervModif->getMesureCo() <= 10) {
                    $intervOrigine->setTypeValidationTechnique($validationAuto);
                    $intervOrigine->setDateValidationTechnique($dateJour);
                }

                //nécessite validation adm
                //OK : modification type intervention, contrat, modification taux TVA, modification type equipement, modification puissance equipement, modification numéro equipement, local equipement = autre
                //mode paiement, devis, modification échéancier
                //OK : Famille = 0 et date intervention > date fin de contrat
                //Intervention HORS CONTRAT et pas de mode de paiement
                //OK : Intervention MES ou GARANTIE et Famille != 1
                //OK : Intervention INTERNE et non lié
                //modification client : type, nom, prénom
                //num série équipement
                //on contrôle que rien de tout cela n'est saisi pour faire la validation auto
                if ($intervModif->getTypePlanification() == null //pas de modification type intervention
                    && $intervModif->getContrat() == null //pas de contrat
                    && $intervModif->getCommentaireClient() == null //pas de commentaire client
                    && ($intervModif->getEquipement()->getTauxTva()->getId() == $intervOrigine->getEquipement()->getTauxTva()->getId()) //pas de modification du taux TVA
                    && ($intervModif->getEquipement()->getEquipementTypePuissance()->getEquipementType()->getId() == $intervOrigine->getEquipement()->getEquipementTypePuissance()->getEquipementType()->getId()) //pas de modification type equipement
                    && ($intervModif->getEquipement()->getEquipementTypePuissance()->getEquipementPuissance()->getId() == $intervOrigine->getEquipement()->getEquipementTypePuissance()->getEquipementPuissance()->getId()) //pas de modification puissance equipement
                    && ($intervModif->getEquipement()->getNumSeriePrincipal() == $intervOrigine->getEquipement()->getNumSeriePrincipal()) //pas de modification numéro equipement
                    && ($intervModif->getEquipement()->getNumSerieSecondaire() == $intervOrigine->getEquipement()->getNumSerieSecondaire()) //pas de modification numéro equipement
                    && ($intervModif->getEquipement()->getEquipementLocal() != null
                        && (($intervOrigine->getEquipement()->getEquipementLocal() != null && $intervModif->getEquipement()->getEquipementLocal()->getId() == $intervOrigine->getEquipement()->getEquipementLocal()->getId())
                            || $intervModif->getEquipement()->getEquipementLocal()->getLibelle() != 'Autre')) //si modification et local equipement != autre
                    && ($intervOrigine->getEquipement()->getEquipementFamilleContrat()->getCode() != 0 || ($intervOrigine->getEquipement()->getEquipementFamilleContrat()->getId() == 0 && $intervOrigine->getPlanning()->getDate() <= $intervOrigine->getEquipement()->getLastContrat()->getDateFinContrat()))//Famille !=0 OU (Famille = 0 et date intervention <= date fin de contrat)
                    && (!in_array($intervOrigine->getPlanning()->getTypePlanificationInit()->getCode(), ['MES', 'GARANTIE']) || ($intervOrigine->getEquipement()->getEquipementFamilleContrat()->getCode() == 1 && in_array($intervOrigine->getPlanning()->getTypePlanificationInit()->getCode(), ['MES', 'GARANTIE'])))//Type intervention = MES ou GARANTIE et Famille ==1
                    && ($intervOrigine->getPlanning()->getTypePlanificationInit()->getCode() != 'INTERNE' || ($intervOrigine->getPlanning()->getTypePlanificationInit()->getCode() == 'INTERNE' && $intervOrigine->getPlanning()->getCodeRegroup() != null))//Intervention INTERNE et lié
                ) {
                    $intervOrigine->setTypeValidationAdm($validationAuto);
                    $intervOrigine->setDateValidationAdm($dateJour);
                }

                //si pas besoin de validation : création facture

                $intervOrigine->getPlanning()->setStatut(Intervention::FINISHED);
                $em->persist($intervOrigine);
                $em->flush();
            } else {
                //envoyer mail d'erreur à etude
            }
        }

        //génération PDF fiche d'intervention + avis d'échéance + lettre d'accompagnement
        //Ajout dans la table communication_client
        return new JsonResponse(['message' => 'OK'], 201);
    }


        /**
         * Ajoute un "POST" entrant à la stack et retourne TRUE si nouveau
         * @param Tech $tech technicien/agent
         * @param String $route route (méthode entrante)
         * @param Request $request Request entrante => extraction du post content
         * @return boolean|sctring CHECKSUM si new, FALSE sinon
         */
        private function pushToStack($tech, $route, Request $request, $status = 1, $force = false)
    {
        $em = $this->getDoctrine()->getManager();
        $content = $request->getContent();
        $checksum = hash("sha256", $content);
        $item = $em->getRepository(InterventionStack::class)->findOneBy(array('checksum' => $checksum, 'agent' => $tech));
        if ($item == null) {
            $item = new InterventionStack();
            $item->setAgent($tech);
            $item->setRoute($route);
            $item->setContent($content);
            $item->setChecksum($checksum);
            $em->persist($item);
            $em->flush();
            return $item;
        } elseif ($force) { // item exists
            return ($request->query->get('force')) ? $item : false;
        }
        return false;
    }

    private function updateInterventionReport(Intervention $intervention, TypeEnvoi $typeEnvoiRapport, TypePlanification $typePlanification = null, TypeVisiteIntervention $typeVisiteIntervention = null, $report, $stack) {
        $intervention
            ->setMemo($report['report']['memo'])
            ->setMesureCo($report['report']['mesure_co'])
            ->setObservations($report['report']['observations'])
            ->setCgvAcceptees($report['report']['cgv_acceptees'])
            ->setCommentaireClient($report['report']['commentaire_client'])
            ->setTypeEnvoiRapport($typeEnvoiRapport)
            ->setMotifModifCodeInt($report['report']['motif_modif_code_int'])
            ->setCliRefusSignature($report['report']['cli_refus_signature'])
            ->setCommentaireRefusSignature($report['report']['commentaire_refus_signature'])
            ->setFichePapierLiee($report['report']['fiche_papier_liee'])
            ->setTypePlanification($typePlanification)
            ->setEntretien($report['report']['entretien'])
            ->setTypeVisiteIntervention($typeVisiteIntervention)
            ->setStack($stack)
        ;
        return $intervention;
    }
}