package com.yonge.cooleshow.admin.controller.open;

import com.alibaba.fastjson.JSON;
import com.microsvc.toolkit.config.jwt.utils.RsaKeyHelper;
import com.yonge.cooleshow.admin.io.request.coupon.CouponOrderVO;
import com.yonge.cooleshow.api.feign.dto.CouponInfoApi;
import com.yonge.cooleshow.api.feign.dto.EmployeeApi;
import com.yonge.cooleshow.api.feign.dto.StudentApi;
import com.yonge.cooleshow.api.feign.dto.TeacherApi;
import com.yonge.cooleshow.api.feign.dto.TenantWrapper;
import com.yonge.cooleshow.biz.dal.entity.Employee;
import com.yonge.cooleshow.biz.dal.entity.Student;
import com.yonge.cooleshow.biz.dal.entity.Teacher;
import com.yonge.cooleshow.biz.dal.entity.TenantInfo;
import com.yonge.cooleshow.biz.dal.entity.TenantStaff;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.enums.coupon.CouponCategoryEnum;
import com.yonge.cooleshow.biz.dal.enums.coupon.CouponUseStateEnum;
import com.yonge.cooleshow.biz.dal.queryInfo.CouponInfoQuery;
import com.yonge.cooleshow.biz.dal.service.CouponInfoService;
import com.yonge.cooleshow.biz.dal.service.EmployeeService;
import com.yonge.cooleshow.biz.dal.service.StudentService;
import com.yonge.cooleshow.biz.dal.service.TeacherService;
import com.yonge.cooleshow.biz.dal.service.TenantInfoService;
import com.yonge.cooleshow.biz.dal.service.TenantStaffService;
import com.yonge.cooleshow.biz.dal.service.UserFirstTimeService;
import com.yonge.cooleshow.biz.dal.wrapper.StudentWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.coupon.CouponOrderWrapper;
import com.yonge.cooleshow.common.controller.BaseController;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.enums.UserFirstTimeTypeEnum;
import com.yonge.toolset.base.exception.BizException;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("${app-config.url.admin:}/open/adminClient")
public class AdminClient extends BaseController {

    @Autowired
    private UserFirstTimeService userFirstTimeService;

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private CouponInfoService couponInfoService;

    @Autowired
    private TenantStaffService tenantStaffService;

    @Autowired
    private TenantInfoService tenantInfoService;

    @GetMapping("/recordTime")
    public HttpResponseResult<Boolean> recordTime(
            @RequestParam("userId") Long userId,
            @RequestParam("userType") String userType,
            @RequestParam("firstTimeType") UserFirstTimeTypeEnum firstTimeType
    ) {
        ClientEnum clientEnum = ClientEnum.valueOf(userType);
        userFirstTimeService.recordTime(userId, clientEnum, firstTimeType);
        return succeed(true);
    }

    @GetMapping("/getTeacher")
    public HttpResponseResult<TeacherApi> getTeacher(@RequestParam("userId") Long userId) {
        Teacher teacher = teacherService.getById(userId);

        TeacherApi teacherApi = new TeacherApi();
        BeanUtils.copyProperties(teacher, teacherApi);
        return succeed(teacherApi);
    }

    @GetMapping("/getStudent")
    public HttpResponseResult<StudentApi> getStudent(@RequestParam("userId") Long userId) {
        Student student = studentService.getById(userId);

        StudentApi studentApi = new StudentApi();
        BeanUtils.copyProperties(student, studentApi);
        return succeed(studentApi);
    }

    @ApiOperation(value = "学生帐号关联Id", notes = "CouponOrderVO.PageRequest")
    @PostMapping("/unionStudent")
    public HttpResponseResult<StudentWrapper.UnionStudentResp> unionStudent(@RequestBody StudentWrapper.UnionStudent info) {

        if (info.getTokenCheck() == null || info.getTokenCheck()) {
            if (StringUtils.isAnyBlank(info.getToken(), info.getMobile())) {
                throw new BizException("请求参数错误");
            }

            // 校验三方帐号关联请求合法性
            RSAPublicKey rsaPublicKey = RsaKeyHelper.getRSAPublicKey("jmedu", "dayaedu", "jmedu.jks", "dayaedu");
            Jwt jwt = JwtHelper.decodeAndVerify(info.getToken(), new RsaVerifier(rsaPublicKey));

            //获取jwt原始内容
            String claims = jwt.getClaims();
            if (StringUtils.isEmpty(claims)) {
                throw new BizException("三方授权校验失败");
            }

        }
        // 学生帐号关联
        StudentWrapper.UnionStudentResp studentResp = studentService.unionStudent(info);

        return succeed(studentResp);
    }

