package org.springblade.gateway.web_gateway.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.yeepay.yop.sdk.service.common.response.YopResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.common.aop.core.TenantAop;
import org.springblade.common.constant.Agent;
import org.springblade.common.enums.AppConstant;
import org.springblade.common.enums.CsFlag;
import org.springblade.common.enums.OrderType;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.ObjectUtil;
import org.springblade.gateway.web_gateway.entity.vo.TenantCensusAddTrendVo;
import org.springblade.gateway.web_gateway.entity.vo.TenantCensusBillsTrendVo;
import org.springblade.gateway.web_gateway.entity.vo.TenantCensusVo;
import org.springblade.gateway.web_gateway.entity.vo.YeePayInfoVO;
import org.springblade.gateway.web_gateway.service.ICensusService;
import org.springblade.ldt.agent.entity.AgentBills;
import org.springblade.ldt.agent.entity.AgentRecord;
import org.springblade.ldt.agent.service.IAgentBillsService;
import org.springblade.ldt.agent.service.IAgentRecordService;
import org.springblade.ldt.agent.vo.AgentInfoVO;
import org.springblade.ldt.bills.entity.Bills;
import org.springblade.ldt.bills.entity.PlatformBills;
import org.springblade.ldt.bills.service.IBillsService;
import org.springblade.ldt.bills.service.IPlatformBillsService;
import org.springblade.ldt.mall.entity.Mall;
import org.springblade.ldt.mall.service.IMallService;
import org.springblade.ldt.shop.entity.Shop;
import org.springblade.ldt.shop.service.IShopService;
import org.springblade.ldt.user.entity.LoginUser;
import org.springblade.ldt.user.entity.Member;
import org.springblade.ldt.user.service.ILoginUserService;
import org.springblade.ldt.user.service.IMemberService;
import org.springblade.yeePay.service.YeepaySaasService;
import org.springframework.web.bind.annotation.GetMapping;
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.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * 统计控制器
 */
@RestController
@RequestMapping("/census")
@Api(tags = "统计控制器")
@AllArgsConstructor
public class CensusController {

	private ICensusService censusService;
	private ILoginUserService loginUserService;
	private IShopService shopService;
	private IMallService mallService;
	private IMemberService memberService;
	private IAgentRecordService agentRecordService;
	private IAgentBillsService agentBillsService;
	private IPlatformBillsService platformBillsService;
	private IBillsService billsService;
	private YeepaySaasService yeepaySaasService;

	@GetMapping("/getTenantCensusCount")
	@ApiOperation(value = "获取租户数据数量统计")
	@SneakyThrows
	public R getTenantCensusCount() {
		Map<String, Object> map = billsService.getMap(new QueryWrapper<Bills>().select("ifnull(sum(total_price),0) as price").lambda()
			.and(wq -> {
				wq.eq(Bills::getType, OrderType.MALL_RECHARGE).or().eq(Bills::getType,OrderType.AGENT_CHARGE);
			})
			.and(wq -> {
				wq.eq(Bills::getCsFlag, CsFlag.CHECK).or().eq(Bills::getPayStatus, AppConstant.BillPayStatus.付款成功.name());
			}));
		return R.data(new TenantCensusVo()
			.setUserCount(loginUserService.count())
			.setShopCount(shopService.count())
			.setMallCount(mallService.count())
			.setMemberCount(memberService.count())
			.setAgentCount(agentRecordService.count())
			.setRechargeTotal(new BigDecimal(map.get("price").toString())));
	}

