/**
 * 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.conditions.query.QueryWrapper;
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.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.*;
import com.xiaoniu.subsystem.business.domain.dto.BudgetPageDTO;
import com.xiaoniu.subsystem.business.domain.dto.ExpenseDTO;
import com.xiaoniu.subsystem.business.domain.dto.ExpensePageDTO;
import com.xiaoniu.subsystem.business.domain.vo.BudgetPageVO;
import com.xiaoniu.subsystem.business.domain.vo.BudgetVO;
import com.xiaoniu.subsystem.business.domain.vo.ExpensePageVO;
import com.xiaoniu.subsystem.business.domain.vo.ExpenseVO;
import com.xiaoniu.subsystem.business.service.IAnnualPlanAmountService;
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.time.LocalDateTime;
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;
	private IAnnualPlanAmountService amountService;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@Operation(summary = "详情", description = "传入flightId")
	public R<ExpenseVO> detail(@Parameter(description = "班次id", required = true) @RequestParam Long flightId) {
		Expense detail = expenseService.getOne(new LambdaQueryWrapper<Expense>()
				.eq(Expense::getFlightId,flightId)
		);
		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("/page")
	@ApiOperationSupport(order = 2)
	@Operation(summary = "分页", description = "传入budget")
	public R<IPage<ExpenseVO>> page(@Validated ExpensePageDTO dto) {
		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(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<Expense> excelUtil = new ExcelUtil<>(Expense.class);
		excelUtil.exportExcel(response, list,"费用数据");

	}

	/**
	 * 新增 费用管理表
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@Operation(summary = "新增", description = "传入expense")
	public R save(@Valid @RequestBody ExpenseDTO dto) {
		Expense expense = expenseService.getOne(new LambdaQueryWrapper<Expense>()
				.eq(Expense::getFlightId,dto.getFlightId())
		);
		if (expense != null){
			expenseService.removeById(expense.getExpenseId());
		}
		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) {
		return R.status(expenseService.updateById(dto
				.setUpdateUser(getUserId()).setUpdateTime(new Date())));
	}

	// /**
	//  * 新增或修改 费用管理表
	//  */
	// @PostMapping("/submit")
	// @ApiOperationSupport(order = 6)
	// @Operation(summary = "新增或修改", description = "传入expense")
	// public R submit(@Valid @RequestBody ExpenseDTO expense) {
	// 	return R.status(expenseService.saveOrUpdate(expense));
	// }


	/**
	 * 删除 费用管理表
	 */
	@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(String.valueOf(reduce)));
		BigDecimal reduce1 = list.stream().map(l ->
						BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getSettlementAmount()) ?
								"0" : l.getSettlementAmount())))
				.reduce(BigDecimal.ZERO, BigDecimal::add);
		voList.add(new LabelAndValueNameVO().setName("已结算金额").setValue(String.valueOf(reduce1)));
		voList.add(new LabelAndValueNameVO().setName("剩余可支配金额")
				.setValue(String.valueOf(reduce.subtract(reduce1))));
		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;
	}
}
