package com.gci.boot.modules.basedata.controller;


import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gci.boot.modules.gis.entity.TbGisRunningbus;
import com.gci.boot.modules.gis.service.ITbGisRunningbusService;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
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 org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.alibaba.excel.EasyExcel;
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.gci.boot.annotation.Query.handle.QueryGenerator;
import com.gci.boot.annotation.permission.DataPermission;
import com.gci.boot.common.log.annotation.AddSysLog;
import com.gci.boot.common.util.DateUtils;
import com.gci.boot.common.util.MinioUtils;
import com.gci.boot.common.validated.SaveValidated;
import com.gci.boot.common.validated.UpdateValidated;
import com.gci.boot.common.vo.Result;
import com.gci.boot.constant.CommonConstant;
import com.gci.boot.enums.FileExtension;
import com.gci.boot.modules.basedata.entity.TbVehicle;
import com.gci.boot.modules.basedata.query.ProjectVehicleListQuery;
import com.gci.boot.modules.basedata.service.ITbVehicleService;
import com.gci.boot.modules.projects.service.IProjectVehicleBindLogService;
import com.gci.boot.modules.system.vo.LoginUser;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 2464
 * @since 2023-08-25
 */
@RestController
@RequestMapping("/base/vehicle")
public class TbVehicleController {
    @Autowired
    private ITbVehicleService iTbVehicleService;
    @Autowired
    private MinioUtils minioUtils;

    @Autowired
    private IProjectVehicleBindLogService projectVehicleBindLogService;
    @Autowired
    private ITbGisRunningbusService gisRunningbusService;

    /**
     * 分页列表查询
     *
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AddSysLog(value = "车辆管理-分页列表查询")
    @GetMapping(value = "/list")
    @DataPermission(item="tb_vehicle.projectId", sqlIds = {"com.gci.boot.modules.basedata.mapper.TbVehicleMapper.selectPage"})
    public Result<?> queryPageList(TbVehicle tbVehicle,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest req) {
        Page<TbVehicle> page = new Page<TbVehicle>(pageNo, pageSize);
        LambdaQueryWrapper<TbVehicle> lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbVehicle.class, tbVehicle);
        IPage<TbVehicle> pageList = iTbVehicleService.page(page, lambdaQueryWrapper);
        return Result.ok(pageList);
    }

    /**
     * 分页列表查询同项目和没有项目的车辆  排除作废的
     *
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AddSysLog(value = "车辆管理-分页列表查询同项目和没有项目的车辆,除作废的")
    @GetMapping(value = "/currentAndNoProjectVehicleList")
    public Result<?> currentAndNoProjectVehicleList(ProjectVehicleListQuery query,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        Page<TbVehicle> page = new Page<TbVehicle>(pageNo, pageSize);
        query.setProjectId(query.getProjectId()+",");
        LambdaQueryWrapper<TbVehicle> lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbVehicle.class, query);
        IPage<TbVehicle> pageList = iTbVehicleService.page(page, lambdaQueryWrapper);
        return Result.ok(pageList);
    }

    /**
     * 分页列表查询同项目的车辆  排除作废的
     *
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AddSysLog(value = "车辆管理-分页列表查询同项目的车辆,排除作废的")
    @GetMapping(value = "/currentProjectVehicleList")
    public Result<?> currentProjectVehicleList(@RequestParam(name = "projectId")String projectId,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        LambdaQueryWrapper<TbVehicle> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //理论上项目内没有禁用的车 以防万一加上条件
        lambdaQueryWrapper.eq(TbVehicle::getProjectId,projectId)
                .eq(TbVehicle::getCancelFlag, CommonConstant.DEL_FLAG_0);
        Page<TbVehicle> page = new Page<TbVehicle>(pageNo, pageSize);
        IPage<TbVehicle> pageList = iTbVehicleService.page(page, lambdaQueryWrapper);
        return Result.ok(pageList);
    }

    /**
     * 添加
     */
    @AddSysLog(value = "车辆管理-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody @Validated(SaveValidated.class) TbVehicle tbVehicle) {
        //是否需要记录绑定日志
        boolean needLog = false;
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //如果没有选择所属项目，则默认分配内置项目
        if(StrUtil.isBlank(tbVehicle.getProjectId())){
            tbVehicle.setProjectId(CommonConstant.INNER_PROJECT);
        }else{
            needLog = true;
        }
        iTbVehicleService.save(tbVehicle);
        if(needLog){
            projectVehicleBindLogService.addLog(tbVehicle.getProjectId(), null,tbVehicle.getPlateNumber(),1,1,sysUser.getUsername());
        }
        //更新runningBus项目id
        CompletableFuture.runAsync(() -> {
            gisRunningbusService.update(new LambdaUpdateWrapper<TbGisRunningbus>().eq(TbGisRunningbus::getPlateNumber,tbVehicle.getPlateNumber())
                    .set(TbGisRunningbus::getProjectId,tbVehicle.getProjectId()));
        });
        return Result.ok("添加成功！");
    }

