/**
 * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
 * <p>
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl.html
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xiaoniu.subsystem.business.controller;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.xiaoniu.common.core.result.R;
import com.xiaoniu.common.core.utils.BeanUtil;
import com.xiaoniu.common.core.utils.DateUtils;
import com.xiaoniu.common.core.utils.poi.ExcelUtil;
import com.xiaoniu.common.core.vo.LabelAndValueNameVO;
import com.xiaoniu.common.log.annotation.Log;
import com.xiaoniu.common.log.enums.BusinessType;
import com.xiaoniu.subsystem.business.domain.Expense;
import com.xiaoniu.subsystem.business.domain.dto.ExpenseDTO;
import com.xiaoniu.subsystem.business.domain.dto.ExpensePageDTO;
import com.xiaoniu.subsystem.business.domain.vo.ExpenseExcelVO;
import com.xiaoniu.subsystem.business.domain.vo.ExpensePageVO;
import com.xiaoniu.subsystem.business.domain.vo.ExpenseVO;
import com.xiaoniu.subsystem.business.service.IExpenseService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;

import static com.xiaoniu.common.security.utils.SecurityUtils.getUnitId;
import static com.xiaoniu.common.security.utils.SecurityUtils.getUserId;

/**
 * 费用管理表 控制器
 *
 * @author sst
 * @since 2024-11-26
 */
@RestController
@AllArgsConstructor
@RequestMapping("/expense")
@Tag(name = "费用管理表", description = "费用管理表接口")
public class ExpenseController  {

