package com.vetti.web.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.vetti.common.config.HotakeOAuth2Properties;
import com.vetti.common.core.domain.entity.SysUser;
import com.vetti.common.core.domain.model.LoginUser;
import com.vetti.common.enums.UserFlagEnum;
import com.vetti.common.exception.ServiceException;
import com.vetti.common.utils.DateUtils;
import com.vetti.common.utils.ip.AddressUtils;
import com.vetti.common.utils.ip.IpUtils;
import com.vetti.framework.web.service.SysPermissionService;
import com.vetti.framework.web.service.TokenService;
import com.vetti.hotake.domain.HotakeCvInfo;
import com.vetti.hotake.domain.HotakeSocialLoginLog;
import com.vetti.hotake.domain.HotakeSocialUser;
import com.vetti.hotake.domain.dto.HotakeSocialLoginRequestDto;
import com.vetti.hotake.domain.dto.HotakeSocialLoginResultDto;
import com.vetti.hotake.domain.dto.HotakeSocialUserInfoDto;
import com.vetti.hotake.mapper.HotakeCvInfoMapper;
import com.vetti.hotake.mapper.HotakeSocialLoginLogMapper;
import com.vetti.hotake.mapper.HotakeSocialUserMapper;
import com.vetti.hotake.service.IHotakeSocialUserService;
import com.vetti.system.service.ISysUserService;
import eu.bitwalker.useragentutils.UserAgent;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 社交用户服务实现
 *
 * @author vetti
 */
@Service
public class HotakeSocialUserServiceImpl implements IHotakeSocialUserService {

    private static final Logger log = LoggerFactory.getLogger(HotakeSocialUserServiceImpl.class);

    @Autowired
    private HotakeOAuth2Properties oAuth2Properties;

    @Autowired
    private HotakeSocialUserMapper socialUserMapper;

    @Autowired
    private HotakeSocialLoginLogMapper socialLoginLogMapper;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private HotakeCvInfoMapper cvInfoMapper;

    private final OkHttpClient httpClient = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .build();

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HotakeSocialLoginResultDto socialLogin(HotakeSocialLoginRequestDto requestDto) {
        String provider = requestDto.getProvider().toLowerCase();
        String code = requestDto.getCode();

        // 1. 获取第三方用户信息
        HotakeSocialUserInfoDto socialUserInfo = getSocialUserInfo(provider, code);
        if (socialUserInfo == null || StrUtil.isBlank(socialUserInfo.getProviderUserId())) {
            recordLoginLog(null, provider, null, "login", "1", "获取第三方用户信息失败");
            throw new ServiceException("获取第三方用户信息失败");
        }

        // 2. 查询是否已绑定
        HotakeSocialUser existSocialUser = socialUserMapper.selectByProviderAndProviderUserId(
                provider, socialUserInfo.getProviderUserId());

        SysUser sysUser;
        String loginType;
        boolean isNewUser = false;

        if (existSocialUser != null && existSocialUser.getUserId() != null) {
            // 已绑定，直接登录
            loginType = "login";
            sysUser = sysUserService.selectUserById(existSocialUser.getUserId());
            if (sysUser == null) {
                recordLoginLog(null, provider, socialUserInfo.getProviderUserId(), loginType, "1", "绑定的用户不存在");
                throw new ServiceException("绑定的用户不存在");
            }
            // 更新token信息
            updateSocialUserToken(existSocialUser, socialUserInfo);
        } else {
            // 未绑定，自动注册
            loginType = "register";
            isNewUser = true;
            sysUser = autoRegister(socialUserInfo, requestDto.getSysUserType());
            // 如果是已存在用户绑定，则不是新用户
            if (sysUser.getCreateTime() != null && 
                System.currentTimeMillis() - sysUser.getCreateTime().getTime() > 5000) {
                isNewUser = false;
            }
            // 创建社交绑定
            createSocialUserBinding(sysUser.getUserId(), socialUserInfo);
        }

        // 3. 生成登录Token
        HotakeSocialLoginResultDto resultDto = createLoginToken(sysUser, provider, isNewUser);

        // 4. 记录登录日志
        recordLoginLog(sysUser.getUserId(), provider, socialUserInfo.getProviderUserId(), loginType, "0", "登录成功");

        // 5. 更新登录信息
        recordLoginInfo(sysUser.getUserId());

        return resultDto;
    }

