package ru.yandex.webmaster3.worker.review;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import ru.yandex.webmaster3.core.notification.LanguageEnum;
import ru.yandex.webmaster3.core.review.SendReviewComplaintEMailTaskData;
import ru.yandex.webmaster3.core.util.IdUtils;
import ru.yandex.webmaster3.core.worker.task.TaskResult;
import ru.yandex.webmaster3.storage.notifications.service.EmailSenderService;
import ru.yandex.webmaster3.storage.user.UserPersonalInfo;
import ru.yandex.webmaster3.storage.user.service.UserPersonalInfoService;
import ru.yandex.webmaster3.tanker.I18nSupportEmailCommons;
import ru.yandex.webmaster3.worker.Task;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author: ishalaru
 * DATE: 19.07.2019
 * Отправляем в support письмо о том, что владелец пожаловался на отзыв на сайт.
 */

@Slf4j
@Component("sendComplaintTask")
public class SendComplaintTask extends Task<SendReviewComplaintEMailTaskData> {
    private static final ObjectMapper OM = new ObjectMapper();
    static final int MAX_RETRY_ATTEMPT = 5;

    private final EmailSenderService emailSenderService;
    private final UserPersonalInfoService userPersonalInfoService;
    private Collection<String> supportEmailAddresses;

    @Autowired
    public SendComplaintTask(EmailSenderService emailSenderService,
                             UserPersonalInfoService userPersonalInfoService,
                             @Value("#{'${webmaster3.worker.review.complaint.support.email.address}'.split(',')}") Collection<String> supportEmailAddresses) {
        this.emailSenderService = emailSenderService;
        this.userPersonalInfoService = userPersonalInfoService;
        this.supportEmailAddresses = supportEmailAddresses;
    }

    @Override
    public Result run(SendReviewComplaintEMailTaskData data) throws Exception {
        final String subject = makeSubject(data);
        final String body = makeBody(data);
        if (!send(new ArrayList<>(supportEmailAddresses), subject, body)) {
            log.error("Can't send email to {}, with body: {}", supportEmailAddresses, body);
            return new Result(TaskResult.UNKNOWN);
        }
        return new Result(TaskResult.SUCCESS);
    }

    private String makeBody(SendReviewComplaintEMailTaskData data) {
        return I18nSupportEmailCommons
                .COMPLAINT_BODY
                .newBuilder(LanguageEnum.DEFAULT_EMAIL_LANGUAGE)
                .site(IdUtils.hostIdToUrl(data.getHostId()))
                .text(data.getComplaintText())
                .json_message(buildJsonValue(data))
                .render();
    }

    private String buildJsonValue(SendReviewComplaintEMailTaskData data) {
        final Map<Long, UserPersonalInfo> usersPersonalInfos =
                userPersonalInfoService.getUsersPersonalInfos(List.of(data.getUserId(), data.getReviewUserId()));
        final UserPersonalInfo abuseUserInfo = usersPersonalInfos.get(data.getUserId());
        final UserPersonalInfo reviewUserInfo = usersPersonalInfos.get(data.getReviewUserId());
        var builder = ComplaintEmailBody.builder();
        builder.abuse(data.getComplaintText())
                .abuseLogin(abuseUserInfo.getLogin())
                .abuseUid(abuseUserInfo.getUserId())
                .abuseTimestamp(data.getComplaintTime().getMillis())
                .reviewId(data.getReviewId())
                .reviewLogin(reviewUserInfo.getLogin())
                .reviewTimestamp(data.getReviewTime().getMillis())
                .reviewText(data.getReviewText())
                .reviewUid(data.getReviewUserId())
                .mapsUrl(IdUtils.hostIdToUrl(data.getHostId()))
                .permalink(IdUtils.hostIdToUrl(data.getHostId()))
        ;
        try {
            return OM.writeValueAsString(builder.build());
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    private String makeSubject(SendReviewComplaintEMailTaskData data) {
        final String site = IdUtils.hostIdToUrl(data.getHostId());
        return I18nSupportEmailCommons
                .COMPLAINT_SUBJECT
                .newBuilder(LanguageEnum.DEFAULT_EMAIL_LANGUAGE)
                .site(site)
                .render();
    }

    private boolean send(Collection<String> supportEmailAddresses, String subject, String body) {
        int value = MAX_RETRY_ATTEMPT;
        while (!supportEmailAddresses.isEmpty() && value > 0) {
            Iterator<String> item = supportEmailAddresses.iterator();
            while (item.hasNext()) {
                if (emailSenderService.sendEmail(item.next(), "", subject, body)) {
                    item.remove();
                }
            }
            value--;
        }
        return supportEmailAddresses.isEmpty();

    }

    @Override
    public Class<SendReviewComplaintEMailTaskData> getDataClass() {
        return SendReviewComplaintEMailTaskData.class;
    }

    @lombok.Value
    @Builder
    public static class ComplaintEmailBody {
        @JsonProperty("review")
        String reviewText;
        @JsonProperty("review_id")
        String reviewId;
        @JsonProperty("review_login")
        String reviewLogin;
        @JsonProperty("review_uid")
        long reviewUid;
        @JsonProperty("review_timestamp")
        long reviewTimestamp;
        @JsonProperty("permalink")
        String permalink;
        @JsonProperty("maps_url")
        String mapsUrl;
        @JsonProperty("abuse")
        String abuse;
        @JsonProperty("abuse_uid")
        Long abuseUid;
        @JsonProperty("abuse_login")
        String abuseLogin;
        @JsonProperty("abuse_timestamp")
        long abuseTimestamp;
    }
}
