package cn.iocoder.yudao.module.pms.controller.admin.qhse.soc;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.net.URLEncodeUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.pms.controller.admin.qhse.soc.vo.IotSocSummaryPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.qhse.soc.vo.IotSocSummaryRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.qhse.soc.vo.IotSocSummarySaveReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.qhse.soc.IotSocSourceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.qhse.soc.IotSocSummaryDO;
import cn.iocoder.yudao.module.pms.dal.mysql.qhse.soc.IotSocSourceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.qhse.soc.IotSocSummaryMapper;
import cn.iocoder.yudao.module.pms.service.qhse.soc.IotSocSourceService;
import cn.iocoder.yudao.module.pms.service.qhse.soc.IotSocSummaryService;
import cn.iocoder.yudao.module.pms.util.SafetyObservationCardGenerator;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import liquibase.repackaged.org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;


@Tag(name = "管理后台 - SOC卡汇总")
@RestController
@RequestMapping("/rq/iot-soc-summary")
@Validated
public class IotSocSummaryController {

    @Resource
    private IotSocSummaryService iotSocSummaryService;
    @Autowired
    private IotSocSourceMapper iotSocSourceMapper;
    @Autowired
    private IotSocSummaryMapper iotSocSummaryMapper;
    @Autowired
    private DeptService deptService;
    @Autowired
    private IotSocSourceService iotSocSourceService;