	@GetMapping("/getTenantTodayCensusCount")
	@ApiOperation(value = "获取今日租户数据数量统计")
	@SneakyThrows
	public R getTenantTodayCensusCount() {
		String date = DateUtil.format(new Date(), DateUtil.PATTERN_DATE);
		Map<String, Object> map = billsService.getMap(new QueryWrapper<Bills>()
			.select("ifnull(sum(total_price),0) as price")
			.eq("date_format(create_time,'%Y-%m-%d')", date)
			.lambda()
			.and(wq -> {
				wq.eq(Bills::getType, OrderType.MALL_RECHARGE).or().eq(Bills::getType,OrderType.AGENT_CHARGE);
			})
			.and(wq -> {
				wq.eq(Bills::getCsFlag, CsFlag.CHECK).or().eq(Bills::getPayStatus, AppConstant.BillPayStatus.付款成功.name());
			}));
		return R.data(new TenantCensusVo()
			.setUserCount(loginUserService.count(new QueryWrapper<LoginUser>().eq("date_format(create_time,'%Y-%m-%d')", date)))
			.setShopCount(shopService.count(new QueryWrapper<Shop>().eq("date_format(create_time,'%Y-%m-%d')", date)))
			.setMallCount(mallService.count(new QueryWrapper<Mall>().eq("date_format(create_time,'%Y-%m-%d')", date)))
			.setMemberCount(memberService.count(new QueryWrapper<Member>().eq("date_format(create_time,'%Y-%m-%d')", date)))
			.setAgentCount(agentRecordService.count(new QueryWrapper<AgentRecord>().eq("date_format(create_time,'%Y-%m-%d')", date)))
			.setRechargeTotal(new BigDecimal(map.get("price").toString())));
	}