	private IExpenseService expenseService;


	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@Operation(summary = "详情", description = "传入expense")
	public R<ExpenseVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long expenseId) {
		Expense detail = expenseService.getById(expenseId);
		return R.data(BeanUtil.copy(detail, ExpenseVO.class));
	}

	/**
	 * 分页 费用管理表
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 2)
	@Operation(summary = "分页", description = "传入budget")
	public R<ExpensePageVO> page(@Validated ExpensePageDTO dto) {
		ExpensePageVO pageVO = new ExpensePageVO();
		IPage<Expense> pages = expenseService.page(new Page<>(dto.getPageNum(), dto.getPageSize()),
				new LambdaQueryWrapper<Expense>()
						.orderByDesc(Expense::getCreateTime)
						.eq(null != dto.getFlightId(),Expense::getFlightId,dto.getFlightId())
						.like(StringUtils.isNotBlank(dto.getFlightName()), Expense::getFlightName,dto.getFlightName())
						.eq(null != dto.getTrainingUnitId(),Expense::getTrainingUnitId,dto.getTrainingUnitId())
						.like(StringUtils.isNotBlank(dto.getTrainingUnitName()), Expense::getTrainingUnitName,dto.getTrainingUnitName()));
		return R.data(pageVO.setVoList(statistics(pages.getRecords()))
				.setVoiPage(BeanUtil.copy(pages, ExpenseVO.class)));
	}

	/**
	 * 导出
	 */
	@GetMapping("/export")
	@ApiOperationSupport(order = 3)
	@Log(title = "费用导出", businessType = BusinessType.EXPORT)
	@Operation(summary = "导出", description = "传入ids")
	public void export(HttpServletResponse response,@Validated ExpensePageDTO dto) {
		List<Expense> list = new ArrayList<>();
		if (StringUtils.isNotBlank(dto.getIds())){
			list.addAll(expenseService.list(new LambdaQueryWrapper<Expense>()
					.orderByDesc(Expense::getCreateTime)
					.in(StringUtils.isNotBlank(dto.getIds()), Expense::getExpenseId,
							Arrays.stream(dto.getIds().split(",")).toList())));
		}else {
			list.addAll(expenseService.list(new LambdaQueryWrapper<Expense>()
				.orderByDesc(Expense::getCreateTime)
				.eq(null != dto.getFlightId(),Expense::getFlightId,dto.getFlightId())
				.like(StringUtils.isNotBlank(dto.getFlightName()),
						Expense::getFlightName,dto.getFlightName())
				.eq(null != dto.getTrainingUnitId(),
						Expense::getTrainingUnitId,dto.getTrainingUnitId())
				.like(StringUtils.isNotBlank(dto.getTrainingUnitName()),
						Expense::getTrainingUnitName,dto.getTrainingUnitName())));
		}
		ExcelUtil<ExpenseExcelVO> excelUtil = new ExcelUtil<>(ExpenseExcelVO.class);
		excelUtil.exportExcel(response, BeanUtil.copy(list,ExpenseExcelVO.class),"费用数据");

	}

	/**
	 * 新增 费用管理表
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@Operation(summary = "新增", description = "传入expense")
	public R save(@Valid @RequestBody ExpenseDTO dto) {
		Expense one = expenseService.getOne(new LambdaQueryWrapper<Expense>()
				.eq(Expense::getFlightName, dto.getFlightName())
				// .eq(Demand::getTrainingBatch, copy.getTrainingBatch())
				.eq(Expense::getTrainingTime, dto.getTrainingTime())
				.eq(Expense::getYear, dto.getYear()));
		if (null != one) {
			return R.fail("已存在年度：" + dto.getYear() +
					"度,开训时间：" + DateUtils.dateTime(dto.getTrainingTime()) +
					",专业（班次）名称：" + dto.getFlightName() +
					"的费用，请核对");
		}
		return R.status(expenseService.save(dto.setCreateDept(getUnitId())
				.setYear(String.valueOf(LocalDate.now().getYear()))
				.setCreateUser(getUserId()).setCreateTime(new Date())));
	}

	/**
	 * 修改 费用管理表
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@Operation(summary = "修改", description = "传入expense")
	public R update(@Valid @RequestBody ExpenseDTO dto) {
		Expense one = expenseService.getOne(new LambdaQueryWrapper<Expense>()
				.ne(Expense::getExpenseId, dto.getExpenseId())
				.eq(Expense::getFlightName, dto.getFlightName())
				// .eq(Demand::getTrainingBatch, copy.getTrainingBatch())
				.eq(Expense::getTrainingTime, dto.getTrainingTime())
				.eq(Expense::getYear, dto.getYear()));
		if (null != one) {
			return R.fail("已存在年度：" + dto.getYear() +
					"度,开训时间：" + DateUtils.dateTime(dto.getTrainingTime()) +
					",专业（班次）名称：" + dto.getFlightName() +
					"的费用，请核对");
		}
		return R.status(expenseService.updateById(dto
				.setUpdateUser(getUserId()).setUpdateTime(new Date())));
	}

	/**
	 * 获取需求报名人数
	 */
	@GetMapping("/get/flightIds")
	@ApiOperationSupport(order = 13)
	@Operation(summary = "获取协议/合同班次ids")
	public R<List<Long>> getPeopleNum() {
		List<Expense> list = expenseService.list(new LambdaQueryWrapper<Expense>()
				.eq(Expense::getCreateDept,getUnitId()));
		if (CollectionUtils.isEmpty(list)) return R.data(Collections.emptyList());
		return R.data(list.stream().map(Expense::getFlightId).toList());
	}


	/**
	 * 删除 费用管理表
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@Operation(summary = "删除", description = "传入ids")
	public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String expenseIds) {
		return R.status(expenseService.removeByIds(Arrays.stream(expenseIds.split(",")).toList()));
	}

	private List<LabelAndValueNameVO> statistics(List<Expense> list) {
		List<LabelAndValueNameVO> voList = new ArrayList<>();
		if (CollectionUtils.isEmpty(list)){
			voList.add(new LabelAndValueNameVO().setName("年度计划金额").setValue("0"));
			voList.add(new LabelAndValueNameVO().setName("已结算金额").setValue("0"));
			voList.add(new LabelAndValueNameVO().setName("剩余可支配金额").setValue("0"));
			voList.add(new LabelAndValueNameVO().setName("未培训班级数量").setValue("0"));
			voList.add(new LabelAndValueNameVO().setName("培训中班级数量").setValue("0"));
			voList.add(new LabelAndValueNameVO().setName("已培训班级数量").setValue("0"));
			return voList;
		}
		BigDecimal reduce = list.stream().map(l ->
						BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getOrganBudgetedAmount()) ?
								"0" : l.getOrganBudgetedAmount())))
				.reduce(BigDecimal.ZERO, BigDecimal::add);
		voList.add(new LabelAndValueNameVO().setName("年度计划金额").setValue(reduce.stripTrailingZeros().toPlainString()));
		BigDecimal reduce1 = list.stream().map(l ->
						BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getSettlementAmount()) ?
								"0" : l.getSettlementAmount())))
				.reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros();
		voList.add(new LabelAndValueNameVO().setName("已结算金额").setValue(reduce1.stripTrailingZeros().toPlainString()));
		voList.add(new LabelAndValueNameVO().setName("剩余可支配金额")
				.setValue(reduce.subtract(reduce1).stripTrailingZeros().toPlainString()));
		voList.add(new LabelAndValueNameVO().setName("未培训班级数量")
				.setValue(String.valueOf(list.stream().filter(l ->
						new Date().compareTo(l.getTrainingTime()) < 0).count())));
		voList.add(new LabelAndValueNameVO().setName("培训中班级数量")
				.setValue(String.valueOf(list.stream().filter(l ->
						l.getTrainingTime().compareTo(new Date()) < 0
								&& l.getEndTime().compareTo(new Date()) > 0).count())));
		voList.add(new LabelAndValueNameVO().setName("已培训班级数量")
				.setValue(String.valueOf(list.stream().filter(l ->
						l.getEndTime().compareTo(new Date()) < 0).count())));
		return voList;
	}
}