    /**
     * 编辑
     */
    @AddSysLog(value = "车辆管理-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody @Validated(UpdateValidated.class) TbVehicle tbVehicle) {
        TbVehicle old =  iTbVehicleService.getById(tbVehicle.getId());

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //如果没有选择所属项目，则默认分配内置项目
        if(StrUtil.isBlank(tbVehicle.getProjectId())){
            tbVehicle.setProjectId(CommonConstant.INNER_PROJECT);
        }

        iTbVehicleService.updateById(tbVehicle);
        //如果不相等，则发生了修改。
        if(!tbVehicle.getProjectId().equals(old.getProjectId())){
            //添加解绑日志
            projectVehicleBindLogService.addLog(old.getProjectId(), null,tbVehicle.getPlateNumber(),2,1,sysUser.getUsername());
            //添加绑定日志
            projectVehicleBindLogService.addLog(tbVehicle.getProjectId(), null,tbVehicle.getPlateNumber(),1,1,sysUser.getUsername());
            //更新runningBus项目id
            CompletableFuture.runAsync(() -> {
                gisRunningbusService.update(new LambdaUpdateWrapper<TbGisRunningbus>().eq(TbGisRunningbus::getPlateNumber,tbVehicle.getPlateNumber())
                        .set(TbGisRunningbus::getProjectId,tbVehicle.getProjectId()));
            });
        }
        return Result.ok("编辑成功！");
    }

    /**
     * 删除
     */
    @AddSysLog(value = "车辆管理-删除")
//    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        iTbVehicleService.removeById(id);
        return Result.ok("删除成功！");
    }

    /**
     * 作废 校验
     */
    @AddSysLog(value = "车辆管理-作废-校验")
    @DeleteMapping(value = "/cancelValid")
    public Result<?> cancelValid(@RequestParam(name = "id", required = true) String id) {
        return iTbVehicleService.cancelValid(id);
    }

    /**
     * 作废
     */
    @AddSysLog(value = "车辆管理-作废")
    @DeleteMapping(value = "/cancel")
    public Result<?> cancel(@RequestParam(name = "id", required = true) String id) {
        iTbVehicleService.cancel(id);
        return Result.ok("作废成功！");
    }

    /**
     * 恢复
     */
    @AddSysLog(value = "车辆管理-恢复")
    @DeleteMapping(value = "/unCancel")
    public Result<?> unCancel(@RequestParam(name = "id", required = true) String id) {
        iTbVehicleService.unCancel(id);
        return Result.ok("恢复成功！");
    }

    /**
     * 批量删除
     */
    @AddSysLog(value = "车辆管理-批量删除")
