package org.sagebionetworks.bridge.play.controllers;

import static org.sagebionetworks.bridge.dao.ParticipantOption.EMAIL_NOTIFICATIONS;

import java.util.Map;

import org.sagebionetworks.bridge.dao.AccountDao;
import org.sagebionetworks.bridge.models.accounts.Account;
import org.sagebionetworks.bridge.models.accounts.HealthId;
import org.sagebionetworks.bridge.models.studies.Study;
import org.sagebionetworks.bridge.services.HealthCodeService;
import org.sagebionetworks.bridge.services.ParticipantOptionsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import play.data.DynamicForm;
import play.data.Form;
import play.mvc.Result;

@Controller
public class EmailController extends BaseController {

    private AccountDao accountDao;
    private ParticipantOptionsService optionsService;
    private HealthCodeService healthCodeService;

    @Autowired
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Autowired
    public void setParticipantOptionsService(ParticipantOptionsService optionsService) {
        this.optionsService = optionsService;
    }

    @Autowired
    public void setHealthCodeService(HealthCodeService healthCodeService) {
        this.healthCodeService = healthCodeService;
    }

    /**
     * An URL to which a POST can be sent to set the user's email notification preference to "off". Cannot turn email
     * notifications back on through this endpoint. This cannot be part of the public API, because MailChimp doesn't
     * deal with non-200 status codes. The token that is submitted is set in the configuration, and must match to allow
     * this call to succeed. Subject to change without warning or backwards compatibility.
     * 
     * @return
     * @throws Exception
     */
    public Result unsubscribeFromEmail() throws Exception {
        try {
            String token = getParameter("token");
            if (token == null || !token.equals(getBridgeConfig().getEmailUnsubscribeToken())) {
                throw new RuntimeException("Not authorized.");
            }
            // Study has to be provided as an URL parameter:
            String studyId = getParameter("study");
            if (studyId == null) {
                throw new RuntimeException("Study not found.");
            }
            Study study = studyService.getStudy(studyId);

            // MailChimp submits email as data[email]
            String email = getParameter("data[email]");
            if (email == null) {
                email = getParameter("email");
            }
            if (email == null) {
                throw new RuntimeException("Email not found.");
            }
            Account account = accountDao.getAccount(study, email);
            if (account == null) {
                throw new RuntimeException("Account not found.");
            }
            HealthId healthId = healthCodeService.getMapping(account.getHealthId());
            if (healthId == null) {
                throw new RuntimeException("Health code not found.");
            }
            optionsService.setBoolean(study, healthId.getCode(), EMAIL_NOTIFICATIONS, false);

            return ok("You have been unsubscribed from future email.");
        } catch(Throwable throwable) {
            return ok(throwable.getMessage());
        }
    }

    /**
     * No idea how you're supposed to test all this static PF stuff. Will use a spy
     * to work around it.
     */
    protected DynamicForm getPostData() {
        return Form.form().bindFromRequest();
    }

    private String getParameter(String paramName) {
        Map<String, String[]> parameters = request().queryString();
        String[] values = parameters.get(paramName);
        String param = (values != null && values.length > 0) ? values[0] : null;
        if (param == null) {
            // How are you supposed to test crap like this?
            DynamicForm requestData = getPostData();
            param = requestData.get("data[email]");
            if (param == null) {
                param = requestData.get("email");
            }
        }
        return param;
    }

}

@@ -503,32 +503,135 @@
 tOptionsService;
+%0A%0Aimport org.apache.commons.lang3.StringUtils;%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;
 %0Aimport org.spri
@@ -872,16 +872,95 @@
 roller %7B
+%0A    private final Logger LOG = LoggerFactory.getLogger(EmailController.class);
 %0A%0A    pr
@@ -3530,40 +3530,275 @@
     
-return ok(throwable.getMessage()
+String errorMsg = %22Unknown error%22;%0A            if (StringUtils.isNotBlank(throwable.getMessage())) %7B%0A                errorMsg = throwable.getMessage();%0A            %7D%0A%0A            LOG.error(%22Error unsubscribing: %22 + errorMsg, throwable);%0A            return ok(errorMsg
 );%0A 

add logging and null check to unsubscribe API