package com.yc.ship.module.product.controller.admin.voyage;

import com.yc.ship.framework.apilog.core.annotation.ApiAccessLog;
import com.yc.ship.framework.common.pojo.CommonResult;
import com.yc.ship.framework.common.pojo.PageParam;
import com.yc.ship.framework.common.pojo.PageResult;
import com.yc.ship.framework.common.util.collection.CollectionUtils;
import com.yc.ship.framework.common.util.collection.MapUtils;
import com.yc.ship.framework.common.util.object.BeanUtils;
import com.yc.ship.framework.excel.core.util.ExcelUtils;
import com.yc.ship.module.product.controller.admin.voyage.vo.*;
import com.yc.ship.module.product.dal.dataobject.voyage.VoyageDO;
import com.yc.ship.module.product.service.voyage.VoyageService;
import com.yc.ship.module.resource.api.route.RouteApi;
import com.yc.ship.module.resource.api.route.dto.RouteRespDTO;
import com.yc.ship.module.resource.dal.dataobject.route.ResourceRouteDO;
import com.yc.ship.module.resource.dal.dataobject.ship.ResourceShipDO;
import com.yc.ship.module.resource.service.route.ResourceRouteService;
import com.yc.ship.module.resource.service.ship.ResourceShipService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.yc.ship.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.yc.ship.framework.common.pojo.CommonResult.success;

/**
 * @author qsl
 */
@Tag(name = "管理后台 - 航次管理")
@RestController
@RequestMapping("/product/voyage")
@Validated
public class VoyageController {

    @Resource
    private VoyageService voyageService;

    @Resource
    private ResourceShipService shipService;

    @Resource
    private ResourceRouteService routeService;

    @Resource
    private RouteApi routeApi;

    @PostMapping("/create")
    @Operation(summary = "创建航次管理")
    @PreAuthorize("@ss.hasPermission('product:voyage:create')")
    public CommonResult<Long> createVoyage(@Valid @RequestBody VoyageSaveReqVO createReqVO) {
        return success(voyageService.createVoyage(createReqVO));
    }

    @PostMapping("/create-batch")
    @Operation(summary = "批量创建航次管理")
    @PreAuthorize("@ss.hasPermission('product:voyage:batchCreate')")
    public CommonResult<Boolean> createVoyageBatch(@Valid @RequestBody VoyageSaveBatchReqVO createReqVO) {
        voyageService.createVoyageBatch(createReqVO);
        return success(true);
    }

