/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.distribution.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.codec.Charsets;
import org.springblade.common.base.BaseEntity;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.api.vo.ExportAllAppointGoodsVO;
import org.springblade.modules.api.vo.ExportAppointGoodsVO;
import org.springblade.modules.api.vo.ExportTakeAppointGoodsVO;
import org.springblade.modules.distribution.vo.AppointStoreVO;
import org.springblade.modules.groupon.entity.Groupon;
import org.springblade.modules.groupon.entity.UserSelfTake;
import org.springblade.modules.groupon.service.IGrouponService;
import org.springblade.modules.groupon.service.IUserSelfTakeService;
import org.springblade.modules.mall.entity.Store;
import org.springblade.modules.mall.service.IStoreService;
import org.springblade.modules.platform.service.UserAppService;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.entity.UserApp;
import org.springblade.modules.system.excel.UserExcel;
import org.springblade.modules.system.service.IUserService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.modules.distribution.entity.Appoint;
import org.springblade.modules.distribution.vo.AppointVO;
import org.springblade.modules.distribution.wrapper.AppointWrapper;
import org.springblade.modules.distribution.service.IAppointService;
import org.springblade.core.boot.ctrl.BladeController;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 履约单表列表 控制器
 *
 * @author BladeX
 * @since 2023-06-06
 */
@RestController
@AllArgsConstructor
@RequestMapping("distribution/appoint")
@Api(value = "履约单表列表", tags = "履约单表列表接口")
public class AppointController extends BladeController {

	private final IAppointService appointService;

	@Resource
	private IStoreService storeService;

	@Resource
	private IGrouponService grouponService;

	@Resource
	private UserAppService userAppService;

	@Resource
	private IUserSelfTakeService userSelfTakeService;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入appoint")
	public R<AppointVO> detail(Appoint appoint) {
		Appoint detail = appointService.getOne(Condition.getQueryWrapper(appoint));
		return R.data(AppointWrapper.build().entityVO(detail));
	}

