package ru.yandex.webmaster3.internal.common.filter;

import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import ru.yandex.autodoc.common.doc.ExtraInfoItem;
import ru.yandex.autodoc.common.doc.params.ParamDescriptor;
import ru.yandex.webmaster3.core.http.RequestFilter;
import ru.yandex.webmaster3.core.http.request.RequestContext;
import ru.yandex.webmaster3.core.http.request.WebmasterUserIdAware;
import ru.yandex.webmaster3.core.security.tvm.TVM2AuthService;
import ru.yandex.webmaster3.core.security.tvm.TVMUserTicket;
import ru.yandex.webmaster3.internal.common.InternalRequest;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author avhaliullin
 */
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class UserSecurityFilter<Req extends InternalRequest & WebmasterUserIdAware> implements RequestFilter<Req, UserSecurityFilterResponse> {
    private static final Logger log = LoggerFactory.getLogger(UserSecurityFilter.class);
    private static final ExtraInfoItem DESCRIPTION_INFO_ITEM = ExtraInfoItem.createSimple("не передается, если есть пользовательский tvm-тикет");
    private static final String TVM_USER_TICKET_HEADER = "X-Ya-User-Ticket";

    private final TVM2AuthService tvm2AuthService;

    @Override
    public UserSecurityFilterResponse beforeRequest(RequestContext ctx, Req req) {
        String userTicketString = ctx.getHttpRequest().getHeader(TVM_USER_TICKET_HEADER);
        if (userTicketString == null) {
            if (req.getGrantOptions().isAllowOffline()) {
                return null;
            } else {
                log.warn("No offline grant provided");
                return new UserSecurityFilterResponse.UserTicketRequired();
            }
        }

        TVMUserTicket userTicket = tvm2AuthService.validateUserTicket(userTicketString.getBytes(StandardCharsets.US_ASCII));
        if (userTicket == null) {
            return new UserSecurityFilterResponse.UserTicketInvalid("User ticket validation failed");
        }
        req.setUserId(userTicket.getUserId());
        return null;
    }

    @Override
    public ParamDescriptor clarifyParameter(ParamDescriptor param) {
        if ("userId".equals(param.getName())) {
            List<ExtraInfoItem> extraInfoItems = new ArrayList<>(param.getExtraInfos());
            extraInfoItems.add(DESCRIPTION_INFO_ITEM);
            return new ParamDescriptor(param.getName(), param.isRequired(), param.getType(), param.getDefaultValue(),
                    param.getDescription(), extraInfoItems);
        } else {
            return param;
        }
    }
}
