package com.yonge.cooleshow.admin.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.biz.dal.dto.VipSubmitReq;
import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
import com.yonge.cooleshow.biz.dal.dto.search.VipRecordSearch;
import com.yonge.cooleshow.biz.dal.entity.Student;
import com.yonge.cooleshow.biz.dal.entity.TenantActivationCode;
import com.yonge.cooleshow.biz.dal.entity.TenantAlbumPurchase;
import com.yonge.cooleshow.biz.dal.entity.TenantGroup;
import com.yonge.cooleshow.biz.dal.entity.TenantGroupAlbum;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.service.MemberPriceSettingsService;
import com.yonge.cooleshow.biz.dal.service.StudentService;
import com.yonge.cooleshow.biz.dal.service.TenantActivationCodeService;
import com.yonge.cooleshow.biz.dal.service.TenantAlbumPurchaseService;
import com.yonge.cooleshow.biz.dal.service.TenantGroupAlbumService;
import com.yonge.cooleshow.biz.dal.service.TenantGroupService;
import com.yonge.cooleshow.biz.dal.service.VipCardRecordService;
import com.yonge.cooleshow.biz.dal.vo.StudentVo;
import com.yonge.cooleshow.biz.dal.vo.VipRecordVo;
import com.yonge.cooleshow.biz.dal.wrapper.StudentWrapper;
import com.yonge.cooleshow.common.controller.BaseController;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.enums.UserLockFlag;
import com.yonge.cooleshow.common.enums.UserStatusEnum;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.page.PageInfo;
import com.yonge.toolset.mybatis.support.PageUtil;
import com.yonge.toolset.utils.date.DateUtil;
import com.yonge.toolset.utils.excel.POIUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("${app-config.url.admin:}/student")
@Api(value = "学生表", tags = "学生表")
public class StudentController extends BaseController {
    @Autowired
    private StudentService studentService;

    @Resource
    private SysUserFeignService sysUserFeignService;

    @Autowired
    private MemberPriceSettingsService memberPriceSettingsService;

    @Autowired
    private VipCardRecordService vipCardRecordService;

    @Autowired
    private TenantGroupService tenantGroupService;

    @Autowired
    private TenantActivationCodeService tenantActivationCodeService;
    @Autowired
    private TenantAlbumPurchaseService tenantAlbumPurchaseService;
    @Autowired
    private TenantGroupAlbumService tenantGroupAlbumService;