    @PostMapping("/create")
    @Operation(summary = "创建SOC卡汇总")
    @PreAuthorize("@ss.hasPermission('rq:iot-soc-summary:create')")
    public CommonResult<Long> createIotSocSummary(@Valid @RequestBody IotSocSummarySaveReqVO createReqVO) {
        return success(iotSocSummaryService.createIotSocSummary(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新SOC卡汇总")
    @PreAuthorize("@ss.hasPermission('rq:iot-soc-summary:update')")
    public CommonResult<Boolean> updateIotSocSummary(@Valid @RequestBody IotSocSummarySaveReqVO updateReqVO) {
        iotSocSummaryService.updateIotSocSummary(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除SOC卡汇总")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('rq:iot-soc-summary:delete')")
    public CommonResult<Boolean> deleteIotSocSummary(@RequestParam("id") Long id) {
        iotSocSummaryService.deleteIotSocSummary(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得SOC卡汇总")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('rq:iot-soc-summary:query')")
    public CommonResult<IotSocSummaryRespVO> getIotSocSummary(@RequestParam("id") Long id) {
        IotSocSummaryDO iotSocSummary = iotSocSummaryService.getIotSocSummary(id);
        return success(BeanUtils.toBean(iotSocSummary, IotSocSummaryRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得SOC卡汇总分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-soc-summary:query')")
    public CommonResult<PageResult<IotSocSummaryRespVO>> getIotSocSummaryPage(@Valid IotSocSummaryPageReqVO pageReqVO) {
        PageResult<IotSocSummaryDO> pageResult = iotSocSummaryService.getIotSocSummaryPage(pageReqVO);
        List<IotSocSummaryRespVO> collect = pageResult.getList().stream().map(e -> {
            IotSocSummaryRespVO iotSocSummaryRespVO = new IotSocSummaryRespVO();
            BeanUtils.copyProperties(e, iotSocSummaryRespVO);
            iotSocSummaryRespVO.setSocClasses(Arrays.asList(e.getSocClass().split(",")));
            return iotSocSummaryRespVO;
        }).collect(Collectors.toList());
        return success(new PageResult<>(collect, pageResult.getTotal()));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出SOC卡汇总 Excel")
    @PreAuthorize("@ss.hasPermission('rq:iot-soc-summary:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportIotSocSummaryExcel(@Valid IotSocSummaryPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<IotSocSummaryDO> list = iotSocSummaryService.getIotSocSummaryPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "SOC卡汇总.xls", "数据", IotSocSummaryRespVO.class,
                        BeanUtils.toBean(list, IotSocSummaryRespVO.class));
    }

    @GetMapping("/safety-card/preview")
    @PermitAll
    public void previewSafetyCard(Long id, HttpServletResponse response) throws Exception {
        IotSocSummaryDO iotSocSummary = iotSocSummaryService.getIotSocSummary(id);
        String person = iotSocSummary.getUserName();
        String date = DateUtil.format(iotSocSummary.getObservationDate(), "yyyy-MM-dd HH:mm:ss");
        String remark = iotSocSummary.getRemark();

        List<SafetyObservationCardGenerator.CheckItem> checkItems = buildCheckItems(iotSocSummary);

        byte[] docBytes = SafetyObservationCardGenerator.generateCardToBytes(checkItems, person, date, remark);

        // ========== 以下是 KKFileView 必须的标准格式 ==========
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setCharacterEncoding("UTF-8");
        response.setContentLength(docBytes.length);
        response.setHeader("Content-Disposition", "inline; filename=preview.docx");
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Expires", "0");

        // 直接输出流（最稳定，不会被Spring包装坏）
        try (OutputStream out = response.getOutputStream()) {
            out.write(docBytes);
            out.flush();
        }
    }

    // 下载接口保持不变（也给你标准版本）
    @GetMapping("/safety-card/download/{id}")
    @PermitAll
    public void downloadSafetyCard(@PathVariable("id") Long id, HttpServletResponse response) throws Exception {
        IotSocSummaryDO iotSocSummary = iotSocSummaryService.getIotSocSummary(id);
        String person = iotSocSummary.getUserName();
        String date = DateUtil.format(iotSocSummary.getObservationDate(), "yyyy-MM-dd HH:mm:ss");
        String remark = iotSocSummary.getRemark();

        List<SafetyObservationCardGenerator.CheckItem> checkItems = buildCheckItems(iotSocSummary);
        byte[] docBytes = SafetyObservationCardGenerator.generateCardToBytes(checkItems, person, date, remark);

        String fileName = URLEncodeUtil.encode("行为安全观察与沟通卡" + StringUtils.substring(date, 0, 10) + person + ".docx");

        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setCharacterEncoding("UTF-8");
        response.setContentLength(docBytes.length);
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        try (OutputStream out = response.getOutputStream()) {
            out.write(docBytes);
            out.flush();
        }
    }
    // 示例：构建检查项（实际业务中需从前端参数/数据库获取）
    private List<SafetyObservationCardGenerator.CheckItem> buildCheckItems(IotSocSummaryDO iotSocSummaryDO) {
        if (StringUtils.isBlank(iotSocSummaryDO.getSocClass())) {
            throw new ServiceException(new ErrorCode(2, "没有SOC类型"));
        }
        String[] split = iotSocSummaryDO.getSocClass().split(",");
        List<SafetyObservationCardGenerator.CheckItem> checkItems = new ArrayList<>();
        for (String s : split) {
            IotSocSourceDO iotSocSourceDO = iotSocSourceMapper.selectById(Long.parseLong(s.trim()));
            if (StringUtils.isBlank(iotSocSourceDO.getRemark())) {
                //获取父类的SOC类型
                IotSocSourceDO iotSocSourceDO1 = iotSocSourceMapper.selectById(iotSocSourceDO.getParentId());
                //继续获取上一级
                IotSocSourceDO iotSocSourceDO2 = iotSocSourceMapper.selectById(iotSocSourceDO1.getParentId());
                SafetyObservationCardGenerator.CheckItem checkItem = new SafetyObservationCardGenerator.CheckItem(iotSocSourceDO2.getName(), iotSocSourceDO1.getName(), iotSocSourceDO2.getRemark(), iotSocSourceDO1.getRemark());
                checkItems.add(checkItem);
            } else {
                IotSocSourceDO iotSocSourceDO1 = iotSocSourceMapper.selectById(iotSocSourceDO.getParentId());
                SafetyObservationCardGenerator.CheckItem checkItem = new SafetyObservationCardGenerator.CheckItem(iotSocSourceDO1.getName(), iotSocSourceDO.getName(), iotSocSourceDO1.getRemark(), iotSocSourceDO.getRemark());
                checkItems.add(checkItem);
            }
        }

        return checkItems;
//        return ImmutableList.of(
//                new SafetyObservationCardGenerator.CheckItem("个人防护", "头部", "Personal Protection Equipment", "Head"),
//                new SafetyObservationCardGenerator.CheckItem("规范操作", "其他", "Tools and Equipment", "Other"),
//                new SafetyObservationCardGenerator.CheckItem("作业场所", "地面滑（水/雨/雪/油污等）", "Housekeeping", "Slippery floor (Water / Rain / Snow / Oil etc.)")
    }

    @GetMapping("/stat")
    @PermitAll
    public CommonResult<ImmutableMap> statSoc(IotSocSummaryPageReqVO pageReqVO) {
        List<IotSocSourceDO> list = iotSocSourceMapper.selectList();
        Long deptId = pageReqVO.getDeptId();
        if (Objects.isNull(pageReqVO.getDeptId())) {
            deptId = SecurityFrameworkUtils.getLoginUserDeptId();
        }
        Set<Long> ids;
        if (Objects.nonNull(deptId)) {
            ids = deptService.getChildDeptIdListFromCache(deptId);
            ids.add(pageReqVO.getDeptId());
        } else {
            ids = new HashSet<>();
        }
        List<ImmutableMap> results = new ArrayList<>();
//        Map person = new HashMap();
        list.stream().filter(e -> "不安全".equals(e.getName())).findFirst().ifPresent(e -> {
            List<IotSocSourceDO> summaryDOS = iotSocSourceMapper.selectList("parent_id", e.getId());
            AtomicReference<Long> unsafe = new AtomicReference<>(0L);
            summaryDOS.forEach(item -> {
                List<String> collect = iotSocSourceService.getChildSocSourceList(ImmutableList.of(item.getId())).stream().map(gg -> String.valueOf(gg.getId())).collect(Collectors.toList());
                collect.add(String.valueOf(item.getId()));
                IotSocSummaryPageReqVO pageReqVO1 = new IotSocSummaryPageReqVO();
//                pageReqVO1.setSocClass(String.valueOf(item.getId()));
                pageReqVO1.setSocClasses(collect);
                pageReqVO1.setObservationDate(pageReqVO.getObservationDate());
                Long count = iotSocSummaryMapper.selectCountBySocClassAndTime(pageReqVO1, ids);
                results.add(ImmutableMap.of(item.getName(), count,"id", item.getId()));
                unsafe.set(unsafe.get() + count);
            });
            results.add(ImmutableMap.of("不安全", unsafe.get()));
        });
        list.stream().filter(e -> "安全的".equals(e.getName())).findFirst().ifPresent(e -> {
            IotSocSummaryPageReqVO pageReqVO1 = new IotSocSummaryPageReqVO();
            pageReqVO1.setSocClass(String.valueOf(e.getId()));
            pageReqVO1.setObservationDate(pageReqVO.getObservationDate());
            Long count = iotSocSummaryMapper.selectCountBySocClassAndTime(pageReqVO1, ids);
            results.add(ImmutableMap.of(e.getName(), count));
        });

        return success(ImmutableMap.of("total", results));
    }

    @GetMapping("/stat/child")
    @PermitAll
    public CommonResult<ImmutableMap> statSocChild(IotSocSummaryPageReqVO pageReqVO) {
        List<IotSocSourceDO> list = iotSocSourceMapper.selectList();
        Long deptId = pageReqVO.getDeptId();
        if (Objects.isNull(pageReqVO.getDeptId())) {
            deptId = SecurityFrameworkUtils.getLoginUserDeptId();
        }
        Set<Long> ids;
        if (Objects.nonNull(deptId)) {
            ids = deptService.getChildDeptIdListFromCache(deptId);
            ids.add(pageReqVO.getDeptId());
        } else {
            ids = new HashSet<>();
        }
        List<ImmutableMap> results = new ArrayList<>();
            List<IotSocSourceDO> summaryDOS = iotSocSourceMapper.selectList("parent_id", pageReqVO.getSocClass());
            summaryDOS.forEach(item -> {
                List<String> collect = iotSocSourceService.getChildSocSourceList(ImmutableList.of(item.getId())).stream().map(gg -> String.valueOf(gg.getId())).collect(Collectors.toList());
                collect.add(String.valueOf(item.getId()));
                IotSocSummaryPageReqVO pageReqVO1 = new IotSocSummaryPageReqVO();
//                pageReqVO1.setSocClass(String.valueOf(item.getId()));
                pageReqVO1.setSocClasses(collect);
                pageReqVO1.setObservationDate(pageReqVO.getObservationDate());
                Long count = iotSocSummaryMapper.selectCountBySocClassAndTime(pageReqVO1, ids);
                results.add(ImmutableMap.of(item.getName(), count));
            });

        return success(ImmutableMap.of("total", results));
    }

}