package com.ruoyi.web.controller.front;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.lang.Dict;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.content.VistorContextHolder;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginCard;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.*;
import com.ruoyi.common.utils.NumberUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.dz.domain.*;
import com.ruoyi.dz.mapper.DzClassesMapper;
import com.ruoyi.dz.mapper.DzSchoolMapper;
import com.ruoyi.dz.service.*;
import com.ruoyi.enums.CardDistributeStatus;
import com.ruoyi.enums.CardStatus;
import com.ruoyi.enums.UserTypeEnum;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.service.CommService;
import com.ruoyi.web.service.SysLoginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/front/user")
@Api(tags = "前台-用户")
public class UserController extends BaseController {
    private final IDzControlService dzControlService;
    private final SysLoginService loginService;
    private final ISysUserService userService;
    private final SysPermissionService permissionService;
    private final TokenService tokenService;
    private final CommService commService;
    private final ISysConfigService configService;
    private final IDzCardsService dzCardsService;
    private final IDzSchoolService dzSchoolService;
    private final IDzClassesService dzClassesService;
    private final DzSchoolMapper dzSchoolMapper;
    private final DzClassesMapper dzClassesMapper;
    private final IDzAgentService agentService;
    private final ISysDeptService deptService;
    private final IDzTeacherService dzTeacherService;
    private final IDzSubjectService dzSubjectService;
    private final WxMaService wxMaService;

    public UserController(IDzControlService dzControlService, SysLoginService loginService, ISysUserService userService, SysPermissionService permissionService, TokenService tokenService, CommService commService, ISysConfigService configService, IDzCardsService dzCardsService, IDzSchoolService dzSchoolService, IDzClassesService dzClassesService, DzSchoolMapper dzSchoolMapper, DzClassesMapper dzClassesMapper, IDzAgentService agentService, ISysDeptService deptService, IDzTeacherService dzTeacherService, IDzSubjectService dzSubjectService, WxMaService wxMaService) {
        this.dzControlService = dzControlService;
        this.loginService = loginService;
        this.userService = userService;
        this.permissionService = permissionService;
        this.tokenService = tokenService;
        this.commService = commService;
        this.configService = configService;
        this.dzCardsService = dzCardsService;
        this.dzSchoolService = dzSchoolService;
        this.dzClassesService = dzClassesService;
        this.dzSchoolMapper = dzSchoolMapper;
        this.dzClassesMapper = dzClassesMapper;
        this.agentService = agentService;
        this.deptService = deptService;
        this.dzTeacherService = dzTeacherService;
        this.dzSubjectService = dzSubjectService;
        this.wxMaService = wxMaService;
    }

    @GetMapping(value = "provinces")
    @Anonymous
    @ApiOperation("省份列表")
    public AjaxResult provinces()
    {
        DzControl cond = new DzControl();
        cond.setIsValid(1);
        return AjaxResult.success(dzControlService.selectDzControlList(cond).stream().map(t -> {
            JSONObject o = new JSONObject();
            o.put("dictValue", t.getLocation());
            o.put("dictLabel", t.getLocation());
            return o;
        }).collect(Collectors.toList()));
    }

    @GetMapping(value = "examTypes")
    @Anonymous
    @ApiOperation("考生类型列表")
    public AjaxResult examTypes(@RequestParam String location)
    {
        DzControl cond = new DzControl();
        cond.setIsValid(1);
        cond.setLocation(location);
        List<DzControl> list = dzControlService.selectDzControlList(cond);
        String examTypes;
        if(CollectionUtils.isEmpty(list) || StringUtils.isBlank(examTypes = list.get(0).getExamTypes())) {
            return AjaxResult.success(Collections.emptyList());
        }
        return AjaxResult.success(Arrays.stream(examTypes.split(",")).map(t -> {
            JSONObject o = new JSONObject();
            o.put("dictValue", t);
            o.put("dictLabel", ExamType.valueOf(t).title());
            return o;
        }).collect(Collectors.toList()));
    }

    @GetMapping(value = "examMajors")
    @Anonymous
    @ApiOperation("专业类别列表")
    public AjaxResult examMajor(@RequestParam String location, @RequestParam ExamType examType)
    {
        if (StringUtils.isBlank(location) || null ==examType) {
            examType = VistorContextHolder.getExamType();
            location = VistorContextHolder.getLocation();
        }
        // 构建查询条件
        DzSubject cond = new DzSubject();
        cond.setLocations(location);
        cond.setExamTypes(examType.name());

        // 查询科目列表
        List<DzSubject> subjectList = dzSubjectService.selectDzSubjectList(cond);

        // 转换为返回格式
        List<JSONObject> list = subjectList.stream().map(subject -> {
            JSONObject o = new JSONObject();
            o.put("dictValue", subject.getSubjectId());
            o.put("dictLabel", subject.getSubjectName());
            return o;
        }).collect(Collectors.toList());

        return AjaxResult.success(list);
    }

