package com.zhongshu.card.server.core.service.school;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.github.microservice.auth.security.type.AuthType;
import com.github.microservice.core.util.bean.BeanUtil;
import com.zhongshu.card.client.model.org.*;
import com.zhongshu.card.client.model.school.*;
import com.github.microservice.net.ResultContent;
import com.github.microservice.net.ResultMessage;
import com.zhongshu.card.client.service.school.SchoolUserService;
import com.zhongshu.card.client.type.UserType;
import com.zhongshu.card.server.core.dao.school.CardInfoDao;
import com.zhongshu.card.server.core.dao.org.OrganizationDao;
import com.zhongshu.card.server.core.dao.org.OrganizationUserDao;
import com.zhongshu.card.server.core.dao.org.UserCountDao;
import com.zhongshu.card.server.core.domain.org.Organization;
import com.zhongshu.card.server.core.domain.org.OrganizationUser;
import com.zhongshu.card.server.core.domain.org.UserAccount;
import com.zhongshu.card.server.core.domain.school.CardInfo;
import com.zhongshu.card.server.core.service.base.SuperService;
import com.zhongshu.card.server.core.service.org.OrganizationUserServiceImpl;
import com.zhongshu.card.server.core.service.projectAbout.CardInfoServiceImpl;
import com.zhongshu.card.server.core.service.user.UserAccountServiceImpl;
import com.zhongshu.card.server.core.util.BeanUtils;
import com.zhongshu.card.server.core.util.CommonUtil;
import com.zhongshu.card.server.core.util.ExcelUtils;
import com.zhongshu.card.server.core.util.ValidateUtils;
import com.zhongshu.card.server.core.util.excel.CommonExeclParam;
import com.zhongshu.card.server.core.util.excel.CommonExeclTd;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author TRX
 * @date 2024/6/12
 */
@Slf4j
@Service
public class SchoolUserServiceImpl extends SuperService implements SchoolUserService {

    @Autowired
    UserAccountServiceImpl userAccountService;

    @Autowired
    OrganizationUserDao organizationUserDao;

    @Autowired
    OrganizationDao organizationDao;

    @Autowired
    CardInfoServiceImpl cardInfoService;

    @Autowired
    CardInfoDao cardInfoDao;

    @Autowired
    UserCountDao userCountDao;

    @Autowired
    OrganizationUserServiceImpl organizationUserService;

    /**
     * 导入 学校用户excel
     *
     * @param request
     * @param response
     * @param file
     * @return
     */
    @Override
    public ResultContent<ImportResultModel> importSchoolUsers(HttpServletRequest request,
            HttpServletResponse response, MultipartFile file) {
        String oid = getCurrentOid();
        Assert.hasText(oid, "oid不能为空");

        ImportResultModel model = new ImportResultModel();
        try {
            int startRow = 2;
            ImportParams params = new ImportParams();
            List<ExcelUserParam> list = ExcelImportUtil.importExcel(file.getInputStream(),
                    ExcelUserParam.class, params);
            model.setTotal(list.size());

            List<String> failDetails = new ArrayList<>();
            List<UserCountAddParam> userList = new ArrayList<>();
            if (ObjectUtils.isNotEmpty(list)) {
                for (ExcelUserParam param1 : list) {
                    // 验证数据合法性
                    boolean b = true;
                    if (b && StringUtils.isEmpty(param1.getName())) {
                        b = false;
                        failDetails.add(String.format("第%d行名称不能为空", startRow));
                    }
                    if (b && StringUtils.isEmpty(param1.getCode())) {
                        b = false;
                        failDetails.add(String.format("第%d行编码不能为空", startRow));
                    }
                    if (b && StringUtils.isEmpty(param1.getPhone())) {
                        b = false;
                        failDetails.add(String.format("第%d行电话不能为空", startRow));
                    }
                    if (b) {
                        if (StringUtils.isEmpty(param1.getCardNumber())) {
                            b = false;
                            failDetails.add(String.format("第%d行身份证号不能为空", startRow));
                        } else if (param1.getCardNumber().length() != 18) {
                            b = false;
                            failDetails.add(String.format("第%d行身份证号格式不正确", startRow));
                        }
                    }
                    if (b) {
                        // 验证通过
                        UserCountAddParam addParam = new UserCountAddParam();
                        initDefaultUserAndOid(addParam);
                        BeanUtils.copyProperties(param1, addParam);
                        if (StringUtils.isNotBlank(param1.getSexStr())) {
                            addParam.setSex(CommonUtil.getSexByStr(param1.getSexStr()));
                        }
                        String passWord = param1.getCardNumber().substring(12, 18);
                        passWord = passWord.toLowerCase().replace("x", "0");
                        addParam.setPassWord(passWord);
                        userList.add(addParam);
                    }
                    startRow++;
                }

                // 添加到
                for (UserCountAddParam param : userList) {
                    ResultContent resultContent = organizationUserService.saveOrgUser(param);
                    log.info("添加日志： {}", resultContent.getMsg());
                }
                model.setSuccess(userList.size());
                model.setFailDetails(failDetails);
            }
        } catch (Exception e) {
            return ResultContent.buildFail(String.format("导入出错：%s", e.getMessage()));
        }
        return ResultContent.buildSuccess(model);
    }


