/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.unomi.plugins.baseplugin.actions;

import org.apache.commons.lang3.StringUtils;
import org.apache.unomi.api.Event;
import org.apache.unomi.api.Persona;
import org.apache.unomi.api.Profile;
import org.apache.unomi.api.Session;
import org.apache.unomi.api.actions.Action;
import org.apache.unomi.api.actions.ActionExecutor;
import org.apache.unomi.api.actions.ActionPostExecutor;
import org.apache.unomi.api.conditions.Condition;
import org.apache.unomi.api.services.*;
import org.apache.unomi.persistence.spi.PersistenceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

public class MergeProfilesOnPropertyAction implements ActionExecutor {
    private static final Logger logger = LoggerFactory.getLogger(MergeProfilesOnPropertyAction.class.getName());

    private ProfileService profileService;
    private PersistenceService persistenceService;
    private EventService eventService;
    private DefinitionsService definitionsService;
    private PrivacyService privacyService;
    private ConfigSharingService configSharingService;

    public int execute(Action action, Event event) {
        String profileIdCookieName = (String) configSharingService.getProperty("profileIdCookieName");
        String profileIdCookieDomain = (String) configSharingService.getProperty("profileIdCookieDomain");
        Integer profileIdCookieMaxAgeInSeconds = (Integer) configSharingService.getProperty("profileIdCookieMaxAgeInSeconds");

        Profile profile = event.getProfile();
        if (profile instanceof Persona || profile.isAnonymousProfile()) {
            return EventService.NO_CHANGE;
        }

        final String mergeProfilePropertyName = (String) action.getParameterValues().get("mergeProfilePropertyName");
        if (StringUtils.isEmpty(mergeProfilePropertyName)) {
            return EventService.NO_CHANGE;
        }

        final String mergeProfilePropertyValue = (String) action.getParameterValues().get("mergeProfilePropertyValue");
        if (StringUtils.isEmpty(mergeProfilePropertyValue)) {
            return EventService.NO_CHANGE;
        }

        final String mergeProfilePreviousPropertyValue = profile.getSystemProperties().get(mergeProfilePropertyName) != null ? profile.getSystemProperties().get(mergeProfilePropertyName).toString() : "";

        final Session currentSession = event.getSession();

        // store the profile id in case the merge change it to a previous one
        String profileId = profile.getItemId();

        Condition propertyCondition = new Condition(definitionsService.getConditionType("profilePropertyCondition"));
        propertyCondition.setParameter("comparisonOperator", "equals");
        propertyCondition.setParameter("propertyName", "systemProperties." + mergeProfilePropertyName);
        propertyCondition.setParameter("propertyValue", mergeProfilePropertyValue);

        Condition excludeMergedProfilesCondition = new Condition(definitionsService.getConditionType("profilePropertyCondition"));
        excludeMergedProfilesCondition.setParameter("comparisonOperator", "missing");
        excludeMergedProfilesCondition.setParameter("propertyName", "mergedWith");

        Condition c = new Condition(definitionsService.getConditionType("booleanCondition"));
        c.setParameter("operator", "and");
        c.setParameter("subConditions", Arrays.asList(propertyCondition, excludeMergedProfilesCondition));

        final List<Profile> profiles = persistenceService.query(c, "properties.firstVisit", Profile.class);

        // Check if the user switched to another profile
        if (StringUtils.isNotEmpty(mergeProfilePreviousPropertyValue) && !mergeProfilePreviousPropertyValue.equals(mergeProfilePropertyValue)) {
            if (profiles.size() > 0) {
                // Take existing profile
                profile = profiles.get(0);
            } else {
                // Create a new profile
                profile = new Profile(UUID.randomUUID().toString());
                profile.setProperty("firstVisit", event.getTimeStamp());
                profile.getSystemProperties().put(mergeProfilePropertyName, mergeProfilePropertyValue);
            }

            logger.info("Different users, switch to " + profile.getItemId());

            HttpServletResponse httpServletResponse = (HttpServletResponse) event.getAttributes().get(Event.HTTP_RESPONSE_ATTRIBUTE);
            sendProfileCookie(profile, httpServletResponse, profileIdCookieName, profileIdCookieDomain, profileIdCookieMaxAgeInSeconds);

            // At the end of the merge, we must set the merged profile as profile event to process other Actions
            event.setProfileId(profile.getItemId());
            event.setProfile(profile);

            if (currentSession != null) {
                currentSession.setProfile(profile);
                eventService.send(new Event("sessionReassigned", currentSession, profile, event.getScope(), event, currentSession, event.getTimeStamp()));
            }

            return EventService.PROFILE_UPDATED + EventService.SESSION_UPDATED;
        } else {
            // Store the merge property identifier in the profile
            profile.getSystemProperties().put(mergeProfilePropertyName, mergeProfilePropertyValue);

            // add current Profile to profiles to be merged
            boolean add = true;
            for (Profile p : profiles) {
                add = add && !StringUtils.equals(p.getItemId(), profile.getItemId());
            }
            if (add) {
                profiles.add(profile);
            }

            if (profiles.size() == 1) {
                return StringUtils.isEmpty(mergeProfilePreviousPropertyValue) ? EventService.PROFILE_UPDATED : EventService.NO_CHANGE;
            }

            // Use oldest profile for master profile
            final Profile masterProfile = profileService.mergeProfiles(profiles.get(0), profiles);

            // Profile has changed
            if (!masterProfile.getItemId().equals(profileId)) {
                HttpServletResponse httpServletResponse = (HttpServletResponse) event.getAttributes().get(Event.HTTP_RESPONSE_ATTRIBUTE);
                // we still send back the current profile cookie. It will be changed on the next request to the ContextServlet.
                // The current profile will be deleted only then because we cannot delete it right now (too soon)
                sendProfileCookie(profile, httpServletResponse,
                        profileIdCookieName, profileIdCookieDomain, profileIdCookieMaxAgeInSeconds);

                final String masterProfileId = masterProfile.getItemId();
                // At the end of the merge, we must set the merged profile as profile event to process other Actions
                event.setProfileId(masterProfileId);
                event.setProfile(masterProfile);

                final Boolean anonymousBrowsing = privacyService.isRequireAnonymousBrowsing(masterProfileId);

                if (currentSession != null){
                    currentSession.setProfile(masterProfile);
                    if (privacyService.isRequireAnonymousBrowsing(profile)) {
                        privacyService.setRequireAnonymousBrowsing(masterProfileId, true, event.getScope());
                    }

                    if (anonymousBrowsing) {
                        currentSession.setProfile(privacyService.getAnonymousProfile(masterProfile));
                        event.setProfileId(null);
                        persistenceService.save(event);
                    }
                }

                event.getActionPostExecutors().add(new ActionPostExecutor() {
                    @Override
                    public boolean execute() {
                        try {
                            for (Profile profile : profiles) {
                                String profileId = profile.getItemId();
                                if (!StringUtils.equals(profileId, masterProfileId)) {
                                    List<Session> sessions = persistenceService.query("profileId", profileId, null, Session.class);
                                    if (currentSession != null){
                                        if (masterProfileId.equals(profileId) && !sessions.contains(currentSession)) {
                                            sessions.add(currentSession);
                                        }
                                    }

                                    for (Session session : sessions) {
                                        persistenceService.update(session, session.getTimeStamp(), Session.class, "profileId", anonymousBrowsing ? null : masterProfileId);
                                    }

                                    List<Event> events = persistenceService.query("profileId", profileId, null, Event.class);
                                    for (Event event : events) {
                                        persistenceService.update(event, event.getTimeStamp(), Event.class, "profileId", anonymousBrowsing ? null : masterProfileId);
                                    }
                                    // we must mark all the profiles that we merged into the master as merged with the master, and they will
                                    // be deleted upon next load
                                    profile.setMergedWith(masterProfileId);
                                    Map<String,Object> sourceMap = new HashMap<>();
                                    sourceMap.put("mergedWith", masterProfileId);
                                    profile.setSystemProperty("lastUpdated", new Date());
                                    sourceMap.put("systemProperties", profile.getSystemProperties());
                                    persistenceService.update(profile, null, Profile.class, sourceMap);
                                }
                            }
                        } catch (Exception e) {
                            logger.error("unable to execute callback action, profile and session will not be saved", e);
                            return false;
                        }
                        return true;
                    }
                });
                return EventService.PROFILE_UPDATED + EventService.SESSION_UPDATED;
            } else {
                return StringUtils.isEmpty(mergeProfilePreviousPropertyValue) ? EventService.PROFILE_UPDATED : EventService.NO_CHANGE;
            }
        }
    }