    @GetMapping(value = "graduateYears")
    @Anonymous
    @ApiOperation("毕业年份列表")
    public AjaxResult graduateYear(@RequestParam String location, @RequestParam ExamType examType)
    {
//        DzControl cond = new DzControl();
//        cond.setIsValid(1);
//        cond.setLocation(location);
//        List<DzControl> list = dzControlService.selectDzControlList(cond);
//        Integer year;
//        if(CollectionUtils.isEmpty(list) || null == (year = list.get(0).getSubmitYear())) {
//            year = Calendar.getInstance().get(Calendar.YEAR);
//        }
//        List<JSONObject> resultList = new ArrayList<>();
//        for(int i = year; i <= year + 6; i++) {
//            JSONObject o = new JSONObject();
//            o.put("dictValue", i);
//            o.put("dictLabel", String.valueOf(i));
//            resultList.add(o);
//        }ss
        int begin = 2026;
        int end = ExamType.VHS.equals(examType) ? 2028 : 2026;
        List<JSONObject> resultList = new ArrayList<>();
        for(int i = begin; i<= end; i++) {
            JSONObject o = new JSONObject();
            o.put("dictValue", i);
            o.put("dictLabel", String.valueOf(i));
            resultList.add(o);
        }

        return AjaxResult.success(resultList);
    }

    @GetMapping("/getSchoolList")
    @Anonymous
    @ApiOperation("查询学校列表")
    public TableDataInfo getSchoolList(@ApiParam("examType") @RequestParam(required = false) String examType, @ApiParam("keyword") @RequestParam(required = false) String keyword)
    {
        DzSchool dzSchool = new DzSchool();
        dzSchool.setCampus(false);
        dzSchool.setName(keyword);
        dzSchool.setExamTypes(StringUtils.isNotBlank(examType) ? examType : VistorContextHolder.getExamType().name());
        startPage();
        List<DzSchool> list = dzSchoolService.selectDzSchoolList(dzSchool);
        return getDataTable(list);
    }

    @GetMapping("/getClassList")
    @Anonymous
    @ApiOperation("查询学校班级列表")
    public AjaxResult getClassList(@ApiParam("schoolId") Long schoolId)
    {
        DzClasses cCond = new DzClasses();
        cCond.setSchoolId(schoolId);
        List<DzClasses> list = dzClassesService.selectDzClassesList(cCond);
        return AjaxResult.success(list);
    }



    /**
     * 登录方法
     *
     * @param loginBody 登录信息i
     * @return 结果
     */
    @PostMapping("userLogin")
    @ApiOperation("前台登陆")
    @Anonymous
    public AjaxResult userLogin(@RequestBody LoginBody loginBody)
    {
        // 生成令牌
        AjaxResult ajax = loginService.login(loginBody.getMobile(), loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid(),AccessFromType.frontApp.name());
        return ajax;
    }


    /**
     * 微信登录方法
     *
     * @param body 登录信息
     * @return 结果
     */
    @PostMapping("loginByCode")
    @ApiOperation("微信登陆")
    @Anonymous
    public AjaxResult loginByCode(@RequestBody JSONObject body)
    {
        String loginCode = body.getString("loginCode");
        String phoneCode = body.getString("phoneCode");
        try {
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(loginCode);
            WxMaPhoneNumberInfo phoneNumberInfo = wxMaService.getUserService().getPhoneNumber(phoneCode);
            String openId = sessionInfo.getOpenid();
            String phoneNumber = phoneNumberInfo.getPhoneNumber();
            return loginService.loginByCode(openId, phoneNumber);
        } catch (WxErrorException e) {
            return AjaxResult.error("登陆失败: " + e.getMessage());
        }
    }

    @PostMapping("bindOpenId")
    @ApiOperation("绑定微信")
    public AjaxResult bindOpenId(@RequestBody JSONObject body)
    {
        String loginCode = body.getString("loginCode");
        try {
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(loginCode);
            String openid = sessionInfo.getOpenid();
            return loginService.bindOpenId(openid);
        } catch (WxErrorException e) {
            return AjaxResult.error("绑定失败: " + e.getMessage());
        }
    }