    @Override
    public String getAuthorizationUrl(String provider, String state) {
        HotakeOAuth2Properties.OAuthClientConfig config = oAuth2Properties.getByProvider(provider);
        if (config == null) {
            throw new ServiceException("不支持的登录平台: " + provider);
        }

        try {
            StringBuilder url = new StringBuilder(config.getAuthUri());
            url.append("?client_id=").append(URLEncoder.encode(config.getClientId(), StandardCharsets.UTF_8.name()));
            url.append("&redirect_uri=").append(URLEncoder.encode(config.getRedirectUri(), StandardCharsets.UTF_8.name()));
            url.append("&response_type=code");
            url.append("&scope=").append(URLEncoder.encode(config.getScope(), StandardCharsets.UTF_8.name()));
            if (StrUtil.isNotBlank(state)) {
                url.append("&state=").append(URLEncoder.encode(state, StandardCharsets.UTF_8.name()));
            }
            return url.toString();
        } catch (Exception e) {
            throw new ServiceException("生成授权URL失败");
        }
    }

    @Override
    public List<HotakeSocialUser> listByUserId(Long userId) {
        return socialUserMapper.selectByUserId(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unbind(Long userId, String provider) {
        HotakeSocialUser socialUser = socialUserMapper.selectByUserIdAndProvider(userId, provider);
        if (socialUser == null) {
            throw new ServiceException("未绑定该平台账号");
        }
        socialUserMapper.deleteById(socialUser.getId());
    }

    /**
     * 获取第三方用户信息
     */
    private HotakeSocialUserInfoDto getSocialUserInfo(String provider, String code) {
        HotakeOAuth2Properties.OAuthClientConfig config = oAuth2Properties.getByProvider(provider);
        if (config == null) {
            throw new ServiceException("不支持的登录平台: " + provider);
        }

        // 1. 用code换取access_token
        JSONObject tokenResponse = getAccessToken(config, code);
        if (tokenResponse == null) {
            return null;
        }

        String accessToken = tokenResponse.getString("access_token");
        String refreshToken = tokenResponse.getString("refresh_token");
        Long expiresIn = tokenResponse.getLong("expires_in");

        // 2. 用access_token获取用户信息
        JSONObject userInfo = getUserInfo(config, accessToken);
        if (userInfo == null) {
            return null;
        }

        // 3. 解析用户信息（不同平台字段不同）
        return parseSocialUserInfo(provider, userInfo, accessToken, refreshToken, expiresIn);
    }

    /**
     * 获取access_token
     */
    private JSONObject getAccessToken(HotakeOAuth2Properties.OAuthClientConfig config, String code) {
        try {
            FormBody.Builder formBuilder = new FormBody.Builder()
                    .add("client_id", config.getClientId())
                    .add("client_secret", config.getClientSecret())
                    .add("code", code)
                    .add("redirect_uri", config.getRedirectUri())
                    .add("grant_type", "authorization_code");

            Request request = new Request.Builder()
                    .url(config.getTokenUri())
                    .post(formBuilder.build())
                    .addHeader("Accept", "application/json")
                    .build();

            try (Response response = httpClient.newCall(request).execute()) {
                if (response.isSuccessful() && response.body() != null) {
                    String body = response.body().string();
                    log.debug("Token response: {}", body);
                    return JSON.parseObject(body);
                }
            }
        } catch (IOException e) {
            log.error("获取access_token失败", e);
        }
        return null;
    }

    /**
     * 获取用户信息
     */
    private JSONObject getUserInfo(HotakeOAuth2Properties.OAuthClientConfig config, String accessToken) {
        try {
            Request request = new Request.Builder()
                    .url(config.getUserInfoUri())
                    .get()
                    .addHeader("Authorization", "Bearer " + accessToken)
                    .addHeader("Accept", "application/json")
                    .build();

            try (Response response = httpClient.newCall(request).execute()) {
                if (response.isSuccessful() && response.body() != null) {
                    String body = response.body().string();
                    log.debug("UserInfo response: {}", body);
                    return JSON.parseObject(body);
                }
            }
        } catch (IOException e) {
            log.error("获取用户信息失败", e);
        }
        return null;
    }

    /**
     * 解析不同平台的用户信息为统一格式
     */
    private HotakeSocialUserInfoDto parseSocialUserInfo(String provider, JSONObject userInfo,
                                                   String accessToken, String refreshToken, Long expiresIn) {
        HotakeSocialUserInfoDto dto = new HotakeSocialUserInfoDto();
        dto.setProvider(provider);
        dto.setAccessToken(accessToken);
        dto.setRefreshToken(refreshToken);
        dto.setExpiresIn(expiresIn);
        dto.setRawUserInfo(userInfo.toJSONString());

        switch (provider.toLowerCase()) {
            case "google":
                dto.setProviderUserId(userInfo.getString("sub"));
                dto.setEmail(userInfo.getString("email"));
                dto.setName(userInfo.getString("name"));
                dto.setAvatar(userInfo.getString("picture"));
                break;
            case "microsoft":
                dto.setProviderUserId(userInfo.getString("id"));
                // Microsoft返回的邮箱字段是mail或userPrincipalName
                String email = userInfo.getString("mail");
                if (StrUtil.isBlank(email)) {
                    email = userInfo.getString("userPrincipalName");
                }
                dto.setEmail(email);
                dto.setName(userInfo.getString("displayName"));
                // Microsoft头像需要单独请求，这里暂不处理
                break;
            case "linkedin":
                dto.setProviderUserId(userInfo.getString("sub"));
                dto.setEmail(userInfo.getString("email"));
                dto.setName(userInfo.getString("name"));
                dto.setAvatar(userInfo.getString("picture"));
                break;
            default:
                throw new ServiceException("不支持的登录平台: " + provider);
        }

        return dto;
    }

    /**
     * 自动注册用户
     */
    private SysUser autoRegister(HotakeSocialUserInfoDto socialUserInfo, String sysUserType) {
        // 检查邮箱是否已存在
        if (StrUtil.isNotBlank(socialUserInfo.getEmail())) {
            SysUser existUser = sysUserService.selectUserByUserName(socialUserInfo.getEmail());
            if (existUser != null) {
                // 邮箱已存在，直接绑定
                return existUser;
            }
        }

        // 创建新用户
        SysUser sysUser = new SysUser();
        sysUser.setUserName(socialUserInfo.getEmail());
        sysUser.setEmail(socialUserInfo.getEmail());
        sysUser.setNickName(socialUserInfo.getName());
        sysUser.setAvatar(socialUserInfo.getAvatar());
        sysUser.setSysUserType(StrUtil.isNotBlank(sysUserType) ? sysUserType : "candidate");
        sysUser.setUserFlag(UserFlagEnum.FLAG_1.getCode());
        sysUser.setUserOperStatus("1");
        sysUser.setPwdUpdateDate(DateUtils.getNowDate());
        // 社交登录用户不设置密码，或设置随机密码
        sysUser.setPassword("");

        boolean success = sysUserService.registerUser(sysUser);
        if (!success) {
            throw new ServiceException("自动注册用户失败");
        }

        return sysUser;
    }

    /**
     * 创建社交账号绑定
     */
    private void createSocialUserBinding(Long userId, HotakeSocialUserInfoDto socialUserInfo) {
        HotakeSocialUser socialUser = new HotakeSocialUser();
        socialUser.setUserId(userId);
        socialUser.setProvider(socialUserInfo.getProvider());
        socialUser.setProviderUserId(socialUserInfo.getProviderUserId());
        socialUser.setEmail(socialUserInfo.getEmail());
        socialUser.setName(socialUserInfo.getName());
        socialUser.setAvatar(socialUserInfo.getAvatar());
        socialUser.setAccessToken(socialUserInfo.getAccessToken());
        socialUser.setRefreshToken(socialUserInfo.getRefreshToken());
        if (socialUserInfo.getExpiresIn() != null) {
            socialUser.setTokenExpireTime(new Date(System.currentTimeMillis() + socialUserInfo.getExpiresIn() * 1000));
        }
        socialUser.setRawUserInfo(socialUserInfo.getRawUserInfo());

        socialUserMapper.insert(socialUser);
    }

    /**
     * 更新社交账号token信息
     */
    private void updateSocialUserToken(HotakeSocialUser socialUser, HotakeSocialUserInfoDto socialUserInfo) {
        socialUser.setAccessToken(socialUserInfo.getAccessToken());
        socialUser.setRefreshToken(socialUserInfo.getRefreshToken());
        if (socialUserInfo.getExpiresIn() != null) {
            socialUser.setTokenExpireTime(new Date(System.currentTimeMillis() + socialUserInfo.getExpiresIn() * 1000));
        }
        socialUser.setRawUserInfo(socialUserInfo.getRawUserInfo());
        socialUserMapper.update(socialUser);
    }

    /**
     * 创建登录Token
     */
    private HotakeSocialLoginResultDto createLoginToken(SysUser sysUser, String provider, boolean isNewUser) {
        // 获取权限
        Set<String> permissions = permissionService.getMenuPermission(sysUser);

        // 创建LoginUser
        LoginUser loginUser = new LoginUser(sysUser.getUserId(), sysUser.getDeptId(), sysUser, permissions);

        // 生成token
        String token = tokenService.createToken(loginUser);

        // 构建返回对象
        HotakeSocialLoginResultDto resultDto = new HotakeSocialLoginResultDto();
        resultDto.setToken(token);
        resultDto.setUserId(sysUser.getUserId());
        resultDto.setSysUserType(sysUser.getSysUserType());
        resultDto.setIsNewUser(isNewUser);
        resultDto.setProvider(provider);
        resultDto.setUser(sysUser);

        // 如果是候选者，查询是否有简历
        if ("candidate".equals(sysUser.getSysUserType())) {
            HotakeCvInfo query = new HotakeCvInfo();
            query.setUserId(sysUser.getUserId());
            query.setCvFileType("cv");  // 只查询简历类型的文件
            List<HotakeCvInfo> cvList = cvInfoMapper.selectHotakeCvInfoList(query);
            
            // 设置简历状态标识
            resultDto.setHasCv(!CollectionUtil.isEmpty(cvList));
            resultDto.setCvCount(cvList != null ? cvList.size() : 0);
        }

        return resultDto;
    }

    /**
     * 记录登录信息
     */
    private void recordLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr());
        sysUser.setLoginDate(DateUtils.getNowDate());
        sysUserService.updateUserProfile(sysUser);
    }

    /**
     * 记录社交登录日志
     */
    private void recordLoginLog(Long userId, String provider, String providerUserId,
                                 String loginType, String status, String msg) {
        try {
            HotakeSocialLoginLog loginLog = new HotakeSocialLoginLog();
            loginLog.setUserId(userId);
            loginLog.setProvider(provider);
            loginLog.setProviderUserId(providerUserId);
            loginLog.setLoginType(loginType);
            loginLog.setLoginIp(IpUtils.getIpAddr());
            loginLog.setLoginLocation(AddressUtils.getRealAddressByIP(IpUtils.getIpAddr()));

            try {
                UserAgent userAgent = UserAgent.parseUserAgentString(
                        com.vetti.common.utils.ServletUtils.getRequest().getHeader("User-Agent"));
                loginLog.setBrowser(userAgent.getBrowser().getName());
                loginLog.setOs(userAgent.getOperatingSystem().getName());
            } catch (Exception ignored) {
            }

            loginLog.setStatus(status);
            loginLog.setMsg(msg);
            loginLog.setLoginTime(new Date());

            socialLoginLogMapper.insert(loginLog);
        } catch (Exception e) {
            log.error("记录社交登录日志失败", e);
        }
    }
}
