package com.yeejoin.precontrol.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Collectors;

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

import com.yeejoin.precontrol.common.entity.*;
import com.yeejoin.precontrol.common.enums.OpsLogEnum;
import com.yeejoin.precontrol.common.service.*;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yeejoin.precontrol.common.annotations.OpsLog;
import com.yeejoin.precontrol.common.component.SpringContextHolder;
import com.yeejoin.precontrol.common.constant.Constant;
import com.yeejoin.precontrol.common.dto.CommonPageableDto;
import com.yeejoin.precontrol.common.dto.ProjectDto;
import com.yeejoin.precontrol.common.event.RegionAddEvent;
import com.yeejoin.precontrol.common.exception.BaseException;
import com.yeejoin.precontrol.common.mapper.PersonAscriptionMapper;
import com.yeejoin.precontrol.common.publish.TranslateEventPublish;
import com.yeejoin.precontrol.common.utils.FileHelper;
import com.yeejoin.precontrol.common.utils.PlatformUtils;
import com.yeejoin.precontrol.common.utils.StringUtil;
import com.yeejoin.precontrol.common.vo.BadProjectVo;
import com.yeejoin.precontrol.common.vo.ProjectVo;
import com.yeejoin.precontrol.common.vo.ReginParams;
import com.yeejoin.precontrol.controller.publics.BaseController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;

/**
 * 项目信息
 *
 * @author duanwei
 * @date 2020-06-30
 */