    /**
     * 导出学校用户
     *
     * @param request
     * @param response
     * @param param
     */
    public void exportSchoolUser(HttpServletRequest request, HttpServletResponse response,
            OrganizationUserSearch param) {
        initOidSearchParam(param);
        Organization organization = organizationDao.findTopByOid(param.getOid());
        Pageable pageable = PageRequest.of(0, Integer.MAX_VALUE);
        Page<OrganizationUser> page = organizationUserDao.page(pageable, param);

        List<Map<String, Object>> maps = new ArrayList<>();
        if (page.getContent() != null) {
            List<OrganizationUser> list = page.getContent();
            maps = list.stream().map(it -> {
                Map<String, Object> map = BeanUtil.bean2Map(it);
                String sex = "";
                if (it.getUser() != null && it.getUser().getSex() != null) {
                    sex = it.getUser().getSex().getRemark();
                }
                map.put("sexStr", sex);
                return map;
            }).collect(Collectors.toList());
        }
        CommonExeclParam execlParam = new CommonExeclParam();
        execlParam.setTitle(String.format("%s用户列表", organization.getName()));
        execlParam.setStartRow(2);
        execlParam.setDatas(maps);

        List<CommonExeclTd> tds = new ArrayList<>();
        tds.add(CommonExeclTd.build("人员编号", "code"));
        tds.add(CommonExeclTd.build("姓名", "name"));
        tds.add(CommonExeclTd.build("性别", "sexStr"));
        tds.add(CommonExeclTd.build("手机号", "phone"));
        tds.add(CommonExeclTd.build("身份证号", "cardNumber"));
        tds.add(CommonExeclTd.build("备注", "remark"));

        execlParam.setTds(tds);
        ExcelUtils.commonExecuteExcel(request, response, execlParam);
    }

