package com.astalange.web.controller;

import com.astalange.core.entity.Licence;
import com.astalange.core.entity.ModePaiement;
import com.astalange.core.entity.Paiement;
import com.astalange.core.entity.AuditLogPaiement;
import com.astalange.core.repository.AuditLogPaiementRepository;
import com.astalange.core.repository.LicenceRepository;
import com.astalange.core.repository.ModePaiementRepository;
import com.astalange.core.repository.PaiementRepository;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.security.Principal;

import java.math.BigDecimal;
import java.time.LocalDate;

@Controller
public class PaiementController {

    private final LicenceRepository licenceRepository;
    private final ModePaiementRepository modePaiementRepository;
    private final PaiementRepository paiementRepository;
    private final AuditLogPaiementRepository auditLogPaiementRepository;

    public PaiementController(LicenceRepository licenceRepository, ModePaiementRepository modePaiementRepository, PaiementRepository paiementRepository, AuditLogPaiementRepository auditLogPaiementRepository) {
        this.licenceRepository = licenceRepository;
        this.modePaiementRepository = modePaiementRepository;
        this.paiementRepository = paiementRepository;
        this.auditLogPaiementRepository = auditLogPaiementRepository;
    }

    @PostMapping("/licences/{id}/paiements")
    public String addPaiement(
            @PathVariable Long id,
            @RequestParam Long adherentId,
            @RequestParam BigDecimal montant,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate datePaiement,
            @RequestParam Long modePaiementId,
            Principal principal) {

        Licence licence = licenceRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Invalid Licence ID"));
        ModePaiement mode = modePaiementRepository.findById(modePaiementId)
                .orElseThrow(() -> new IllegalArgumentException("Invalid ModePaiement ID"));

        // Validation basique pour ne pas payer plus que le reste à payer
        if (montant.compareTo(licence.getResteAPayer()) > 0) {
            montant = licence.getResteAPayer();
        }

        if (montant.compareTo(BigDecimal.ZERO) > 0) {
            Paiement paiement = new Paiement();
            paiement.setLicence(licence);
            paiement.setModePaiement(mode);
            paiement.setMontant(montant);
            paiement.setDatePaiement(datePaiement);
            if (principal != null) {
                paiement.setGestionnaire(principal.getName());
            }
            paiementRepository.save(paiement);
            
            AuditLogPaiement log = new AuditLogPaiement();
            log.setAction("CREATE");
            log.setUtilisateur(principal != null ? principal.getName() : "Système");
            log.setPaiementId(paiement.getId());
            log.setMontant(montant);
            log.setAdherentNomComplet(licence.getAdherent().getNom() + " " + licence.getAdherent().getPrenom());
            log.setDetails("Création d'un paiement de " + montant + "€ via " + mode.getNom() + " pour la licence " + (licence.getNumeroLicence() != null ? licence.getNumeroLicence() : "sans numéro"));
            auditLogPaiementRepository.save(log);
        }

        return "redirect:/adherents/" + adherentId + "/edit";
    }

    @PostMapping("/paiements/{id}/update")
    public String updatePaiement(
            @PathVariable Long id,
            @RequestParam BigDecimal montant,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate datePaiement,
            @RequestParam Long modePaiementId,
            @RequestParam(required = false) String redirect,
            Principal principal) {

        Paiement paiement = paiementRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Invalid Paiement ID"));
        
        ModePaiement mode = modePaiementRepository.findById(modePaiementId)
                .orElseThrow(() -> new IllegalArgumentException("Invalid ModePaiement ID"));

        BigDecimal ancienMontant = paiement.getMontant();
        String ancienMode = paiement.getModePaiement().getNom();

        Licence licence = paiement.getLicence();
        
        // Validation basique pour ne pas dépasser le montant total de la licence
        BigDecimal maxAmount = licence.getResteAPayer().add(paiement.getMontant());
        if (montant.compareTo(maxAmount) > 0) {
            montant = maxAmount;
        }

        if (montant.compareTo(BigDecimal.ZERO) > 0) {
            paiement.setModePaiement(mode);
            paiement.setMontant(montant);
            paiement.setDatePaiement(datePaiement);
            if (principal != null) {
                paiement.setGestionnaire(principal.getName());
            }
            paiementRepository.save(paiement);

            AuditLogPaiement log = new AuditLogPaiement();
            log.setAction("UPDATE");
            log.setUtilisateur(principal != null ? principal.getName() : "Système");
            log.setPaiementId(paiement.getId());
            log.setMontant(montant);
            log.setAdherentNomComplet(licence.getAdherent().getNom() + " " + licence.getAdherent().getPrenom());
            log.setDetails("Modification du paiement: montant " + ancienMontant + "€ -> " + montant + "€, mode " + ancienMode + " -> " + mode.getNom());
            auditLogPaiementRepository.save(log);
        }

        if (redirect != null && !redirect.isEmpty()) {
            return "redirect:" + redirect;
        }
        return "redirect:/adherents/" + licence.getAdherent().getId() + "/edit";
    }

    @PostMapping("/paiements/{id}/delete")
    public String deletePaiement(
            @PathVariable Long id,
            @RequestParam(required = false) String redirect,
            Principal principal) {

        Paiement paiement = paiementRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Invalid Paiement ID"));

        Long adherentId = paiement.getLicence().getAdherent().getId();

        AuditLogPaiement log = new AuditLogPaiement();
        log.setAction("DELETE");
        log.setUtilisateur(principal != null ? principal.getName() : "Système");
        log.setPaiementId(paiement.getId());
        log.setMontant(paiement.getMontant());
        log.setAdherentNomComplet(paiement.getLicence().getAdherent().getNom() + " " + paiement.getLicence().getAdherent().getPrenom());
        log.setDetails("Suppression du paiement de " + paiement.getMontant() + "€ via " + paiement.getModePaiement().getNom());
        auditLogPaiementRepository.save(log);

        paiementRepository.delete(paiement);

        if (redirect != null && !redirect.isEmpty()) {
            return "redirect:" + redirect;
        }
        return "redirect:/adherents/" + adherentId + "/edit";
    }
}
