package com.astalange.web.controller;

import com.astalange.core.entity.*;
import com.astalange.core.repository.CategorieRepository;
import com.astalange.core.repository.CreneauEntrainementRepository;
import com.astalange.core.repository.EducateurRepository;
import com.astalange.core.repository.EquipeRepository;
import com.astalange.core.repository.SaisonRepository;
import com.astalange.core.repository.TerrainRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.*;

@Controller
@RequestMapping("/planning")
public class PlanningController {

    private final CreneauEntrainementRepository creneauRepository;
    private final TerrainRepository terrainRepository;
    private final CategorieRepository categorieRepository;
    private final SaisonRepository saisonRepository;
    private final EquipeRepository equipeRepository;
    private final EducateurRepository educateurRepository;

    public PlanningController(CreneauEntrainementRepository creneauRepository,
                              TerrainRepository terrainRepository,
                              CategorieRepository categorieRepository,
                              SaisonRepository saisonRepository,
                              EquipeRepository equipeRepository,
                              EducateurRepository educateurRepository) {
        this.creneauRepository = creneauRepository;
        this.terrainRepository = terrainRepository;
        this.categorieRepository = categorieRepository;
        this.saisonRepository = saisonRepository;
        this.equipeRepository = equipeRepository;
        this.educateurRepository = educateurRepository;
    }

    @GetMapping
    public String showPlanning(@RequestParam(required = false) JourSemaine jour, Model model) {
        Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null);
        if (saisonActive == null) {
            model.addAttribute("noActiveSeason", true);
            return "planning/planning";
        }

        JourSemaine selectedDay = (jour != null) ? jour : JourSemaine.LUNDI;
        List<Terrain> terrains = terrainRepository.findAll();
        
        // Sort terrains to ensure consistent order (Terrain Vert then Terrain Synthétique)
        terrains.sort(Comparator.comparing(Terrain::getId));

        Map<Long, Integer> terrainIndices = new HashMap<>();
        for (int i = 0; i < terrains.size(); i++) {
            terrainIndices.put(terrains.get(i).getId(), i);
        }

        List<CreneauEntrainement> creneaux = creneauRepository.findBySaisonAndJourSemaineFetch(saisonActive, selectedDay);
        List<Educateur> educateurs = educateurRepository.findAllWithCategorieAndEquipe();

        // Detect conflicts and populate educator initials
        for (int i = 0; i < creneaux.size(); i++) {
            CreneauEntrainement c1 = creneaux.get(i);

            // Populate educator initials
            List<String> initials = new ArrayList<>();
            for (Educateur ed : educateurs) {
                boolean match = false;
                if (c1.getEquipe() != null) {
                    if (ed.getEquipe() != null && ed.getEquipe().getId().equals(c1.getEquipe().getId())) {
                        match = true;
                    }
                } else if (c1.getCategorie() != null) {
                    if (ed.getCategorie() != null && ed.getCategorie().getId().equals(c1.getCategorie().getId())) {
                        match = true;
                    } else if (ed.getEquipe() != null && ed.getEquipe().getCategorie() != null && ed.getEquipe().getCategorie().getId().equals(c1.getCategorie().getId())) {
                        match = true;
                    }
                }
                if (match) {
                    initials.add(ed.getInitiales());
                }
            }
            c1.setInitialesEducateurs(String.join(", ", initials));

            for (int j = 0; j < creneaux.size(); j++) {
                if (i == j) continue;
                CreneauEntrainement c2 = creneaux.get(j);
                if (c1.overlapsWith(c2)) {
                    c1.setEnConflit(true);
                    c1.getCategoriesEnConflit().add(c2.getCategorie().getNom());
                }
            }
        }

        model.addAttribute("saisonActive", saisonActive);
        model.addAttribute("selectedDay", selectedDay);
        model.addAttribute("jours", JourSemaine.values());
        model.addAttribute("terrains", terrains);
        model.addAttribute("terrainIndices", terrainIndices);
        model.addAttribute("creneaux", creneaux);