    /**
     * 编辑或新增加学校用户信息
     *
     * @param param
     * @return
     */
    @Override
    public ResultContent addOrUpdateSchoolUser(SchoolUserCountParam param) {
        List<CardInfoParam> cardInfos = param.getCardInfos();
        HashMap<String, String> map = new HashMap<>();
        for (CardInfoParam cardInfo : cardInfos) {
            if (cardInfo.getCardType() == null) {
                return ResultContent.buildFail("卡片类型不能为空");
            }
            if (StringUtils.isEmpty(cardInfo.getCode())) {
                return ResultContent.buildFail("code不能为空");
            }
            if (map.containsKey(cardInfo.getCode())) {
                return ResultContent.buildFail(String.format("code已存在：%s", cardInfo.getCode()));
            }
            map.put(cardInfo.getCode(), cardInfo.getCode());
        }

        String cardNumber = param.getCardNumber();
        if (!ValidateUtils.isIDCard(cardNumber)) {
            return ResultContent.buildFail(String.format("证件号码格式错误"));
        }
        String passWord = param.getCardNumber().substring(12, 18);
        passWord = passWord.toLowerCase().replace("x", "0");
        param.setPassWord(passWord);

        ResultContent resultContent = organizationUserService.saveOrgUser(param);
        if (resultContent.isFailed()) {
            return resultContent;
        }

        OrganizationUser organizationUser = (OrganizationUser) resultContent.getContent();
        // 维护卡片信息
        String userId = organizationUser.getUserId();
        String oid = organizationUser.getOid();
        // 删除所有卡片
        cardInfoDao.deleteByUserIdAndOid(userId, oid);
        for (CardInfoParam cardInfo : cardInfos) {
            cardInfo.setUserId(userId);
            cardInfo.setOid(oid);
            cardInfoService.addCardInfo(cardInfo);
        }
        return ResultContent.buildSuccess();
    }

    /**
     * 查询校园端用户详情
     *
     * @param param
     * @return
     */
    public ResultContent<SchoolUserModel> getSchoolUserDetail(OrgUserDetailParam param) {
        SchoolUserModel model = new SchoolUserModel();
        if (StringUtils.isEmpty(param.getOid())) {
            param.setOid(getCurrentOid());
        }
        Assert.hasText(param.getUserId(), "userId不能为空");
        Assert.hasText(param.getOid(), "oid不能为空");

        ResultContent<OrganizationUserModel> resultContent = userAccountService.getOrgUserDetail(param);
        if (resultContent.isFailed()) {
            return ResultContent.buildFail(resultContent.getMsg());
        }
        OrganizationUserModel userModel = resultContent.getContent();
        BeanUtils.copyProperties(userModel, model);

        // 查询卡片信息
        List<CardInfoModel> cardInfos = cardInfoService.getUserOrgAllCard(param.getUserId(), param.getOid());
        model.setCardInfos(cardInfos);
        return ResultContent.buildSuccess(model);
    }

    //-------------------------------卡片信息维护 start-------------------

    /**
     * 查询用户的所有卡片
     *
     * @param param
     * @return
     */
    @Override
    public ResultContent<List<CardInfoModel>> getUserOrgAllCard(OrgUserDetailParam param) {
        if (StringUtils.isEmpty(param.getOid())) {
            param.setOid(getCurrentOid());
        }
        Assert.hasText(param.getUserId(), "userId不能为空");
        Assert.hasText(param.getOid(), "oid不能为空");
        List<CardInfoModel> cardInfos = cardInfoService.getUserOrgAllCard(param.getUserId(), param.getOid());
        return ResultContent.buildSuccess(cardInfos);
    }

    /**
     * 得到当前用户  在机构的所有卡片
     *
     * @return
     */
    @Override
    public ResultContent<List<CardInfoModel>> getCurrentUserOrgAll(String oid) {
        String userId = getCurrentUserId();
        Assert.hasText(userId, "userId不能为空");
        Assert.hasText(oid, "oid不能为空");
        List<CardInfoModel> cardInfos = cardInfoService.getUserOrgAllCard(userId, oid);
        return ResultContent.buildSuccess(cardInfos);
    }

    /**
     * 得到当前用户所有的卡片 （不区分学校）
     *
     * @return
     */
    @Override
    public ResultContent<List<CardInfoModel>> getCurrentUserAllCard() {
        return cardInfoService.getUserProjectAllCard(getCurrentUserId(), getCurrentProjectOid());
    }

    //-------------------------------卡片信息维护 end---------------------