	@GetMapping("/getTenantPlatformBills")
	@ApiOperation(value = "获取租户平台收益统计")
	@SneakyThrows
	public R getTenantPlatformBills(@RequestParam Date time) {
		return R.data(new TenantCensusBillsTrendVo()
			.setPlatformBills(platformBillsService.listMaps(new QueryWrapper<PlatformBills>()
				.select("ifnull(sum(fee),0) as price", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time")))
			.setUserPayBills(platformBillsService.listMaps(new QueryWrapper<PlatformBills>()
				.select("ifnull(sum(price),0) as price", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.and(platformBillsQueryWrapper -> {
					platformBillsQueryWrapper.lambda()
						.eq(PlatformBills::getType, OrderType.USER_PAY).or()
						.eq(PlatformBills::getType, OrderType.WECHAT_PAY);
				})
				.groupBy("time")
				.orderBy(true, true, "time")))
			.setAgentChargeBills(platformBillsService.listMaps(new QueryWrapper<PlatformBills>()
				.select("ifnull(sum(price),0) as price", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time").lambda()
				.eq(PlatformBills::getType, OrderType.AGENT_CHARGE)))
			.setMallChargeBills(platformBillsService.listMaps(new QueryWrapper<PlatformBills>()
				.select("ifnull(sum(price),0) as price", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time").lambda()
				.eq(PlatformBills::getType, OrderType.MALL_RECHARGE))));
	}

	@GetMapping("/getTenantAddTrend")
	@ApiOperation(value = "获取租户平台新增趋势统计")
	@SneakyThrows
	public R getTenantAddTrend(@RequestParam Date time) {
		return R.data(new TenantCensusAddTrendVo()
			.setUserAddCount(loginUserService.listMaps(new QueryWrapper<LoginUser>()
				.select("count(*) as `count`", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time")))
			.setAgentAddCount(agentRecordService.listMaps(new QueryWrapper<AgentRecord>()
				.select("count(*) as `count`", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time")))
			.setMallAddCount(mallService.listMaps(new QueryWrapper<Mall>()
				.select("count(*) as `count`", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time")))
			.setMemberAddCount(memberService.listMaps(new QueryWrapper<Member>()
				.select("count(*) as `count`", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time")))
			.setShopAddCount(shopService.listMaps(new QueryWrapper<Shop>()
				.select("count(*) as `count`", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time"))));
	}

	@GetMapping("/getAgentInfo")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "代理商信息")
	@TenantAop(agent = Agent.roleName)
	public R<AgentInfoVO> agentInfo(BladeUser bladeUser) {
		return R.data(agentRecordService.getAgentInfo(bladeUser.getUserId()));
	}

	@GetMapping("/getMerchantInfo")
	@ApiOperation(value = "易宝商户信息")
	public R<YeePayInfoVO> getMerchantInfo(BladeUser bladeUser) {
		Mall mall = mallService.getOne(Wrappers.<Mall>lambdaQuery().eq(Mall::getTenantId, bladeUser.getTenantId()));
		if (mall == null || ObjectUtil.isEmpty(mall.getMerchantNo())) {
			return R.data(null);
		}
		YopResponse yopResponse = yeepaySaasService.accountInfosQuery(mall.getMerchantNo());
		JSONObject res = JSON.parseObject(yopResponse.getStringResult());
		if (!Objects.equals(res.getString("returnCode"), "UA00000")) {
			throw new ServiceException(res.getString("returnMsg"));
		}
		return R.data(YeePayInfoVO.builder().mall(mall).yeePayInfo(res).build());
	}

	@GetMapping("/getAgentTenantCensusCount")
	@ApiOperation(value = "获取代理租户数据数量统计")
	@TenantAop(agent = Agent.roleName)
	public R getAgentTenantCensusCount(BladeUser bladeUser) {
		Long userId = Agent.getAgentUserId(bladeUser);
		Map<String, Object> map = agentBillsService.getMap(new QueryWrapper<AgentBills>()
			.select("ifnull(sum(fee),0) as price")
			.lambda()
			.eq(AgentBills::getAgenter, userId));
		return R.data(new TenantCensusVo()
			.setShopCount(shopService.count(Wrappers.<Shop>lambdaQuery().eq(Shop::getAgenter, userId)))
			.setIncomeTotal(new BigDecimal(map.get("price").toString())));
	}

	@GetMapping("/getAgentTenantTodayCensusCount")
	@ApiOperation(value = "获取今日代理租户数据数量统计")
	@TenantAop(agent = Agent.roleName)
	public R getAgentTenantTodayCensusCount(BladeUser bladeUser) {
		Long userId = Agent.getAgentUserId(bladeUser);
		String date = DateUtil.format(new Date(), DateUtil.PATTERN_DATE);
		Map<String, Object> map = agentBillsService.getMap(new QueryWrapper<AgentBills>()
			.select("ifnull(sum(fee),0) as price")
			.eq("date_format(create_time,'%Y-%m-%d')", date)
			.lambda()
			.eq(AgentBills::getAgenter, userId));
		return R.data(new TenantCensusVo()
			.setShopCount(shopService.count(Wrappers.<Shop>query()
				.eq("date_format(create_time,'%Y-%m-%d')", date)
				.lambda().eq(Shop::getAgenter, userId)))
			.setIncomeTotal(new BigDecimal(map.get("price").toString())));
	}

	@GetMapping("/getTenantAgentBills")
	@ApiOperation(value = "获取租户平台代理收益统计")
	@TenantAop(agent = Agent.roleName)
	public R getTenantAgentBills(@RequestParam Date time, BladeUser bladeUser) {
		Long userId = Agent.getAgentUserId(bladeUser);
		return R.data(new TenantCensusBillsTrendVo()
			.setAgentIncomeBills(agentBillsService.listMaps(new QueryWrapper<AgentBills>()
				.select("ifnull(sum(fee),0) as price", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time").lambda()
				.eq(AgentBills::getAgenter, userId))));
	}

	@GetMapping("/getAgentTenantAddTrend")
	@ApiOperation(value = "获取代理租户平台新增趋势统计")
	@TenantAop(agent = Agent.roleName)
	public R getAgentTenantAddTrend(@RequestParam Date time, BladeUser bladeUser) {
		Long userId = Agent.getAgentUserId(bladeUser);
		return R.data(new TenantCensusAddTrendVo()
			.setShopAddCount(shopService.listMaps(new QueryWrapper<Shop>()
				.select("count(*) as `count`", "date_format(create_time,'%Y-%m-%d') as time")
				.eq("date_format(create_time,'%Y-%m')", DateUtil.format(time, "yyyy-MM"))
				.groupBy("time")
				.orderBy(true, true, "time")
				.lambda()
				.eq(Shop::getAgenter, userId))));
	}
}
