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

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

import org.apache.commons.lang3.tuple.Pair;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.admin.security.action.AdminAction;
import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.blackbox.UserWithLogin;
import ru.yandex.webmaster3.core.blackbox.service.BlackboxUsersService;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.sanctions.SanctionsRecheckRequested;
import ru.yandex.webmaster3.core.util.IdUtils;
import ru.yandex.webmaster3.core.util.PageUtils;
import ru.yandex.webmaster3.storage.admin.security.AccessObjectEnum;
import ru.yandex.webmaster3.storage.sanctions.SanctionsFilter;
import ru.yandex.webmaster3.storage.sanctions.SanctionsCHDao;
import ru.yandex.webmaster3.storage.util.clickhouse2.ClickhouseException;

/**
 * @author avhaliullin
 */
@ReadAction
@Description("Отфильтрованные нажатия на кнопочку 'я все исправил' в разделе санкции")
@Component
public class ListSanctionsAction extends AdminAction<ListSanctionsRequest, ListSanctionsResponse> {
    private final BlackboxUsersService blackboxExternalYandexUsersService;
    private final SanctionsCHDao sanctionsCHDao;

    public ListSanctionsAction(@Qualifier("blackboxYandexTeamUsersService") BlackboxUsersService blackboxExternalYandexUsersService,
                               SanctionsCHDao sanctionsCHDao) {
        super(AccessObjectEnum.SANCTIONS);
        this.blackboxExternalYandexUsersService = blackboxExternalYandexUsersService;
        this.sanctionsCHDao = sanctionsCHDao;
    }

    @Override
    public ListSanctionsResponse process(ListSanctionsRequest request) throws WebmasterException {
        WebmasterHostId hostId = null;
        if (request.getHostName() != null) {
            hostId = IdUtils.urlToHostId(request.getHostName());
        }
        Long userId = null;
        if (request.getUserLogin() != null) {
            UserWithLogin user = blackboxExternalYandexUsersService.getUserByLogin(request.getUserLogin());
            if (user == null) {
                return new ListSanctionsResponse.UserNotFoundErrorResponse(request.getUserLogin());
            }
            userId = user.getUserId();
        }
        try {
            Pair<List<ThreatsRecheckRequestView>, Long> result;
            SanctionsFilter filter = SanctionsFilter.builder()
                    .host(hostId)
                    .userId(userId)
                    .dateFrom(request.getFromDate())
                    .dateTo(request.getToDate())
                    .sanctions(request.getSanctions())
                    .build();

            PageUtils.Pager pager = PageUtils.getPage(request.getP(), request.getPSize());
            result = listUsingNativePager(filter, pager);

            return new ListSanctionsResponse.NormalReponse(result.getLeft(), result.getRight());
        } catch (ClickhouseException e) {
            throw new WebmasterException("Failed to list sanctions",
                    new WebmasterErrorResponse.ClickhouseErrorResponse(getClass(), null, e), e);
        }
    }

    private Pair<List<ThreatsRecheckRequestView>, Long> listUsingNativePager(SanctionsFilter filter, PageUtils.Pager pager) throws ClickhouseException {
        long count = sanctionsCHDao.countSanctions(filter);
        List<SanctionsRecheckRequested> sanctions = sanctionsCHDao.listSanctions(filter, pager);
        List<ThreatsRecheckRequestView> requests = sanctions
                .stream()
                .map(ListSanctionsAction::mapSanction)
                .collect(Collectors.toList());
        return Pair.of(requests, count);
    }

    private static ThreatsRecheckRequestView mapSanction(SanctionsRecheckRequested sanction) {
        return new ThreatsRecheckRequestView(
                sanction.getHostId(),
                sanction.getDate().toDateTime(),
                sanction.getUserId(),
                sanction.getSanctions()
        );
    }
}