//    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        iTbVehicleService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.ok("批量删除成功！");
    }

    /**
     * 文件上传
     */
    @AddSysLog(value = "车辆管理-文件上传")
    @PostMapping("/upload")
    public Result<?> upload(HttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        if (ObjectUtil.isEmpty(file)) {
            return Result.error("请正确上传文件！");
        }
        return Result.ok(minioUtils.uploadFileValid(file, FileExtension.PIC.getNameList()));
    }

    /**
     * 导出
     * @return
     */
    @AddSysLog(value = "车辆管理-导出")
    @GetMapping("/export")
    @DataPermission(item="tb_vehicle.projectId", sqlIds = {"com.gci.boot.modules.basedata.mapper.TbVehicleMapper.selectList"})
    public Result<?> export(TbVehicle tbVehicle,HttpServletResponse response){
        try (OutputStream output = response.getOutputStream()){

            String fileName = "车辆档案.xlsx";
            try {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName);

            LambdaQueryWrapper<TbVehicle> lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbVehicle.class, tbVehicle);
            List<TbVehicle> list = iTbVehicleService.list(lambdaQueryWrapper);
            EasyExcel.write(output, TbVehicle.class).sheet("sheet1").doWrite(list);

        } catch (IOException e) {
            return Result.error("导出错误！");
        }
        return Result.ok();
    }

    /**
     * 项目待添加车辆列表
     * 查询当前项目或未绑定项目的车辆
     *
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AddSysLog(value = "车辆管理-查询当前项目或未绑定项目的车辆")
    @GetMapping(value = "/vehiclePage")
    public Result<?> vehiclePage(TbVehicle tbVehicle,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest req) {
        Page<TbVehicle> page = new Page<TbVehicle>(pageNo, pageSize);
        LambdaQueryWrapper<TbVehicle> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.and(w->w.eq(TbVehicle::getProjectId, tbVehicle.getProjectId()).or().eq(TbVehicle::getProjectId,CommonConstant.INNER_PROJECT).or().eq(TbVehicle::getProjectId, "").or().isNull(TbVehicle::getProjectId));
        lambdaQueryWrapper.eq(TbVehicle::getCancelFlag, CommonConstant.DEL_FLAG_0);
        lambdaQueryWrapper.eq(StringUtils.hasLength(tbVehicle.getVehicleType()), TbVehicle::getVehicleType,tbVehicle.getVehicleType());
        lambdaQueryWrapper.like(StringUtils.hasLength(tbVehicle.getPlateNumber()),TbVehicle::getPlateNumber, tbVehicle.getPlateNumber());
        lambdaQueryWrapper.like(StringUtils.hasLength(tbVehicle.getFrameNumber()),TbVehicle::getFrameNumber, tbVehicle.getFrameNumber());
        lambdaQueryWrapper.between(tbVehicle.getDeliveryTimeStart()!=null, TbVehicle::getDeliveryTime, tbVehicle.getDeliveryTimeStart(), tbVehicle.getDeliveryTimeEnd());
        lambdaQueryWrapper.orderByAsc(TbVehicle::getProjectId);
        lambdaQueryWrapper.orderByDesc(TbVehicle::getPlateNumber);
        IPage<TbVehicle> pageList = iTbVehicleService.page(page, lambdaQueryWrapper);
        return Result.ok(pageList);
    }

    @AddSysLog(value = "车辆管理-查询保险期内的车辆")
    @GetMapping(value = "/validPage")
    public Result<?> validPage(TbVehicle tbVehicle,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest req) {
    	List<String> projectIds = new ArrayList<>();
    	if(StringUtils.hasLength(tbVehicle.getProjectId())) {
    		projectIds.add(tbVehicle.getProjectId());
    		projectIds.add(CommonConstant.INNER_PROJECT);
    		projectIds.add("");
    	}
    	tbVehicle.setProjectId(null);
        Page<TbVehicle> page = new Page<TbVehicle>(pageNo, pageSize);
        LambdaQueryWrapper<TbVehicle> lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbVehicle.class, tbVehicle);
        lambdaQueryWrapper.eq(TbVehicle::getCancelFlag, CommonConstant.DEL_FLAG_0);
        lambdaQueryWrapper.in(projectIds.size()>0, TbVehicle::getProjectId, projectIds);
/*        String sql = "select DISTINCT vehicle_id from tb_insurance t where t.compulsory_valid_time >= '"+DateUtils.formatDate(new Date())+"'";
        lambdaQueryWrapper.inSql(TbVehicle::getId,sql);*/
        lambdaQueryWrapper.orderByAsc(TbVehicle::getPlateNumber);
        IPage<TbVehicle> pageList = iTbVehicleService.page(page, lambdaQueryWrapper);
        return Result.ok(pageList);
    }

}