    @PutMapping("/update")
    @Operation(summary = "更新航次管理")
    @PreAuthorize("@ss.hasPermission('product:voyage:update')")
    public CommonResult<Boolean> updateVoyage(@Valid @RequestBody VoyageSaveReqVO updateReqVO) {
        voyageService.updateVoyage(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除航次管理")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('product:voyage:delete')")
    public CommonResult<Boolean> deleteVoyage(@RequestParam("id") Long id) {
        voyageService.deleteVoyage(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得航次管理")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('product:voyage:query')")
    public CommonResult<VoyageRespVO> getVoyage(@RequestParam("id") Long id) {
        VoyageDO voyage = voyageService.getVoyage(id);
        return success(BeanUtils.toBean(voyage, VoyageRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得航次管理分页")
    @PreAuthorize("@ss.hasPermission('product:voyage:query')")
    public CommonResult<PageResult<VoyageRespVO>> getVoyagePage(@Valid VoyagePageReqVO pageReqVO) {
        PageResult<VoyageDO> pageResult = voyageService.getVoyagePage(pageReqVO);
        PageResult<VoyageRespVO> page = BeanUtils.toBean(pageResult, VoyageRespVO.class);
        List<VoyageRespVO> list = page.getList();

        // 批量查询预定人数
        List<Long> voyageIds = CollectionUtils.convertList(list, VoyageRespVO::getId);
        Map<Long, Integer> bookingCountMap = new HashMap<>();;
        if (!voyageIds.isEmpty()) {
            bookingCountMap = voyageService.countBatchByVoyageIds(voyageIds).stream()
                    .collect(Collectors.toMap(
                            countMap -> (Long) countMap.get("voyageId"),
                            countMap -> countMap.get("count") != null ? ((Number) countMap.get("count")).intValue() : 0
                    ));
        }

        List<Long> shipIds = CollectionUtils.convertList(list, VoyageRespVO::getShipId);
        List<ResourceShipDO> shipList = shipService.getList(shipIds);
        Map<Long, ResourceShipDO> shipDoMap = CollectionUtils.convertMap(shipList, ResourceShipDO::getId);

        List<Long> routeIds = CollectionUtils.convertList(list, VoyageRespVO::getRouteId);
        List<ResourceRouteDO> routeList = routeService.getList(routeIds);
        Map<Long, ResourceRouteDO> routeDoMap = CollectionUtils.convertMap(routeList, ResourceRouteDO::getId);
        Map<Long, Integer> finalBookingCountMap = bookingCountMap;
        list.forEach(item -> {
            MapUtils.findAndThen(shipDoMap, item.getShipId(), shipDO -> item.setShipName(shipDO.getName()));
            MapUtils.findAndThen(routeDoMap, item.getRouteId(), routeDO -> item.setRouteName(routeDO.getName()));

            // 从批量查询的 Map 中获取预定人数
            item.setBookingCount(finalBookingCountMap.getOrDefault(item.getId(), 0));
        });
        return success(page);
    }

    @GetMapping("/list-simple")
    @Operation(summary = "获得资源管理-航次列表")
    public CommonResult<List<VoyageRespVO>> getVoyageListSimple(VoyageReqVO reqVO) {
        List<VoyageDO> list = voyageService.getListSimple(reqVO);
        List<VoyageRespVO> voyageRespVOS = BeanUtils.toBean(list, VoyageRespVO.class);
        List<Long> routeIds = CollectionUtils.convertList(voyageRespVOS, VoyageRespVO::getRouteId);
        List<ResourceRouteDO> routeList = routeService.getList(routeIds);
        Map<Long, Integer> routeDoMap = CollectionUtils.convertMap(routeList, ResourceRouteDO::getId, ResourceRouteDO::getDirection);
        voyageRespVOS.stream().forEach(voyageRespVO -> {
            MapUtils.findAndThen(routeDoMap, voyageRespVO.getRouteId(), direction -> voyageRespVO.setDirection(direction));
            if(routeDoMap.get(voyageRespVO.getRouteId()) == 2) {
                voyageRespVO.setFname(voyageRespVO.getName()+"-下水");
            }else {
                voyageRespVO.setFname(voyageRespVO.getName()+"-上水");
            }
        });
        return success(voyageRespVOS);
    }

    @GetMapping("/listByShipId")
    @Operation(summary = "获得资源管理-航次列表")
    public CommonResult<List<VoyageRespVO>> listByShipId(Long shipId) {
        List<VoyageDO> list = voyageService.getListByShipId(shipId);
        List<VoyageRespVO> voyageRespVOS = BeanUtils.toBean(list, VoyageRespVO.class);
        List<Long> routeIds = CollectionUtils.convertList(voyageRespVOS, VoyageRespVO::getRouteId);
        List<ResourceRouteDO> routeList = routeService.getList(routeIds);
        Map<Long, Integer> routeDoMap = CollectionUtils.convertMap(routeList, ResourceRouteDO::getId, ResourceRouteDO::getDirection);
        voyageRespVOS.stream().forEach(voyageRespVO -> {
            MapUtils.findAndThen(routeDoMap, voyageRespVO.getRouteId(), direction -> voyageRespVO.setDirection(direction));
            if(routeDoMap.get(voyageRespVO.getRouteId()) == 2) {
                voyageRespVO.setFname(voyageRespVO.getName()+"-下水");
            }else {
                voyageRespVO.setFname(voyageRespVO.getName()+"-上水");
            }
        });
        return success(voyageRespVOS);
    }

    @GetMapping("/list-calendar")
    @Operation(summary = "获得资源管理-航次列表-日历")
    public CommonResult<List<VoyageRespVO>> getVoyageListCalendar(VoyageCalendarReqVO reqVO) {
        List<VoyageDO> list = voyageService.getListCalendar(reqVO);
        List<VoyageRespVO> voyageRespList = BeanUtils.toBean(list, VoyageRespVO.class);

        List<Long> shipIds = CollectionUtils.convertList(voyageRespList, VoyageRespVO::getShipId);
        List<ResourceShipDO> shipList = shipService.getList(shipIds);
        Map<Long, ResourceShipDO> shipMap = CollectionUtils.convertMap(shipList, ResourceShipDO::getId);

        List<Long> routeIds = CollectionUtils.convertList(voyageRespList, VoyageRespVO::getRouteId);
        Map<Long, RouteRespDTO> longRouteRespMap = routeApi.queryRoute(routeIds);
        voyageRespList.forEach(item -> {
            MapUtils.findAndThen(shipMap, item.getShipId(), shipDO -> item.setShipName(shipDO.getName()));
            MapUtils.findAndThen(shipMap, item.getShipId(), shipDO -> item.setShortShipName(shipDO.getShortName()));
            MapUtils.findAndThen(longRouteRespMap, item.getRouteId(), routeRespDTO -> {
                item.setRouteResp(routeRespDTO);
                item.setRouteName(routeRespDTO.getName());
            });
        });
        return success(voyageRespList);
    }

    //根据游轮ID获取上架的航次列表
    @GetMapping("/on-shelf-list-by-ship-id")
    @Operation(summary = "根据游轮ID获取上架的航次列表,给旅行社下单时调用")
    public CommonResult<List<VoyageRespVO>> getOnShelfListByShipId(@RequestParam("shipId") Long shipId) {
        List<VoyageDO> list = voyageService.getOnShelfListByShipId(shipId);
        List<VoyageRespVO> res = BeanUtils.toBean(list, VoyageRespVO.class);
        res.forEach(item -> {
            if(item.getDirection()==2){
                item.setFname(item.getName()+"-下水");
            }else{
                item.setFname(item.getName()+"-上水");
            }
        });
        return success(res);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出航次管理 Excel")
    @PreAuthorize("@ss.hasPermission('product:voyage:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportVoyageExcel(@Valid VoyagePageReqVO pageReqVO,
                                  HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<VoyageDO> list = voyageService.getVoyagePage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "航次管理.xls", "数据", VoyageRespVO.class,
                BeanUtils.toBean(list, VoyageRespVO.class));
    }


    @PutMapping("/update-lock")
    @Operation(summary = "锁定或解锁航次管理")
    @PreAuthorize("@ss.hasPermission('product:voyage:update-lock')")
    public CommonResult<Boolean> updateLockVoyage(String id) {
        voyageService.updateLockVoyage(id);
        return success(true);
    }
}