    /**
     * 删除校园端用户
     *
     * @param id
     * @return
     */
    @Override
    public ResultContent deleteUser(String id) {
        Assert.hasText(id, "id不能为空");
        OrganizationUser organizationUser = organizationUserDao.findTopById(id);
        if (ObjectUtils.isEmpty(organizationUser)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        organizationUserDao.delete(organizationUser);
        return ResultContent.buildSuccess();
    }

    //-----------------------小程序c端用户管理 start--------------------

    /**
     * 注册用户
     *
     * @param param
     * @return
     */
    @Override
    public ResultContent register(RegisterUserParam param) {
        Assert.hasText(param.getName(), "姓名不能为空");
        Assert.hasText(param.getPhone(), "phone不能为空");
        Assert.hasText(param.getCardNumber(), "证件号码不能为空");
        String phone = param.getPhone();
        if (!ValidateUtils.isPhoneNumber(phone)) {
            return ResultContent.buildFail("电话号码格式不正确");
        }

        // 保存卡片信息
        List<CardInfoParam> cardInfos = param.getCardInfos();
        if (ObjectUtils.isNotEmpty(cardInfos)) {
            HashMap<String, String> map = new HashMap<>();
            for (CardInfoParam cardInfo : cardInfos) {
                if (cardInfo.getCardType() == null) {
                    return ResultContent.buildFail("卡片类型不能为空");
                }
                if (StringUtils.isEmpty(cardInfo.getCode())) {
                    return ResultContent.buildFail("code不能为空");
                }
                if (map.containsKey(cardInfo.getCode())) {
                    return ResultContent.buildFail(String.format("code已存在：%s", cardInfo.getCode()));
                }
                map.put(cardInfo.getCode(), cardInfo.getCode());

                CardInfo cardInfo1 = cardInfoDao.findByCode(cardInfo.getCode());
                if (ObjectUtils.isNotEmpty(cardInfo1)) {
                    return ResultContent.buildFail(String.format("卡号code已存在：%s", cardInfo.getCode()));
                }
            }
        }

        String cardNumber = param.getCardNumber();
        if (!ValidateUtils.isIDCard(cardNumber)) {
            return ResultContent.buildFail("身份证号码格式不正确");
        }
        String loginName = param.getPhone();
        UserAccount temp = userCountDao.findTopByLoginName(loginName);
        if (ObjectUtils.isNotEmpty(temp)) {
            if (StringUtils.isNotEmpty(temp.getCardNumber()) && !temp.getCardNumber().equals(param.getCardNumber())) {
                return ResultContent.buildFail(String.format("用户已存在，证件号码不匹配"));
            }
        }
        // 注册用户
        RegisterUserAccountParam addParam = new RegisterUserAccountParam();
        BeanUtils.copyProperties(param, addParam);
        addParam.setUserType(UserType.ConsumerUser);
        ResultContent<String> resultContent = userAccountService.registerUserAccount(addParam);
        if (resultContent.isFailed()) {
            return ResultContent.buildFail(resultContent.getMsg());
        }

        // 添加卡片
        String userId = resultContent.getContent();
        UserAccount userAccount = userCountDao.findTopByUserId(userId);
        if (ObjectUtils.isNotEmpty(cardInfos)) {
            for (CardInfoParam cardInfo : cardInfos) {
                cardInfo.setUserId(userId);
                cardInfo.setOid("");
                cardInfoService.addCardInfo(cardInfo);
            }
        }

        // 返回用户所在学校的信息
        RegisterResultModel registerResult = new RegisterResultModel();
        UserCountModel userCountModel = userAccountService.toModel(userAccount);
        registerResult.setUserInfo(userCountModel);

        // 返回用户所有的学校信息
        List<OrganizationUserSimpleModel> schools = organizationUserService.getUserOrgans(userAccount, AuthType.School);
        registerResult.setSchools(schools);
        if (ObjectUtils.isNotEmpty(schools)) {
            registerResult.setCode(schools.get(0).getCode());
        }
        return ResultContent.buildSuccess(registerResult);
    }


}