    private static void sendProfileCookie(Profile profile, ServletResponse response, String profileIdCookieName, String profileIdCookieDomain, int cookieAgeInSeconds) {
        if (response instanceof HttpServletResponse) {
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
            if (!(profile instanceof Persona)) {
                httpServletResponse.addHeader("Set-Cookie",
                        profileIdCookieName + "=" + profile.getItemId() +
                                "; Path=/" +
                                "; Max-Age=" + cookieAgeInSeconds +
                                (StringUtils.isNotBlank(profileIdCookieDomain) ? ("; Domain=" + profileIdCookieDomain) : "")  +
                                "; SameSite=Lax");
            }
        }
    }

    public void setProfileService(ProfileService profileService) {
        this.profileService = profileService;
    }

    public void setPersistenceService(PersistenceService persistenceService) {
        this.persistenceService = persistenceService;
    }

    public void setEventService(EventService eventService) {
        this.eventService = eventService;
    }

    public void setPrivacyService(PrivacyService privacyService) {
        this.privacyService = privacyService;
    }

    public void setDefinitionsService(DefinitionsService definitionsService) {
        this.definitionsService = definitionsService;
    }

    public void setConfigSharingService(ConfigSharingService configSharingService) {
        this.configSharingService = configSharingService;
    }

}