    @GetMapping("/getEmployee")
    public HttpResponseResult<EmployeeApi> getEmployee(@RequestParam("userId") Long userId) {
        Employee employee = employeeService.get(userId);

        EmployeeApi employeeApi = new EmployeeApi();
        BeanUtils.copyProperties(employee, employeeApi);
        return succeed(employeeApi);
    }

    @ApiOperation(value = "机构信息查询", notes = "tenantId -> 机构ID")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "tenantId", value = "机构ID", required = true, dataType = "Long", paramType = "query")
    })
    @GetMapping("/getTenant")
    public HttpResponseResult<TenantWrapper.Tenant> getTenant(@RequestParam("tenantId") Long tenantId) {

        TenantWrapper.Tenant build = TenantWrapper.Tenant.builder().build();

        TenantInfo tenantInfo = tenantInfoService.getById(tenantId);
        if (Objects.nonNull(tenantInfo)) {
            build = TenantWrapper.Tenant.from(JSON.toJSONString(tenantInfo));
        }

        return succeed(build);
    }

    @ApiOperation(value = "机构员工信息查询", notes = "userId -> 机构用户ID")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "机构用户ID", required = true, dataType = "Long", paramType = "query")
    })
    @GetMapping("/getTenantStaff")
    public HttpResponseResult<TenantWrapper.Staff> getTenantStaff(@RequestParam("userId") Long userId) {

        // 默认返回值
        TenantWrapper.Staff ret = TenantWrapper.Staff.builder().build();

        TenantStaff staff = tenantStaffService.getByUserId(userId);
        if (Objects.nonNull(staff)) {
            ret = TenantWrapper.Staff.from(JSON.toJSONString(staff));
            ret.setStatus(staff.getStatus().name());
            Long tenantId = staff.getTenantId();
            TenantInfo tenantInfo = tenantInfoService.getById(Optional.ofNullable(tenantId).orElse(-1L));
            ret.setTenantEnableFlag(Optional.ofNullable(tenantInfo).map(TenantInfo::getEnableFlag).orElse(false));
        }
        return succeed(ret);
    }

    /**
     * 订单优惠券信息
     * @return HttpResponseResult<CouponOrderVO.CouponPageInfo>
     */
    @PostMapping(value = "/orderInfo", consumes="application/json", produces="application/json")
    @ApiOperation(value = "查询订单优惠券信息", notes = "CouponOrderVO.PageRequest")
    public HttpResponseResult<CouponInfoApi> queryCouponOrderPageInfo(@RequestParam Long userId, @RequestParam String issueIds, @RequestParam BigDecimal orderAmount, @RequestParam ClientEnum client) {

        List<Long> collect = Arrays.stream(issueIds.split(","))
                                   .map(Long::valueOf)
                                   .collect(Collectors.toList());

        CouponOrderVO.PageRequest request = new CouponOrderVO.PageRequest();
        request.setClientType(client);
        request.setCouponTypes(CouponCategoryEnum.getCategory("MALL"));
        request.setIssueIds(collect);
        request.setUseState(CouponUseStateEnum.USABLE);
        request.setTimestamp(DateTime.now().getMillis());
        request.setAmount(orderAmount.doubleValue());

        CouponInfoApi couponInfoApi = new CouponInfoApi();
        couponInfoApi.setDiscountedPrices(BigDecimal.ZERO);

        if (CollectionUtils.isNotEmpty(collect)) {

            // 订单优惠券信息
            CouponOrderWrapper wrapper = couponInfoService.queryUserOrderCouponInfo(request.getUserId(),
                    CouponInfoQuery.CouponOrderQuery.from(request.jsonString()));

            couponInfoApi.setDiscountedPrices(BigDecimal.valueOf(wrapper.getDiscountedPrices()));
        }

        return succeed(couponInfoApi);
    }

    /**
     * 更新订单优惠券信息
     * @return HttpResponseResult<Boolean>
     */
    @PostMapping(value = "/orderUpdate", consumes="application/json", produces="application/json")
    @ApiOperation(value = "更新订单优惠券信息")
    public HttpResponseResult<Boolean> updateCouponOrderInfo(@RequestParam String couponIssueId,@RequestParam Boolean returnCoupon,@RequestParam String orderNo) {

        CouponOrderVO.CouponUpdateRequest  request = new CouponOrderVO.CouponUpdateRequest();
        request.setOrderNo(orderNo);
        request.setReset(returnCoupon);
        request.setUseType(CouponCategoryEnum.MALL);
        List<Long> collect = Arrays.stream(couponIssueId.split(","))
                                   .map(Long::valueOf)
                                   .collect(Collectors.toList());
        request.setIssueIds(collect);
        // 更新受影响优惠券数据
        int ret = couponInfoService.updateUserOrderCouponInfo(CouponOrderWrapper.from(request.jsonString()));

        return succeed(ret > 0);
    }
}