    @GetMapping("/detail/{id}")
    @ApiOperation(value = "详情", notes = "传入id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", paramType = "path", dataType = "long", required = true),
    })
    @PreAuthorize("@pcs.hasPermissions('student/detail')")
    public HttpResponseResult<StudentVo> detail(@PathVariable("id") Long id) {
        StudentVo detail = studentService.detail(id);
        if (detail != null && detail.getTenantGroupId() != null) {
            TenantGroup group = tenantGroupService.getById(detail.getTenantGroupId());
            detail.setTenantGroupName(group == null ? "" : group.getName());
        }
        return succeed(detail);
    }

    @PostMapping("/page")
    @ApiOperation(value = "查询分页", notes = "传入StudentSearch")
    @PreAuthorize("@pcs.hasPermissions('student/page')")
    public HttpResponseResult<PageInfo<StudentVo>> page(@RequestBody StudentSearch query) {

        if (StringUtils.isNotBlank(query.getUserStatus())) {
            switch (query.getUserStatus()) {
                case "LOCKED":
                    query.setDelFlag(YesOrNoEnum.NO);
                    query.setLockFlag(UserLockFlag.LOCKED);
                    break;
                case "CLOSED":
                    query.setDelFlag(YesOrNoEnum.YES);
                    break;

                default:
                    query.setDelFlag(YesOrNoEnum.NO);
                    query.setLockFlag(UserLockFlag.NORMAL);
                    break;
            }
        }
        Long tenantAlbumPurchaseId = query.getTenantAlbumPurchaseId();
        if (tenantAlbumPurchaseId != null) {
            // 查询关联这个专辑对应的小组学生
            TenantAlbumPurchase tenantAlbumPurchase = tenantAlbumPurchaseService.getById(tenantAlbumPurchaseId);
            Long tenantAlbumId = tenantAlbumPurchase.getTenantAlbumId();
            List<String> tenantGroupIds = tenantGroupAlbumService.lambdaQuery()
                    .eq(TenantGroupAlbum::getTenantAlbumId, tenantAlbumId)
                    .eq(TenantGroupAlbum::getDelFlag, false)
                    .eq(TenantGroupAlbum::getStatus, true)
                    .list().stream().map(TenantGroupAlbum::getTenantGroupId).map(String::valueOf).distinct().collect(Collectors.toList());
            if (CollectionUtils.isEmpty(tenantGroupIds)) {
                // 没有小组
                return succeed(PageUtil.getPageInfo(PageUtil.getPage(query), new ArrayList<>()));
            }
            String tenantGroupId = query.getTenantGroupId();
            if (StringUtils.isNotEmpty(tenantGroupId)) {
                if(!tenantGroupIds.contains(tenantGroupId)){
                    return succeed(PageUtil.getPageInfo(PageUtil.getPage(query), new ArrayList<>()));
                }
            } else {
                query.setTenantGroupId(String.join(",", tenantGroupIds));
            }
        }

        IPage<StudentVo> pages = studentService.selectPage(PageUtil.getPage(query), query);
        List<StudentVo> rows = pages.getRecords();

        //如果真实姓名字段为空 把真实姓名赋值给昵称
        rows.forEach(r -> {
            if (StringUtils.isEmpty(r.getRealName())) {
                if (StringUtils.isNotEmpty(r.getUsername())) {
                    r.setRealName(r.getUsername());
                }
            }
        });

        Map<String, List<TenantActivationCode>> groupByPhone = new HashMap<>();
        if (!rows.isEmpty() && query.getTenantAlbumPurchaseId() != null) {
            List<String> studentPhones =
                    rows.stream().map(StudentVo::getPhone).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
            groupByPhone = tenantActivationCodeService.lambdaQuery()
                    .eq(TenantActivationCode::getTenantAlbumPurchaseId, query.getTenantAlbumPurchaseId())
                    .in(TenantActivationCode::getActivationPhone, studentPhones)
                    .list().stream().collect(Collectors.groupingBy(TenantActivationCode::getActivationPhone));
        }

        List<Long> tenantGroupIds = rows.stream().map(Student::getTenantGroupId)
                .filter(next -> next != null && next != -1L).distinct().collect(Collectors.toList());
        Map<Long, String> tenantGroupIdNameMap = new HashMap<>();
        if (!tenantGroupIds.isEmpty()) {
            Map<Long, String> tenantGroupMap = tenantGroupService.lambdaQuery()
                    .in(TenantGroup::getId, tenantGroupIds)
                    .list().stream().collect(Collectors.toMap(TenantGroup::getId, TenantGroup::getName));
            tenantGroupIdNameMap.putAll(tenantGroupMap);
        }


        for (StudentVo vo : rows) {
            vo.setSendActiveCodeNum(groupByPhone.getOrDefault(vo.getPhone(), new ArrayList<>()).size());
            if (vo.getDelFlag() == YesOrNoEnum.YES) {
                vo.setUserStatus(UserStatusEnum.CLOSED);
            } else {
                if (vo.getLockFlag() == UserLockFlag.LOCKED) {
                    vo.setUserStatus(UserStatusEnum.LOCKED);
                } else {
                    vo.setUserStatus(UserStatusEnum.NORMAL);
                }
            }
            vo.setTenantGroupName(tenantGroupIdNameMap.getOrDefault(vo.getTenantGroupId(), ""));
        }
        return succeed(PageUtil.pageInfo(pages));
    }

    @ApiOperation(value = "学生列表导出")
    @PostMapping("export")
    @PreAuthorize("@pcs.hasPermissions('student/export')")
    public void export(HttpServletResponse response, @RequestBody StudentSearch queryInfo) throws IOException {
        queryInfo.setPage(1);
        queryInfo.setRows(49999);

        if (StringUtils.isNotBlank(queryInfo.getUserStatus())) {
            switch (queryInfo.getUserStatus()) {
                case "LOCKED":
                    queryInfo.setDelFlag(YesOrNoEnum.NO);
                    queryInfo.setLockFlag(UserLockFlag.LOCKED);
                    break;
                case "CLOSED":
                    queryInfo.setDelFlag(YesOrNoEnum.YES);
                    break;

                default:
                    queryInfo.setDelFlag(YesOrNoEnum.NO);
                    queryInfo.setLockFlag(UserLockFlag.NORMAL);
                    break;
            }
        }
        List<StudentVo> rows = studentService.selectPage(PageUtil.getPage(queryInfo), queryInfo).getRecords();
        if (rows.size() < 1) {
            throw new BizException("没有可导出数据");
        }

        List<Long> tenantGroupIds = rows.stream().map(Student::getTenantGroupId)
                .filter(next -> next != null && next != -1L).distinct().collect(Collectors.toList());
        Map<Long, String> tenantGroupIdNameMap = new HashMap<>();
        if (!tenantGroupIds.isEmpty()) {
            Map<Long, String> tenantGroupMap = tenantGroupService.lambdaQuery()
                    .in(TenantGroup::getId, tenantGroupIds)
                    .list().stream().collect(Collectors.toMap(TenantGroup::getId, TenantGroup::getName));
            tenantGroupIdNameMap.putAll(tenantGroupMap);
        }

        for (StudentVo vo : rows) {
            if (vo.getDelFlag() == YesOrNoEnum.YES) {
                vo.setUserStatus(UserStatusEnum.CLOSED);
            } else {
                if (vo.getLockFlag() == UserLockFlag.LOCKED) {
                    vo.setUserStatus(UserStatusEnum.LOCKED);
                } else {
                    vo.setUserStatus(UserStatusEnum.NORMAL);
                }
            }
            vo.setTenantGroupName(tenantGroupIdNameMap.getOrDefault(vo.getTenantGroupId(), ""));
        }
        OutputStream outputStream = response.getOutputStream();
        try {
            HSSFWorkbook workbook = POIUtil.exportExcel(new String[]{"学生编号", "学生姓名", "真实姓名", "性别", "出生日期",
                    "年龄", "专业", "手机号码", "会员类型", "会员结束时间", "注册时间", "用户状态", "学生来源","小组"}, new String[]{
                    "userId", "username", "realName", "gender.msg", "birthdate", "age", "subjectName", "phone",
                    "vipType.name", "membershipEndTimeStr", "createTime", "userStatus.msg", "tenantName", "tenantGroupName"}, rows);
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attac:wq" +
                    "hment;filename=学生列表-" + DateUtil.getDate(new Date()) + ".xls");

            outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

//    @PostMapping("/addVip")
//    @ApiOperation(value = "添加会员")
//    @PreAuthorize("@pcs.hasPermissions('student/addVip')")
//    public HttpResponseResult<Boolean> addVip(@Valid @RequestBody VipSubmitReq vipSubmitReq) {
//        SysUser sysUser = sysUserFeignService.queryUserInfo();
//        if (sysUser == null || sysUser.getId() == null) {
//            return failed("用户信息获取失败");
//        }
//        return succeed(memberPriceSettingsService.addVip(vipSubmitReq, ClientEnum.STUDENT, sysUser));
//    }


    @PostMapping("/vipRecord")
    @ApiOperation(value = "会员记录")
    @PreAuthorize("@pcs.hasPermissions('student/vipRecord')")
    public HttpResponseResult<PageInfo<VipRecordVo>> vipRecord(@Valid @RequestBody VipRecordSearch recordSearch) {

        recordSearch.setDisplayFlag(true);
        recordSearch.setClient(ClientEnum.STUDENT);
        return succeed(vipCardRecordService.vipRecord(recordSearch));
    }

    @PostMapping("/updateTenant")
    @ApiOperation(value = "修改机构")
    public HttpResponseResult<Boolean> updateTenant(@RequestBody StudentWrapper.StudentUpdateTenant updateTenant) {
        SysUser user = sysUserFeignService.queryUserById(updateTenant.getStudentId());
        if (user == null || null == user.getId()) {
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }

        Student student = studentService.getById(user.getId());
        if (student == null) {
            return failed("未查询到学生的信息");
        }

        if (student.getTenantId() == null || student.getTenantId() == -1L) {
            return failed("非机构用户不允许更换机构");
        }

        studentService.updateTenant(student, updateTenant.getTenantId());
        return succeed();
    }


    @PostMapping("/add")
    @ApiOperation(value = "新增", notes = "传入Student")
    public HttpResponseResult<Boolean> add(@Validated @RequestBody StudentWrapper.Student student) {
        SysUser sysUser = sysUserFeignService.queryUserByMobile(student.getPhone());
        if (sysUser != null && sysUser.getUserType().contains(ClientEnum.STUDENT.getCode())) {
            throw new BizException("学生账号已经存在");
        }
        studentService.save(student);
        return succeed();
    }

    @PostMapping("/update")
    @ApiOperation(value = "修改", notes = "传入Student")
    public HttpResponseResult<Boolean> update(@Validated @RequestBody StudentWrapper.Student student) {
        if (student.getId() == null) {
            throw new BizException("id 不能为空");
        }
        studentService.save(student);
        return succeed();
    }
}