    @GetMapping("getUserBindCard")
    @ApiOperation("取用户卡绑定状态")
    public AjaxResult getUserBindCard() {
        SysUser sysUser = userService.selectUserById(SecurityUtils.getUserId());
        if(null != sysUser.getBindStatus() && BindStatus.Pend.code().equals(sysUser.getBindStatus())) {
            DzCards dzCards = dzCardsService.selectDzCardsByCardId(sysUser.getCardId());
            return AjaxResult.success(Dict.of("cardNo", dzCards.getCardNo(), "password", dzCards.getPassword()));
        }
        return AjaxResult.success();
    }


    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    @ApiOperation("前台个人信息")
    public AjaxResult getInfo(HttpServletRequest request)
    {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        if (!loginUser.getPermissions().equals(permissions))
        {
            loginUser.setPermissions(permissions);
            tokenService.refreshToken(loginUser);
        }
        DzTeacher dzTeacher;
        if(UserTypeEnum.isTeacher(user.getUserType()) && null != (dzTeacher = dzTeacherService.selectDzTeacherByTeacherId(user.getUserTypeId()))) {
            user.setSchoolId(dzTeacher.getSchoolId());
            user.setSchoolName(dzTeacher.getSchoolName());
            if(null != dzTeacher.getCampusId()) {
                user.setCampusName(dzSchoolMapper.selectDzSchoolById(dzTeacher.getCampusId()).getName());
            }
            List<String> campusClassList = Lists.newArrayList();
            List<String> schoolClassList = Lists.newArrayList();
            for(DzClasses dzClass : dzClassesMapper.selectClassesForTeacher(dzTeacher.getTeacherId())) {
                if(null == dzClass.getDeptId()) {
                    schoolClassList.add(dzClass.getName());
                } else {
                    campusClassList.add(dzClass.getName());
                }
            }
            user.setSchoolClassName(StringUtils.join(schoolClassList, ","));
            user.setCampusClassName(StringUtils.join(campusClassList, ","));
        }
        DzCards cards=null;
        if(null != user.getCardId()) {
            cards = dzCardsService.selectDzCardsByCardId(user.getCardId());
            if (null!=cards.getSchoolId()){
                DzSchool school = dzSchoolService.selectDzSchoolById(cards.getSchoolId());
                if(null != school){
                    user.setClassSelect(school.getClassSelect());
                }
            }
        }
        AjaxResult ajax = AjaxResult.success(user);
        ajax.put("card", loginUser.getCard());
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        ajax.put("isDefaultModifyPwd", commService.initPasswordIsModify(user.getPwdUpdateDate()));
        ajax.put("isPasswordExpired", commService.passwordIsExpiration(user.getPwdUpdateDate()));

        // 添加组织信息.卡号/邀请码开始找：再逐步找到 代理商-机构
        Long agentId = null;
        if(null != cards) {
            agentId = cards.getAgentId();
        }else{
            if (null != user.getInviteCode()) {
                String inviteCode = user.getInviteCode();
                // 如果邀请码全部是数字，则转换为Long
                if (NumberUtils.isNumeric(inviteCode)) {
                    try {
                        agentId = Long.parseLong(inviteCode);
                    } catch (NumberFormatException e) {
                        // 如果转换失败，保持为null
                        agentId = null;
                    }
                }
            }
        }

        // 通过代理商查询机构信息
        Long deptId = null;
        if (null != agentId&&0!=agentId) {
            DzAgent agent = agentService.selectDzAgentByAgentId(agentId);
            if(null != agent && null != agent.getDeptId()) {
                deptId = agent.getDeptId();
            }
        }else{
            if (null!=user.getDeptId()){
                deptId = user.getDeptId();
            }
        }

        if(null==deptId){
            if (UserTypeEnum.isTeacher(user.getUserType())){
                DzTeacher teacher = dzTeacherService.selectDzTeacherByUserId(user.getUserId());
                if(null != teacher && null != teacher.getDeptId()){
                    deptId = teacher.getDeptId();
                }
            }else if (UserTypeEnum.isAgent(user.getUserType())){
                DzAgent agent = agentService.selectDzAgentByUserId(user.getUserId());
                if(null != agent && null != agent.getDeptId()){
                    deptId = agent.getDeptId();
                }
            }
        }

        if (null==deptId){
            //默认使用单招一卡通
            deptId = 101L;
        }

        // 构建组织信息对象
        // 查询机构信息
        SysDept dept = deptService.selectDeptById(deptId);
        JSONObject org = new JSONObject();
        if(null != dept) {
            // 优先使用机构中的信息
            if(StringUtils.isNotBlank(dept.getLogo())) {
                org.put("logo", dept.getLogo());
            }
            if(StringUtils.isNotBlank(dept.getDeptName())) {
                org.put("orgName", dept.getDeptName());
            }
            if(StringUtils.isNotBlank(dept.getContactPhone())) {
                org.put("contactPhone", dept.getContactPhone());
            }
        }
        ajax.put("org", org);

        //获取app的配置文件
        String type = request.getHeader("type");
        //H5 wechat frontApp均需要菜单
        if(AccessFromType.isFrontApp(type)||AccessFromType.isH5(type)||AccessFromType.isWechat(type)){
            String appConfig = configService.selectConfigByKey("app.common.config");
            com.alibaba.fastjson.JSONObject json = com.alibaba.fastjson.JSONObject.parseObject(appConfig);
            ajax.put("appConfig", json);
        }

//        if (null!=user.getCardId()){
//            user.setAccountType(AccountType.common.getValue());
//        }else {
//            user.setAccountType(AccountType.audit.getValue());
//        }
//
//        //处理accountType。1正常，2审核账号 user.data.accountType=2
//        String auditAccount = configService.selectConfigByKey("audit.account");
//        if (StringUtils.isNotBlank(auditAccount)){
//            if (auditAccount.contains(user.getPhonenumber())||auditAccount.contains(user.getUserName())){
//                user.setAccountType(AccountType.audit.getValue());
//            }
//        }

        return ajax;
    }