@RestController
@Api(tags = "项目信息Api")
@RequestMapping(value = "/project", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Slf4j
public class ProjectController extends BaseController {
	/**
	 * 工程服务
	 */
	@Autowired
	IProjectService iProjectService;
	/**
	 * 二维码服务
	 */
	@Autowired
	IProjectQrcodeService iProjectQrcodeService;
	/**
	 * 项目坐标信息服务
	 */
	@Autowired
	IProjectCoordinateService iProjectCoordinateService;
	/**
	 * 关系表mapper
	 */
	@Autowired
	PersonAscriptionMapper personAscriptionMapper;
	/**
	 * 地区服务
	 */
	@Autowired
	IDistrictsService iDistrictsService;
	/**
	 * 人员关系表服务
	 */
	@Autowired
	IPersonAscriptionService iPersonAscriptionService;

	/**
	 * 人员服务
	 */
	@Autowired
	IPersonService iPersonService;

	/**
	 * 翻译事件服务
	 */
	@Autowired
	TranslateEventPublish translateEventPublish;

	@Autowired
	PlatformUtils platformUtils;

	@Autowired
	IProjectCompanyService iProjectCompanyService;

	@Autowired
	IProjectDeviceService iProjectDeviceService;

	@Autowired
	IStatisticsService statisticsService;
	@Autowired
	IProjectCameraService projectCameraService;
	@Autowired
	ITaskPersonService iTaskPersonService;
	@Autowired
	ITaskService iTaskService;

	/**
	 * 新增项目信息
	 *
	 * @return
	 */
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	@ApiOperation(httpMethod = "POST", value = "新增项目信息", notes = "新增项目信息")
	public boolean saveProject(@RequestBody ProjectDto project) {
		if (project.getName().equals(project.getProjectNum())) {
			throw new BaseException("项目名称和项目编号不能重复！");
		}
		List<Project> list = iProjectService.list(new QueryWrapper<Project>().lambda()
				.eq(Project::getName, project.getName()).or().eq(Project::getProjectNum, project.getProjectNum()));
		if (StringUtil.isNotEmpty(list)) {
			throw new BaseException("项目名称或项目编号已经存在！");
		}
		List<Project> projects = iProjectService
				.list(new QueryWrapper<Project>().lambda().eq(Project::getProjectRegion, project.getProjectRegion()));
		if (CollectionUtils.isNotEmpty(projects)) {
			throw new BaseException("该区域已关联项目！");
		}
		// 地图终点
		project.setPointType("endmost");
		project.setJobNum(0L);
		iProjectService.saveProject(project);
		// 保存项目的时候发布事件同步海康平台区域
		SpringContextHolder.publishEvent(new RegionAddEvent(this, project));
		if (CollectionUtils.isNotEmpty(project.getCameraList())) {
			projectCameraService.saveBatch(project.getCameraList());
		}
		List<ProjectCompany> companyList = project.getProjectCompanyList();
		if (StringUtil.isNotEmpty(companyList)) {
			companyList.forEach(item -> item.setProjectId(project.getId()));
			iProjectCompanyService.saveBatch(companyList);
		}

		List<ProjectDevice> deviceList = project.getProjectDeviceList();
		if (StringUtil.isNotEmpty(deviceList)) {
			List<String> numbers = deviceList.stream().map(ProjectDevice::getNumber).collect(Collectors.toList());
			List<ProjectDevice> dList = iProjectDeviceService
					.list(new LambdaQueryWrapper<ProjectDevice>().in(ProjectDevice::getNumber, numbers));
			if (dList.size() > 0) {
				StringBuffer sb = new StringBuffer();
				dList.forEach(i -> sb.append(i.getNumber()).append(","));
				throw new BaseException(sb + "设备编号已经存在！");
			}
			deviceList.forEach(item -> item.setProjectId(project.getId()));
			iProjectDeviceService.saveBatch(deviceList);
		}

		Project project1 = new Project();
		BeanUtils.copyProperties(project, project1, "id");
		translateEventPublish.publish(project1);

		// 更新推送
		List<String> status = new ArrayList<String>(Arrays.asList("开发", "在建", "策划"));
		if (status.contains(project.getStatus())) {
			statisticsService.initWs(project.getOrgCode(), Constant.WS_COMPOSITESUM);
			statisticsService.initWs(project.getOrgCode(), Constant.WS_MAPPROJECTSUM);
		}

		return true;
	}

	/**
	 * 根据id删除
	 *
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
	@ApiOperation(httpMethod = "DELETE", value = "根据id删除", notes = "根据id删除")
	public boolean deleteById(HttpServletRequest request, @PathVariable Long id) {
		return iProjectService.removeById(id);
	}

	/**
	 * 根据ids删除
	 *
	 * @param ids
	 * @return
	 */
	@RequestMapping(value = "/ids/{ids}", method = RequestMethod.DELETE)
	@ApiOperation(httpMethod = "DELETE", value = "根据ids删除", notes = "根据ids删除")
	@OpsLog(value=OpsLogEnum.DELETE_PROJECT)
	public boolean deleteByIds(HttpServletRequest request, @PathVariable List<Long> ids) {
		return iProjectService.removeByIds(ids);
	}

	/**
	 * 区域是否已经关联其他项目 TRUE 未关联 FALSE 已关联
	 * 
	 * @param region
	 * @return
	 */
	@GetMapping("/checkProjectRegion/{region}")
	public Boolean checkProjectRegion(@PathVariable String region) {
		List<Project> projects = iProjectService
				.list(new QueryWrapper<Project>().lambda().eq(Project::getProjectRegion, region));
		return CollectionUtils.isNotEmpty(projects) ? Boolean.FALSE : Boolean.TRUE;
	}

	/**
	 * 修改项目信息
	 *
	 * @return
	 */
	@RequestMapping(value = "/updateById", method = RequestMethod.PUT)
	@ApiOperation(httpMethod = "PUT", value = "修改项目信息", notes = "修改项目信息")
	@OpsLog(value=OpsLogEnum.EDIT_PROJECT)
	public boolean updateByIdProject(@RequestBody ProjectDto project) {
		if (project.getName().equals(project.getProjectNum())) {
			throw new BaseException("项目名称和项目编号不能重复！");
		}
		List<Project> list = iProjectService.list(new QueryWrapper<Project>().lambda()
				.eq(Project::getName, project.getName()).or().eq(Project::getProjectNum, project.getProjectNum()));
		if (StringUtil.isNotEmpty(list)) {
			if (!list.get(0).getId().equals(project.getId())) {
				throw new BaseException("项目名称或项目编号已经存在！");
			}
		}
		List<Project> projects = iProjectService
				.list(new QueryWrapper<Project>().lambda().eq(Project::getProjectRegion, project.getProjectRegion()));
		projects.removeIf(item -> item.getId().equals(project.getId()));
		if (CollectionUtils.isNotEmpty(projects)) {
			throw new BaseException("该区域已关联项目！");
		}
		// 设置一下项目的未交底次数
		Project resultProject = iProjectService.getById(project.getId());
		project.setPointType("endmost");
		project.setJobNum(resultProject.getJobNum());
		iProjectService.updateById(project);
		
		//更新区域
		if(project.getProjectRegion()==null) 
		{
			iProjectService.update(new LambdaUpdateWrapper<Project>().set(Project::getProjectRegion, null).eq(Project::getId, project.getId()));
		}

		List<ProjectCompany> companyList = project.getProjectCompanyList();
		if (StringUtil.isNotEmpty(companyList)) {
			companyList.forEach(item -> item.setProjectId(project.getId()));
			iProjectCompanyService.saveOrUpdateBatch(companyList);
		}

		List<ProjectDevice> deviceList = project.getProjectDeviceList();
		if (StringUtil.isNotEmpty(deviceList)) {
			List<String> numbers = deviceList.stream().map(ProjectDevice::getNumber).collect(Collectors.toList());
			iProjectDeviceService
					.remove(new LambdaQueryWrapper<ProjectDevice>().eq(ProjectDevice::getProjectId, project.getId()));
			List<ProjectDevice> dList = iProjectDeviceService
					.list(new LambdaQueryWrapper<ProjectDevice>().in(ProjectDevice::getNumber, numbers));
			if (dList.size() > 0) {
				StringBuffer sb = new StringBuffer();
				dList.forEach(i -> sb.append(i.getNumber()).append(","));
				throw new BaseException(sb + "设备编号已经存在！");
			}
			deviceList.forEach(item -> item.setProjectId(project.getId()));
			iProjectDeviceService.saveBatch(deviceList);
		}

		Project project1 = new Project();
		BeanUtils.copyProperties(project, project1, "id");
		translateEventPublish.publish(project1);
		if (CollectionUtils.isNotEmpty(project.getCameraList())
				&& !resultProject.getProjectRegion().equals(project.getProjectRegion())) {
			projectCameraService.saveBatch(project.getCameraList());
		}

		statisticsService.initWs(resultProject.getOrgCode(), Constant.WS_COMPOSITESUM);
		statisticsService.initWs(resultProject.getOrgCode(), Constant.WS_MAPPROJECTSUM);
		return true;
	}

	/**
	 * 根据id查询
	 *
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "根据id查询", notes = "根据id查询")
	public Object selectById(HttpServletRequest request, @PathVariable Long id) {
		ReginParams reginParams = getReginInfo();
		Long companyId = null;
		if (this.isFbsRole(reginParams)) {
			companyId = this.getCompanyId(reginParams);
		}
		return iProjectService.selectById(id, companyId);
	}

	/**
	 * 列表分页查询
	 *
	 * @return
	 */
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "列表分页查询", notes = "列表分页查询")
	public Object listPage(@ApiParam(value = "分页条件 isAll=0 具体分页必传") CommonPageableDto pageable,
			@ApiParam(value = "查询参数") ProjectDto projectDto,
			@ApiParam(value = "查询Ids") @RequestParam(required = false) List<Long> ids,
			@ApiParam(value = "类型 0查询列表 1 导出列表") @RequestParam Long operType, HttpServletResponse response)
			throws UnsupportedEncodingException {
		String fileName = java.net.URLEncoder.encode("工程信息表", "UTF-8") + ".xls";
		if (null != ids && ids.size() > 0) {
			projectDto.setProjectIds(ids);
		}
		if (projectDto.getProjectId() != null) {
			projectDto.setId(projectDto.getProjectId());
		}
		// getUserInfo();
		ReginParams reginInfo = getReginInfo();
		if (isFbsRole(reginInfo)) {
			Company company = reginInfo.getCompany();
			if (company != null) {
				Long companyId = company.getId();
				projectDto.setCompanyId(companyId);
			}
			String roleName = null;
			if (reginInfo.getRole() != null) {
				roleName = reginInfo.getRole().getRoleName();
			}
			if (!roleName.contains("fbs_admin")) {
				PersonAscription ascription = iPersonAscriptionService.getOne(new LambdaQueryWrapper<PersonAscription>()
						.eq(PersonAscription::getPersonId, reginInfo.getPerson().getId()));
				projectDto.setProjectIds(Arrays.asList(ascription.getProjectId()));
			}
		}
		IPage<ProjectVo> page = iProjectService.listByPage(pageable, projectDto);
		if (operType == 1) {
			List<ProjectVo> excelList = page.getRecords();
			for (ProjectVo vo : excelList) {
				if (null != vo.getOrgCode()) {
					vo.setPlatformProjectName(platformUtils.getDepartmentNameByOrgCode(vo.getOrgCode()));
				}
			}
			FileHelper.exportExcel(excelList, "工程信息", "工程信息", ProjectVo.class, fileName, response);
			return null;
		} else {
			return page;
		}
	}

	/**
	 * 导入工程信息
	 *
	 * @return
	 */
	@RequestMapping(value = "/import", method = RequestMethod.POST)
	@ApiOperation(httpMethod = "POST", value = "导入工程信息", notes = "导入工程信息")
	public Object projectImport(
			@ApiParam(value = "导入数据文件", required = true) @RequestBody(required = true) MultipartFile file,
			HttpServletResponse response) throws Exception {
		String fileName = file.getOriginalFilename();
		if (!fileName.endsWith(".xls")) {
			throw new BaseException("文件格式错误");
		}
		List<Project> data = iProjectService.projectImport(file);
		return iProjectService.saveProjectImportData(data);
	}

	/**
	 * 项目列表下拉框
	 *
	 * @return
	 */
	@RequestMapping(value = "/select", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "项目列表下拉框", notes = "项目列表下拉框")
	public List<HashMap<String, Object>> projectSelect() {
		return iProjectService.projectSelect();
	}

	/**
	 * 监控屏地图连线
	 *
	 * @return
	 */
	@RequestMapping(value = "/mapLine", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "监控屏地图连线", notes = "监控屏地图连线")
	public Object mapLine() throws IOException {
		String orgCode = platformUtils.getOrgCode();
		return iProjectService.getMapLine(orgCode, null);
	}

	/**
	 * 首页违章项目
	 *
	 * @return
	 */
	@RequestMapping(value = "/badProject", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "首页违章项目", notes = "首页违章项目")
	public Object badProject(@ApiParam(value = "是否查询所有违章和0违章", required = false) boolean isAllStatus,
			@ApiParam(value = "是否0违章", required = true) boolean isBad,
			@ApiParam(value = "分页") CommonPageableDto pageable, @ApiParam(value = "查询参数") BadProjectVo badProjectVo,
			@ApiParam(value = "类型 0查询列表 1 导出列表") @RequestParam Long operType, HttpServletResponse response) {
		String fileName = UUID.randomUUID().toString() + ".xls";
		String title = isAllStatus ? "在建工程信息" : isBad ? "违章工程信息" : "0违章工程信息";
		badProjectVo.setOrgCode(platformUtils.getOrgCode());
		IPage<BadProjectVo> page = iProjectService.pageBadProject(isBad, isAllStatus, pageable, badProjectVo);
		if (operType == 1) {
			List<BadProjectVo> excelList = page.getRecords();
			FileHelper.exportExcel(excelList, title, title, BadProjectVo.class, fileName, response);
			return null;
		} else {
			return page;
		}
	}

	/**
	 * 首页违章项目
	 *
	 * @return
	 */
	@RequestMapping(value = "/name", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "项目名称", notes = "项目名称")
	public String name(@ApiParam(value = "项目id", required = true) Long projectId) {
		Project project = iProjectService.getById(projectId);
		return project == null ? null : project.getName();
	}

	/**
	 * 查询所有项目列表
	 *
	 * @return
	 */
	@RequestMapping(value = "/all/list", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "查询所有项目列表", notes = "查询所有项目列表")
	public List<Project> listAll() {
		return iProjectService.list();
	}

	/**
	 * 获取该用户拥有的项目列表
	 * 
	 * @return
	 */
	@RequestMapping(value = "/orgcode", method = RequestMethod.GET)
	@ApiOperation(httpMethod = "GET", value = "获取该用户拥有的项目列表", notes = "获取该用户拥有的项目列表")
	public List<Map> listByOrgcode() {
		List<Map> listRet = new ArrayList<Map>();
		List<Project> list = iProjectService.list();
		String personOrgCode = getPerson().getOrgCode();
		if (list != null && list.size() > 0) {
			for (Project project : list) {
				String projectOrgCod = project.getOrgCode();
				Map map = new HashMap();
				map.put("id", project.getId());
				map.put("name", project.getName());
				if (personOrgCode == null) {
					listRet.add(map);
				} else if (projectOrgCod != null && personOrgCode.contains(projectOrgCod)) {
					listRet.add(map);
				}
			}
		}
		return listRet;
	}

	/**
	 * 删除项目分包商
	 *
	 * @return
	 */
	@RequestMapping(value = "/company/{id}", method = RequestMethod.DELETE)
	@ApiOperation(httpMethod = "DELETE", value = "删除项目分包商", notes = " 删除项目分包商")
	public boolean deleteCompany(@PathVariable Long id) {
		ProjectCompany projectCompany = iProjectCompanyService.getById(id);
		if(projectCompany==null) {
	    	return false;
		}
		List<Task> list = iTaskService
				.list(new LambdaQueryWrapper<Task>().eq(Task::getProjectId, projectCompany.getProjectId()));
		Set<Long> ids = list.stream().map(i -> i.getId()).collect(Collectors.toSet());
		int count = iTaskPersonService.count(new LambdaQueryWrapper<TaskPerson>()
				.eq(TaskPerson::getCompanyId, projectCompany.getCompanyId()).in(TaskPerson::getTaskId, ids));
		if (count > 0) {
			throw new BaseException("分包商已关联任务,无法删除");
		}
		iProjectCompanyService.removeById(id);
		return true;
	}
}