	/**
	 * 分页 履约单表列表
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入appoint")
	public R<IPage<AppointStoreVO>> list(Integer appointState, Query query) {
		Store store = storeService.getByUserId();
		return R.data(appointService.getAppointAllVOs(Condition.getPage(query), appointState));
	}

	@GetMapping("/tzList")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "团长分页", notes = "传入appoint")
	public R<IPage<AppointStoreVO>> tzList(Integer appointState, Query query) {
		UserApp userApp = userAppService.getByUserId(AuthUtil.getUserId());
		if(ObjectUtil.isEmpty(userApp.getLivingHall()) || !userApp.getLivingHall().equals(1)){
			return R.fail("团长身份异常，请联系客服");
		}
		UserSelfTake userSelfTake = userSelfTakeService.getOne(Wrappers.lambdaQuery(UserSelfTake.class).eq(UserSelfTake::getUserId, userApp.getUserId()));
		return R.data(appointService.getAppointTakeVOs(Condition.getPage(query), appointState, userSelfTake.getSelfTakeId()));
	}

	@GetMapping("/storeList")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入appoint")
	public R<IPage<AppointStoreVO>> storeList(Integer appointState, Query query) {
		Store store = storeService.getByUserId();
		if(ObjectUtil.isEmpty(store)){
			return R.fail("供应商身份异常，请联系客服");
		}
		return R.data(appointService.getAppointStoreVOs(Condition.getPage(query), appointState, store.getId()));
	}

	@GetMapping("/appointAllList")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "供应商负责的自提点列表", notes = "传入")
	public R<IPage<AppointVO>> appointAllList(Appoint appoint, Query query){
		return R.data(appointService.appointListBy(Condition.getPage(query), appoint));
	}

	@GetMapping("/appointStoreList")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "供应商负责的自提点列表", notes = "传入")
	public R<IPage<AppointVO>> appointStoreList(Appoint appoint, Query query){
		Store store = storeService.getByUserId();
		if(ObjectUtil.isEmpty(store)){
			return R.fail("供应商身份异常，请联系客服");
		}
		appoint.setStoreId(store.getId());
		return R.data(appointService.appointListBy(Condition.getPage(query), appoint));
	}

	@GetMapping("/appointTakeList")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "团长负责的自提点列表", notes = "传入")
	public R<IPage<AppointVO>> appointTakeList(Appoint appoint, Query query){
		UserApp userApp = userAppService.getByUserId(AuthUtil.getUserId());
		if(ObjectUtil.isEmpty(userApp.getLivingHall()) || !userApp.getLivingHall().equals(1)){
			return R.fail("团长身份异常，请联系客服");
		}
		UserSelfTake userSelfTake = userSelfTakeService.getOne(Wrappers.lambdaQuery(UserSelfTake.class).eq(UserSelfTake::getUserId, userApp.getUserId()));
		appoint.setTakeId(userSelfTake.getSelfTakeId());
		return R.data(appointService.appointListBy(Condition.getPage(query), appoint));
	}

	/**
	 * 自定义分页 履约单表列表
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入appoint")
	public R<IPage<AppointVO>> page(AppointVO appoint, Query query) {
		IPage<AppointVO> pages = appointService.selectAppointPage(Condition.getPage(query), appoint);
		return R.data(pages);
	}

	/**
	 * 新增 履约单表列表
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入appoint")
	public R save(@Valid @RequestBody Appoint appoint) {
		return R.status(appointService.save(appoint));
	}

	/**
	 * 修改 履约单表列表
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入appoint")
	public R update(@Valid @RequestBody Appoint appoint) {
		return R.status(appointService.updateById(appoint));
	}

	/**
	 * 新增或修改 履约单表列表
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增或修改", notes = "传入appoint")
	public R submit(@Valid @RequestBody Appoint appoint) {
		return R.status(appointService.saveOrUpdate(appoint));
	}


	/**
	 * 删除 履约单表列表
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(appointService.removeByIds(Func.toLongList(ids)));
	}

	@GetMapping("exportAllAppointGoods")
	@ApiOperation(value = "运营商导出excle", notes = "传入团购id")
	public void exportAllAppointGoods(Long grouponId, HttpServletResponse response){
		List<ExportAllAppointGoodsVO> exportAppointGoodsVOS = appointService.exportAllGoods(grouponId);
		ExcelUtil.export(response, "履约单管理" + DateUtil.time(), "履约单列表", exportAppointGoodsVOS, ExportAllAppointGoodsVO.class);
	}

	@GetMapping("exportStoreAppointGoods")
	@ApiOperation(value = "供应商导出excle", notes = "传入团购id")
	public void exportStoreAppointGoods(Long grouponId, HttpServletResponse response){
		Store store = storeService.getByUserId();
		List<ExportAppointGoodsVO> exportAppointGoodsVOS = appointService.exportStoreGoods(grouponId, store.getId());
		ExcelUtil.export(response, "履约单管理" + DateUtil.time(), "履约单列表", exportAppointGoodsVOS, ExportAppointGoodsVO.class);
	}

	@GetMapping("exportTakeAppointGoods")
	@ApiOperation(value = "团长提货点导出excle", notes = "传入团购id")
	public void exportTakeAppointGoods(Long grouponId, HttpServletResponse response){
		UserSelfTake userSelfTake = userSelfTakeService.getOne(Wrappers.lambdaQuery(UserSelfTake.class).eq(UserSelfTake::getUserId, AuthUtil.getUserId()));
		List<ExportTakeAppointGoodsVO> exportAppointGoodsVOS = appointService.exportTakeGoods(grouponId, userSelfTake.getSelfTakeId());
		ExcelUtil.export(response, "履约单管理" + DateUtil.time(), "履约单列表", exportAppointGoodsVOS, ExportTakeAppointGoodsVO.class);
	}

	@PostMapping("/shipments")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "履约单发货", notes = "传入id")
	public R shipments(@ApiParam(value = "主键集合", required = true) @RequestParam String id) {
		Store store = storeService.getByUserId();
		if(ObjectUtil.isEmpty(store)){
			return R.fail("供应商身份异常，请联系客服");
		}
		Appoint appoint = appointService.getById(id);
		Groupon groupon = grouponService.getById(appoint.getGrouponId());
		if(groupon.getTakeStartTime().isBefore(DateUtil.fromDate(new Date()))){
			return R.fail("团购提货时间已经到了，该履约单无法进行发货了");
		}
		return R.status(appointService.update(Wrappers.lambdaUpdate(Appoint.class).eq(BaseEntity::getId, id)
				.eq(Appoint::getStoreId, store.getId())
				.eq(Appoint::getState, 0)
				.set(Appoint::getState, 1)
				.set(Appoint::getShipmentsTime, new Date())));
	}

	@PostMapping("/shipmnetsALl")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "团购履约单发货", notes = "传入id")
	public R shipmnetsALl(@ApiParam(value = "主键集合", required = true) @RequestParam String grouponId){
		Store store = storeService.getByUserId();
		if(ObjectUtil.isEmpty(store)){
			return R.fail("供应商身份异常，请联系客服");
		}
		Groupon groupon = grouponService.getById(grouponId);
		if(groupon.getTakeStartTime().isBefore(DateUtil.fromDate(new Date()))){
			return R.fail("团购提货时间已经到了，该履约单无法进行发货了");
		}
		return R.status(appointService.update(Wrappers.lambdaUpdate(Appoint.class).eq(Appoint::getGrouponId, grouponId)
				.eq(Appoint::getStoreId, store.getId())
				.eq(Appoint::getState, 0)
				.set(Appoint::getState, 1)
				.set(Appoint::getShipmentsTime, new Date())));
	}

	@PostMapping("/commitAppoint")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "履约单收货", notes = "传入id")
	public R commitAppoint(@ApiParam(value = "主键集合", required = true) @RequestParam Long id) {
		appointService.commitAppoint(id);
		return R.success("核销成功");
	}

	@PostMapping("/commitAppointAll")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "团购履约单收货", notes = "传入ids")
	public R commitAppointAll(@ApiParam(value = "主键集合", required = true) @RequestParam String grouponId) {
		UserSelfTake userSelfTake = userSelfTakeService.getOne(Wrappers.lambdaQuery(UserSelfTake.class).eq(UserSelfTake::getUserId, AuthUtil.getUserId()));
		List<Appoint> list = appointService.list(Wrappers.lambdaUpdate(Appoint.class).eq(Appoint::getGrouponId, grouponId)
				.eq(Appoint::getGrouponId, grouponId).eq(Appoint::getTakeId, userSelfTake.getSelfTakeId())
				.eq(Appoint::getState, 1));
		if(list.size() == 0){
			return R.fail("暂时没有可以进行核销的供应商");
		}
		for (Appoint appoint : list) {
			appointService.commitAppoint(appoint.getId());
		}
		return R.success("核销成功");
	}

}
