 package com.bonus.canteen.core.tenant;

import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.bonus.canteen.core.common.utils.TenantContextHolder;
import java.io.IOException;

import com.bonus.canteen.core.data.dataset.rule.RoutingRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

 @Component
@Order(Integer.MIN_VALUE)
public class TenantContextHolderFilter extends GenericFilterBean {
   private static final Logger log = LoggerFactory.getLogger(TenantContextHolderFilter.class);
   private final TenantConfigProperties tenantConfigProperties;

   @Override
   public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
      RoutingRule.reset();

      try {
         String tenantId = null;
         if (servletRequest instanceof HttpServletRequest) {
            tenantId = ((HttpServletRequest)servletRequest).getHeader(this.tenantConfigProperties.getCarrierName());
         }

         if (StringUtils.isBlank(tenantId)) {
            tenantId = servletRequest.getParameter(this.tenantConfigProperties.getCarrierName());
         }

         if (CharSequenceUtil.isBlank(tenantId)) {
            TenantContextHolder.setTenantId((Long)null);
         } else {
            if (!tenantId.matches("^\\d+$")) {
               return;
            }

            TenantContextHolder.setTenantId(Long.parseLong(tenantId));
         }

         log.trace("retrieved tenant from request args:{}", TenantContextHolder.getTenantId());
         MDC.put(this.tenantConfigProperties.getMdc(), TenantContextHolder.getTenantId() == null ? null : String.valueOf(TenantContextHolder.getTenantId()));
         filterChain.doFilter(servletRequest, servletResponse);
      } finally {
         RoutingRule.reset();
         TenantContextHolder.clear();
         MDC.remove(this.tenantConfigProperties.getMdc());
      }
   }

   public TenantContextHolderFilter(final TenantConfigProperties tenantConfigProperties) {
      this.tenantConfigProperties = tenantConfigProperties;
   }
}
