package ru.yandex.webmaster3.admin.action.spamban;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.admin.security.action.AbstractAdminRequest;
import ru.yandex.webmaster3.admin.security.action.AdminAction;
import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.http.ActionResponse;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.http.RequestQueryProperty;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.http.request.PagerAware;
import ru.yandex.webmaster3.core.util.PageUtils;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;
import ru.yandex.webmaster3.storage.admin.security.AccessObjectEnum;
import ru.yandex.webmaster3.storage.user.SpamBanRule;
import ru.yandex.webmaster3.storage.user.dao.SpamBanRulesYDao;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;
import ru.yandex.wmtools.common.error.UserException;

/**
 * Created by ifilippov5 on 22.12.16.
 */
@ReadAction
@Description("Вывод всех правил.")
@Component("/admin/spamban/rule/list")
public class ListRulesAction extends AdminAction<ListRulesAction.Request, ListRulesAction.Response> {
    @Autowired
    private SpamBanRulesYDao spamBanRulesYDao;

    public ListRulesAction() {
        super(AccessObjectEnum.SPAM_BAN);
    }

    @Override
    public Response process(Request request) throws WebmasterException {
        List<SpamBanRule> spamBanRules;
        try {
            Stream<SpamBanRule> rulesStream = spamBanRulesYDao.getRules().parallelStream();
            if (!StringUtils.isEmpty(request.maskFilter)) {
                rulesStream = rulesStream.filter(
                        rule -> {
                            boolean weaklyMatches = rule.getMask().contains(request.maskFilter);
                            try {
                                return rule.getIpInfo().matches(request.maskFilter) || weaklyMatches;
                            } catch (UserException e) {
                                return weaklyMatches;
                            }
                        }
                );
            }
            spamBanRules = rulesStream
                    .sorted((o1, o2) -> o2.getUpdateDate().compareTo(o1.getUpdateDate()))
                    .collect(Collectors.toList());
        } catch (WebmasterYdbException e) {
            throw new WebmasterException("Unable to list spam ban rules",
                    new WebmasterErrorResponse.YDBErrorResponse(this.getClass(), e), e);
        }
        PageUtils.Pager page = PageUtils.getPage(request.page, request.pageSize, spamBanRules.size());
        List<SpamBanRule> result;
        if (page.isEmpty()) {
            result = Collections.emptyList();
        } else {
            result = spamBanRules.subList(page.toRangeStart(), Math.min(page.toRangeStart() + page.getPageSize(), spamBanRules.size()));
        }

        return new Response(spamBanRules.size(), result);
    }

    public static class Request extends AbstractAdminRequest implements PagerAware {
        private String maskFilter;
        private int page;
        private int pageSize = 20;

        @Override
        public void setP(int page) {
            this.page = page;
        }

        @Override
        @RequestQueryProperty("20")
        public void setPSize(int pageSize) {
            this.pageSize = pageSize;
        }

        @Description("Фильтр по вхождению подстроки в маске")
        @RequestQueryProperty()
        public void setMaskFilter(String maskFilter) {
            this.maskFilter = maskFilter;
        }
    }

    public static class Response implements ActionResponse.NormalResponse {
        private final int totalSpamBanRules;
        private final List<SpamBanRule> spamBanRules;

        public Response(int totalSpamBanRules, List<SpamBanRule> spamBanRules) {
            this.totalSpamBanRules = totalSpamBanRules;
            this.spamBanRules = spamBanRules;
        }

        public int getTotalSpamBanRules() {
            return totalSpamBanRules;
        }

        public List<SpamBanRule> getSpamBanRules() {
            return spamBanRules;
        }
    }
}
