package com.astalange.web.controller;

import com.astalange.core.entity.Adherent;
import com.astalange.core.entity.Categorie;
import com.astalange.core.entity.Licence;
import com.astalange.core.entity.Saison;
import com.astalange.core.repository.AdherentRepository;
import com.astalange.core.repository.CategorieRepository;
import com.astalange.core.repository.SaisonRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping("/adherents")
public class AdherentController {

    private final AdherentRepository adherentRepository;
    private final CategorieRepository categorieRepository;
    private final com.astalange.core.repository.LicenceRepository licenceRepository;
    private final com.astalange.core.repository.ModePaiementRepository modePaiementRepository;
    private final SaisonRepository saisonRepository;
    private final com.astalange.core.service.CategorieService categorieService;

    public AdherentController(AdherentRepository adherentRepository, CategorieRepository categorieRepository, com.astalange.core.repository.LicenceRepository licenceRepository, com.astalange.core.repository.ModePaiementRepository modePaiementRepository, SaisonRepository saisonRepository, com.astalange.core.service.CategorieService categorieService) {
        this.adherentRepository = adherentRepository;
        this.categorieRepository = categorieRepository;
        this.licenceRepository = licenceRepository;
        this.modePaiementRepository = modePaiementRepository;
        this.saisonRepository = saisonRepository;
        this.categorieService = categorieService;
    }

    @org.springframework.web.bind.annotation.ModelAttribute("equipes")
    public List<com.astalange.core.entity.Equipe> populateEquipes() {
        return List.of();
    }

    @GetMapping
    public String listAdherents(
            @org.springframework.web.bind.annotation.RequestParam(required = false) String query,
            @org.springframework.web.bind.annotation.RequestParam(required = false) String nom,
            @org.springframework.web.bind.annotation.RequestParam(required = false) String prenom,
            @org.springframework.web.bind.annotation.RequestParam(required = false) String categorie,
            @org.springframework.web.bind.annotation.RequestParam(required = false) String licence,
            @org.springframework.web.bind.annotation.RequestParam(required = false) String email,
            @org.springframework.web.bind.annotation.RequestParam(required = false) String paiement,
            @org.springframework.web.bind.annotation.RequestParam(defaultValue = "0") int page,
            @org.springframework.web.bind.annotation.RequestParam(defaultValue = "20") int size,
            Model model) {

        List<Adherent> adherents = adherentRepository.findAllWithLicencesAndCategories();

        // 1. Filter by global query
        if (query != null && !query.trim().isEmpty()) {
            String q = query.trim().toLowerCase();
            adherents = adherents.stream().filter(a -> 
                (a.getNom() != null && a.getNom().toLowerCase().contains(q)) ||
                (a.getPrenom() != null && a.getPrenom().toLowerCase().contains(q)) ||
                (a.getLicenceActuelle() != null && a.getLicenceActuelle().getNumeroLicence() != null && a.getLicenceActuelle().getNumeroLicence().toLowerCase().contains(q))
            ).collect(java.util.stream.Collectors.toList());
            model.addAttribute("searchQuery", query.trim());
        }

        // 2. Filter by specific column filters
        if (nom != null && !nom.trim().isEmpty()) {
            String n = nom.trim().toLowerCase();
            adherents = adherents.stream().filter(a -> a.getNom() != null && a.getNom().toLowerCase().contains(n)).collect(java.util.stream.Collectors.toList());
            model.addAttribute("nomFilter", nom.trim());
        }
        if (prenom != null && !prenom.trim().isEmpty()) {
            String p = prenom.trim().toLowerCase();
            adherents = adherents.stream().filter(a -> a.getPrenom() != null && a.getPrenom().toLowerCase().contains(p)).collect(java.util.stream.Collectors.toList());
            model.addAttribute("prenomFilter", prenom.trim());
        }
        if (categorie != null && !categorie.trim().isEmpty()) {
            adherents = adherents.stream().filter(a -> 
                a.getLicenceActuelle() != null && 
                a.getLicenceActuelle().getCategorie() != null && 
                a.getLicenceActuelle().getCategorie().getNom().equalsIgnoreCase(categorie.trim())
            ).collect(java.util.stream.Collectors.toList());
            model.addAttribute("categorieFilter", categorie.trim());
        }
        if (licence != null && !licence.trim().isEmpty()) {
            String l = licence.trim().toLowerCase();
            adherents = adherents.stream().filter(a -> 
                a.getLicenceActuelle() != null && 
                a.getLicenceActuelle().getNumeroLicence() != null && 
                a.getLicenceActuelle().getNumeroLicence().toLowerCase().contains(l)
            ).collect(java.util.stream.Collectors.toList());
            model.addAttribute("licenceFilter", licence.trim());
        }
        if (email != null && !email.trim().isEmpty()) {
            String e = email.trim().toLowerCase();
            adherents = adherents.stream().filter(a -> a.getEmail() != null && a.getEmail().toLowerCase().contains(e)).collect(java.util.stream.Collectors.toList());
            model.addAttribute("emailFilter", email.trim());
        }
        if (paiement != null && !paiement.trim().isEmpty()) {
            adherents = adherents.stream().filter(a -> {
                String statut = a.getStatutPaiement();
                if ("A_JOUR".equalsIgnoreCase(paiement)) {
                    return "À jour".equalsIgnoreCase(statut);
                } else if ("RESTE".equalsIgnoreCase(paiement)) {
                    return statut != null && statut.startsWith("Reste");
                } else if ("AUCUNE".equalsIgnoreCase(paiement)) {
                    return "Aucune licence".equalsIgnoreCase(statut);
                }
                return true;
            }).collect(java.util.stream.Collectors.toList());
            model.addAttribute("paiementFilter", paiement.trim());
        }

        // 3. Paginate
        int totalElements = adherents.size();
        int totalPages = (int) Math.ceil((double) totalElements / size);
        if (page < 0) page = 0;
        if (page >= totalPages && totalPages > 0) page = totalPages - 1;

        int start = page * size;
        int end = Math.min(start + size, totalElements);
        List<Adherent> pageContent = (start < totalElements) ? adherents.subList(start, end) : List.of();

        model.addAttribute("adherents", pageContent);
        model.addAttribute("currentPage", page);
        model.addAttribute("totalPages", totalPages);
        model.addAttribute("totalElements", totalElements);
        model.addAttribute("pageSize", size);

        Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null);
        if (saisonActive != null) {
            model.addAttribute("categories", categorieRepository.findBySaison(saisonActive));
        } else {
            model.addAttribute("categories", categorieRepository.findAll());
        }