        return "planning/planning";
    }

    @GetMapping("/new")
    public String showCreateForm(Model model, RedirectAttributes redirectAttributes) {
        Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null);
        if (saisonActive == null) {
            redirectAttributes.addFlashAttribute("error", "Veuillez activer une saison avant de planifier un créneau.");
            return "redirect:/saisons";
        }

        CreneauEntrainement creneau = new CreneauEntrainement();
        creneau.setSaison(saisonActive);
        
        model.addAttribute("creneau", creneau);
        model.addAttribute("categories", categorieRepository.findBySaison(saisonActive));
        model.addAttribute("terrains", terrainRepository.findAll());
        model.addAttribute("zones", ZoneTerrain.values());
        model.addAttribute("jours", JourSemaine.values());
        model.addAttribute("equipes", List.of());

        return "planning/form";
    }

    @GetMapping("/{id}/edit")
    public String showEditForm(@PathVariable Long id, Model model, RedirectAttributes redirectAttributes) {
        CreneauEntrainement creneau = creneauRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Créneau introuvable : " + id));

        model.addAttribute("creneau", creneau);
        model.addAttribute("categories", categorieRepository.findBySaison(creneau.getSaison()));
        model.addAttribute("terrains", terrainRepository.findAll());
        model.addAttribute("zones", ZoneTerrain.values());
        model.addAttribute("jours", JourSemaine.values());

        if (creneau.getCategorie() != null) {
            model.addAttribute("equipes", equipeRepository.findByCategorieId(creneau.getCategorie().getId()));
        } else {
            model.addAttribute("equipes", List.of());
        }

        return "planning/form";
    }

    @PostMapping
    public String saveCreneau(@ModelAttribute("creneau") CreneauEntrainement creneau, BindingResult result, Model model, RedirectAttributes redirectAttributes) {
        // Validation
        if (creneau.getHeureDebut() != null && creneau.getHeureFin() != null) {
            if (!creneau.getHeureDebut().isBefore(creneau.getHeureFin())) {
                result.rejectValue("heureDebut", "error.heureDebut", "L'heure de début doit être antérieure à l'heure de fin.");
            }
            if (creneau.getHeureDebut().isBefore(java.time.LocalTime.of(8, 0)) || creneau.getHeureFin().isAfter(java.time.LocalTime.of(22, 0))) {
                result.rejectValue("heureDebut", "error.heureDebut", "Les entraînements doivent se dérouler entre 08:00 et 22:00.");
            }
        }

        if (creneau.getEquipe() != null && creneau.getEquipe().getId() == null) {
            creneau.setEquipe(null);
        }

        if (result.hasErrors()) {
            Saison saison = creneau.getSaison();
            if (saison == null) {
                saison = saisonRepository.findByEstActiveTrue().orElseThrow();
                creneau.setSaison(saison);
            }
            model.addAttribute("categories", categorieRepository.findBySaison(saison));
            model.addAttribute("terrains", terrainRepository.findAll());
            model.addAttribute("zones", ZoneTerrain.values());
            model.addAttribute("jours", JourSemaine.values());
            if (creneau.getCategorie() != null && creneau.getCategorie().getId() != null) {
                model.addAttribute("equipes", equipeRepository.findByCategorieId(creneau.getCategorie().getId()));
            } else {
                model.addAttribute("equipes", List.of());
            }
            return "planning/form";
        }

        // Set active season if not set (for new items)
        if (creneau.getSaison() == null) {
            Saison saisonActive = saisonRepository.findByEstActiveTrue().orElseThrow();
            creneau.setSaison(saisonActive);
        }

        creneauRepository.save(creneau);
        redirectAttributes.addFlashAttribute("success", "Créneau d'entraînement enregistré avec succès.");
        return "redirect:/planning?jour=" + creneau.getJourSemaine().name();
    }

    @PostMapping("/{id}/delete")
    public String deleteCreneau(@PathVariable Long id, RedirectAttributes redirectAttributes) {
        CreneauEntrainement creneau = creneauRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Créneau introuvable : " + id));
        JourSemaine jour = creneau.getJourSemaine();
        creneauRepository.delete(creneau);
        redirectAttributes.addFlashAttribute("success", "Créneau d'entraînement supprimé avec succès.");
        return "redirect:/planning?jour=" + jour.name();
    }
}
