package com.bizzan.bitrade.interceptor;


import lombok.extern.slf4j.Slf4j;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.env.Environment;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.bizzan.bitrade.constant.Platform;
import com.bizzan.bitrade.constant.SysConstant;
import com.bizzan.bitrade.entity.AppRevision;
import com.bizzan.bitrade.entity.Member;
import com.bizzan.bitrade.entity.transform.AuthMember;
import com.bizzan.bitrade.event.MemberEvent;
import com.bizzan.bitrade.service.AppRevisionService;
import com.bizzan.bitrade.service.MemberService;
import com.bizzan.bitrade.util.RedisManager;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;

/**
 * @author
 * @date 2020年01月11日
 */
@Slf4j
public class MemberInterceptor implements HandlerInterceptor {

    /** 按平台分别缓存最低版本号，避免每次请求查库（0=Android, 1=iOS） */
    private static volatile String cachedLowestVersionAndroid = null;
    private static volatile String cachedLowestVersionIos = null;
    private static volatile long lastRefreshTimeAndroid = 0L;
    private static volatile long lastRefreshTimeIos = 0L;
    private static final long CACHE_TTL_MS = 5 * 60 * 1000L;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // ── 版本检查：与强制更新逻辑一致 ───────────────────────────
        BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        boolean versionCheckEnabled = factory.getBean(Environment.class)
                .getProperty("app.version.check.enabled", Boolean.class, false);
        if (versionCheckEnabled) {
            String appVersion = request.getHeader("x-app-version");
            String platformHeader = request.getHeader("x-app-platform");
            // 兜底：内部服务通过 HttpSend 表单转发时，header 不会带过来，从参数读取
            if (appVersion == null || appVersion.isEmpty()) {
                appVersion = request.getParameter("x-app-version");
            }
            if (platformHeader == null || platformHeader.isEmpty()) {
                platformHeader = request.getParameter("x-app-platform");
            }
            // 没有app版本信息的视为web端，不需要版本拦截
            if (appVersion != null && !appVersion.isEmpty()) {
                boolean isIos = "1".equals(platformHeader);
                String lowestVersion = getLowestVersion(request, isIos);
                if (lowestVersion != null && !lowestVersion.isEmpty()) {
                    if (isVersionLessThan(appVersion, lowestVersion)) {
                        ajaxReturn(response, 4099, getVersionOutdatedMessage(request));
                        return false;
                    }
                }
            }
        }

        HttpSession session = request.getSession();
        log.info(request.getRequestURL().toString());
        AuthMember user = (AuthMember) session.getAttribute(SysConstant.SESSION_MEMBER);
        if (user != null) {
            return true;
        } else {
        	ajaxReturn(response, 4000, "The current login status has expired, please login again!");
            return false;
            /*
            String token = request.getHeader("access-auth-token");
            log.info("token:{}",token);
            //解决service为null无法注入问题
            BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
            RedisManager redisManager = (RedisManager) factory.getBean("redisManager");
            Member member = redisManager.getTokenMember(token);
            //MemberService memberService = (MemberService) factory.getBean("memberService");
            //MemberEvent memberEvent = (MemberEvent) factory.getBean("memberEvent");
            //Member member = memberService.loginWithToken(token, request.getRemoteAddr(), "");
            if (member != null) {
                //Calendar calendar = Calendar.getInstance();
                //calendar.add(Calendar.HOUR_OF_DAY, 24 * 7);
                //member.setTokenExpireTime(calendar.getTime());
               // memberService.save(member);
                //memberEvent.onLoginSuccess(member, request.getRemoteAddr());
                session.setAttribute(SysConstant.SESSION_MEMBER, AuthMember.toAuthMember(member));
                return true;
            } else {
                ajaxReturn(response, 4000, "The current login status has expired, please login again!");
                return false;
            }*/
        }
    }

    /** 从 Spring 容器获取对应平台的最低版本号，5 分钟缓存一次 */
    private String getLowestVersion(HttpServletRequest request, boolean isIos) {
        long now = System.currentTimeMillis();
        long lastRefresh = isIos ? lastRefreshTimeIos : lastRefreshTimeAndroid;
        String cached = isIos ? cachedLowestVersionIos : cachedLowestVersionAndroid;
        if (cached == null || now - lastRefresh > CACHE_TTL_MS) {
            try {
                BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
                AppRevisionService appRevisionService = factory.getBean(AppRevisionService.class);
                Platform platform = isIos ? Platform.IOS : Platform.ANDROID;
                AppRevision revision = appRevisionService.findRecentVersion(platform);
                if (revision != null && revision.getLowestVersion() != null) {
                    cached = revision.getLowestVersion();
                    if (isIos) { cachedLowestVersionIos = cached; lastRefreshTimeIos = now; }
                    else       { cachedLowestVersionAndroid = cached; lastRefreshTimeAndroid = now; }
                }
            } catch (Exception e) {
                log.error("Failed to get app lowest version for platform={}", isIos ? "iOS" : "Android", e);
            }
        }
        return cached;
    }

    /** 版本比较：a < b 返回 true（与 Flutter AppVersion.isForceUpdate 逻辑一致） */
    private static boolean isVersionLessThan(String a, String b) {
        String[] partsA = a.split("\\.");
        String[] partsB = b.split("\\.");
        int maxLen = Math.max(partsA.length, partsB.length);
        for (int i = 0; i < maxLen; i++) {
            int va = i < partsA.length ? safeParseInt(partsA[i]) : 0;
            int vb = i < partsB.length ? safeParseInt(partsB[i]) : 0;
            if (va != vb) return va < vb;
        }
        return false;
    }

    private static int safeParseInt(String s) {
        try { return Integer.parseInt(s.trim()); } catch (NumberFormatException e) { return 0; }
    }

    private static String getVersionOutdatedMessage(HttpServletRequest request) {
        String lang = request.getHeader("lang");
        if ("en_US".equals(lang)) return "Please update to the latest version of the App";
        if ("zh_HK".equals(lang)) return "請更新至最新版本的App";
        if ("ja_JP".equals(lang)) return "最新バージョンのアプリに更新してください";
        if ("ko_KR".equals(lang)) return "최신 버전의 앱으로 업데이트해 주세요";
        return "请更新至最新版本的App";
    }


    public static void ajaxReturn(HttpServletResponse response, int code, String msg) throws IOException, JSONException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/json; charset=UTF-8");
        PrintWriter out = response.getWriter();
        JSONObject json = new JSONObject();
        json.put("code", code);
        json.put("message", msg);
        out.print(json.toString());
        out.flush();
        out.close();
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

    }
}