        return "adherents/list";
    }

    @GetMapping("/new")
    public String showCreateForm(Model model) {
        model.addAttribute("adherent", new Adherent());
        return "adherents/form";
    }

    @org.springframework.web.bind.annotation.PostMapping
    public String saveAdherent(
            @jakarta.validation.Valid @org.springframework.web.bind.annotation.ModelAttribute("adherent") Adherent adherent,
            org.springframework.validation.BindingResult result,
            Model model) {
        
        if (result.hasErrors()) {
            if (adherent.getId() != null) {
                Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null);
                if (saisonActive != null) {
                    model.addAttribute("categories", categorieRepository.findBySaison(saisonActive));
                    model.addAttribute("saisonActive", saisonActive);
                } else {
                    model.addAttribute("categories", categorieRepository.findAll());
                }
                model.addAttribute("licences", licenceRepository.findByAdherentId(adherent.getId()));
                model.addAttribute("modesPaiement", modePaiementRepository.findAll());
            } else {
                Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null);
                if (saisonActive != null) {
                    model.addAttribute("categories", categorieRepository.findBySaison(saisonActive));
                } else {
                    model.addAttribute("categories", categorieRepository.findAll());
                }
            }
            return "adherents/form";
        }
        
        if (adherent.getId() != null) {
            Adherent existing = adherentRepository.findById(adherent.getId()).orElse(null);
            if (existing != null) {
                boolean dateChanged = !existing.getDateNaissance().equals(adherent.getDateNaissance());
                
                if (dateChanged) {
                    int newBirthYear = adherent.getDateNaissance().getYear();
                    List<Licence> licences = licenceRepository.findByAdherentId(adherent.getId());
                    for (Licence licence : licences) {
                        Saison saison = licence.getSaison();
                        Categorie newCat = categorieRepository.findBySaison(saison).stream()
                                .filter(c -> newBirthYear >= c.getAnneeMin() && newBirthYear <= c.getAnneeMax())
                                .findFirst()
                                .orElse(null);
                        if (newCat != null) {
                            licence.setCategorie(newCat);
                            licence = licenceRepository.save(licence);
                            categorieService.syncDotationsForLicence(licence);
                        }
                    }
                }
                
                existing.setNom(adherent.getNom());
                existing.setPrenom(adherent.getPrenom());
                existing.setDateNaissance(adherent.getDateNaissance());
                existing.setLieuNaissanceVille(adherent.getLieuNaissanceVille());
                existing.setLieuNaissancePays(adherent.getLieuNaissancePays());
                existing.setNationalite(adherent.getNationalite());
                existing.setEmail(adherent.getEmail());
                existing.setRepresentantLegal(adherent.getRepresentantLegal());
                existing.setResidentTalange(adherent.isResidentTalange());
                existing.setSexe(adherent.getSexe());
                existing.setTypeMaillot(adherent.getTypeMaillot());
                
                adherentRepository.save(existing);
            } else {
                adherentRepository.save(adherent);
            }
            return "redirect:/adherents";
        } else {
            Adherent saved = adherentRepository.save(adherent);
            return "redirect:/adherents/" + saved.getId() + "/edit";
        }
    }

    @GetMapping("/{id}/edit")
    public String editAdherent(@org.springframework.web.bind.annotation.PathVariable Long id, Model model) {
        Adherent adherent = adherentRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Adhérent invalide : " + id));
                
        Saison saisonActive = saisonRepository.findByEstActiveTrue().orElse(null);
        if (saisonActive != null) {
            model.addAttribute("categories", categorieRepository.findBySaison(saisonActive));
            model.addAttribute("saisonActive", saisonActive);
        } else {
            model.addAttribute("categories", categorieRepository.findAll());
        }

        model.addAttribute("adherent", adherent);
        model.addAttribute("licences", licenceRepository.findByAdherentId(id));
        model.addAttribute("modesPaiement", modePaiementRepository.findAll());
        return "adherents/form";
    }

    @org.springframework.web.bind.annotation.PostMapping("/{id}/delete")
    public String deleteAdherent(@org.springframework.web.bind.annotation.PathVariable Long id) {
        Adherent adherent = adherentRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Adhérent invalide : " + id));
        adherentRepository.delete(adherent);
        return "redirect:/adherents";
    }
}
