package dev.lions.unionflow.client.exception;

import jakarta.el.PropertyNotFoundException;
import jakarta.faces.FacesException;
import jakarta.faces.application.ViewExpiredException;
import jakarta.faces.context.ExceptionHandler;
import jakarta.faces.context.ExceptionHandlerWrapper;
import jakarta.faces.context.FacesContext;
import jakarta.faces.event.ExceptionQueuedEvent;
import jakarta.faces.event.ExceptionQueuedEventContext;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ViewExpiredExceptionHandler extends ExceptionHandlerWrapper {

    private static final Logger LOG = Logger.getLogger(ViewExpiredExceptionHandler.class.getName());
    private ExceptionHandler wrapped;

    public ViewExpiredExceptionHandler(ExceptionHandler wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public ExceptionHandler getWrapped() {
        return wrapped;
    }

    private static boolean isPropertyNotFound(Throwable t) {
        for (Throwable x = t; x != null; x = x.getCause()) {
            if (x instanceof PropertyNotFoundException) return true;
        }
        return false;
    }

    @Override
    public void handle() throws FacesException {
        Iterator<ExceptionQueuedEvent> iterator = getUnhandledExceptionQueuedEvents().iterator();

        while (iterator.hasNext()) {
            ExceptionQueuedEvent event = iterator.next();
            ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
            Throwable throwable = context.getException();

            if (isPropertyNotFound(throwable)) {
                LOG.log(Level.WARNING, "PropertyNotFoundException EL (évite page d''erreur TreeMap): {0}",
                    throwable.getMessage());
                try {
                    FacesContext fc = FacesContext.getCurrentInstance();
                    if (fc != null && fc.getExternalContext() != null && !fc.getResponseComplete()) {
                        fc.getExternalContext().redirect(
                            fc.getExternalContext().getRequestContextPath() + "/pages/secure/organisation/liste.xhtml");
                        fc.responseComplete();
                    }
                } catch (Exception e) {
                    String msg = e != null ? e.getMessage() : "";
                    if (msg != null && (msg.contains("already commited") || msg.contains("already committed"))) {
                        LOG.log(Level.WARNING, "Redirection impossible (réponse déjà envoyée): {0}", msg);
                    } else {
                        LOG.log(Level.SEVERE, "Redirection après PropertyNotFoundException: {0}", msg);
                    }
                }
                iterator.remove();
                continue;
            }

            if (throwable instanceof ViewExpiredException) {
                ViewExpiredException vee = (ViewExpiredException) throwable;
                FacesContext facesContext = FacesContext.getCurrentInstance();
                
                try {
                    LOG.log(Level.INFO, "ViewExpiredException interceptée pour la vue: {0}", vee.getViewId());
                    
                    // Vérifier que FacesContext et ExternalContext sont disponibles
                    if (facesContext != null && facesContext.getExternalContext() != null) {
                        // Stocker l'URL demandée pour redirection après connexion si possible
                        String originalURL = vee.getViewId();
                        try {
                            if (facesContext.getExternalContext().getSessionMap() != null) {
                                facesContext.getExternalContext().getSessionMap().put("redirectURL", originalURL);
                            }
                        } catch (Exception e) {
                            LOG.log(Level.WARNING, "Impossible de stocker l'URL de redirection: {0}", e.getMessage());
                        }
                        
                        // Rediriger vers la racine qui déclenchera Keycloak
                        try {
                            String redirectURL = "/";
                            facesContext.getExternalContext().redirect(
                                facesContext.getExternalContext().getRequestContextPath() + redirectURL
                            );
                            facesContext.responseComplete();
                        } catch (Exception e) {
                            LOG.log(Level.SEVERE, "Erreur lors de la redirection: {0}", e.getMessage());
                            // Fallback: essayer une redirection simple
                            try {
                                facesContext.getExternalContext().redirect("/");
                                facesContext.responseComplete();
                            } catch (Exception fallbackException) {
                                LOG.log(Level.SEVERE, "Impossible de rediriger vers la racine: {0}", fallbackException.getMessage());
                            }
                        }
                    }
                } catch (Exception e) {
                    LOG.log(Level.SEVERE, "Erreur dans ViewExpiredExceptionHandler: {0}", e.getMessage());
                } finally {
                    iterator.remove();
                }
            }
        }
        
        // Laisser le parent gérer les autres exceptions
        getWrapped().handle();
    }
}