    /**
     * 修改用户
     */
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("userInfo")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("更新个人信息")
    public AjaxResult updateProfile(@RequestBody SysUser user)
    {
        LoginUser loginUser = getLoginUser();
        SysUser currentUser = loginUser.getUser();
        boolean updateUserName = null != user.getPhonenumber() && !user.getPhonenumber().equals(currentUser.getPhonenumber()) && currentUser.getUserName().equals(currentUser.getPhonenumber());
        currentUser.setNickName(user.getNickName());
        currentUser.setEmail(user.getEmail());
        currentUser.setPhonenumber(user.getPhonenumber());
        currentUser.setSex(user.getSex());
        currentUser.setScores(user.getScores());
        if (com.ruoyi.common.utils.StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
        {
            return error("修改用户'" + loginUser.getUsername() + "'失败，手机号码已存在");
        }
        if (com.ruoyi.common.utils.StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
        {
            return error("修改用户'" + loginUser.getUsername() + "'失败，邮箱账号已存在");
        }
        if(NumberUtils.isPositive(user.getCardId())) {
            DzCards dzCards = new DzCards();
            dzCards.setCardId(user.getCardId());
            dzCards.setSchoolId(user.getSchoolId());
            dzCards.setClassId(user.getClassId());
            dzCardsService.updateDzCards(dzCards);
            LoginCard loginCard = loginUser.getCard();
            if(null != user.getSchoolId() && !user.getSchoolId().equals(loginCard.getSchoolId())) {
                loginCard.setSchoolId(user.getSchoolId());
                loginCard.setSchoolName(dzSchoolMapper.selectDzSchoolById(user.getSchoolId()).getName());
            }
            if(null != user.getClassId() && !user.getClassId().equals(loginCard.getClassId())) {
                loginCard.setClassId(user.getClassId());
                loginCard.setClassName(dzClassesMapper.selectDzClassesByClassId(user.getClassId()).getName());
            }
        }
        if(!UserTypeEnum.isCard(user.getUserType())) {
            currentUser.setLocation(user.getLocation());
            currentUser.setExamType(user.getExamType());
            currentUser.setExamMajor(user.getExamMajor());
            currentUser.setEndYear(user.getEndYear());
        }
        if (updateUserName) {
            currentUser.setUserName(user.getPhonenumber());
        }
        if (userService.updateUserProfile(currentUser) > 0)
        {
            // 更新缓存用户信息
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改个人信息异常，请联系管理员");
    }

    @PostMapping("verifyCard")
    @ApiOperation("校验卡")
    @Anonymous
    public AjaxResult verifyCard(@ApiParam("卡号") @RequestParam String cardNo, @ApiParam("密码") @RequestParam String password)
    {
        DzCards cards = dzCardsService.selectDzCardsByCardNo(cardNo);
        if(null == cards || !cards.getPassword().equals(password)) {
            return AjaxResult.error("卡号或密码不正确");
        }
//        if(CardStatus.Free.getVal().equals(cards.getStatus())||CardStatus.Open.getVal().equals(cards.getStatus())) {
//            return AjaxResult.error("卡未分配");
//        }else if(CardStatus.Active.getVal().equals(cards.getStatus())) {
//            return AjaxResult.error("卡已使用");
//        }

        if(!CardDistributeStatus.Assign.getVal().equals(cards.getDistributeStatus()) || !CardStatus.Free.getVal().equals(cards.getStatus())) {
            return AjaxResult.error("无效卡");
        }
        if(null != cards.getAssignSchoolId()) {
            cards.setAssignSchoolName(dzSchoolService.selectDzSchoolById(cards.getAssignSchoolId()).getName());
        }
        return AjaxResult.success(cards);
    }
}
