package com.hotwj.platform.noticeManagerment.notificationIssue.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hotwj.platform.noticeManagerment.adminNotice.domain.bo.HotAdminNoticeBo;
import com.hotwj.platform.noticeManagerment.adminNotice.domain.vo.HotAdminNoticeVo;
import com.hotwj.platform.noticeManagerment.adminNotice.service.IHotAdminNoticeService;
import com.hotwj.platform.noticeManagerment.notificationIssue.domain.bo.HotNotificationIssueBo;
import com.hotwj.platform.noticeManagerment.notificationIssue.domain.bo.IssueRequest;
import com.hotwj.platform.noticeManagerment.notificationIssue.domain.vo.CompanyNoticeStatusVo;
import com.hotwj.platform.noticeManagerment.notificationIssue.domain.vo.HotNotificationIssueVo;
import com.hotwj.platform.noticeManagerment.notificationIssue.service.IHotNotificationIssueService;
import com.hotwj.platform.noticeManagerment.systemNotification.domain.bo.HotSystemNotificationGroupBo;
import com.hotwj.platform.noticeManagerment.systemNotification.service.IHotSystemNotificationService;
import com.hotwj.platform.resourceManagement.company.domain.bo.SysCompanyBo;
import com.hotwj.platform.resourceManagement.company.domain.vo.SysCompanyVo;
import com.hotwj.platform.resourceManagement.company.service.ISysCompanyService;
import com.hotwj.platform.resourceManagement.company.service.ISysUserLoginPortService;
import com.hotwj.platform.resourceManagement.companySafetyManager.domain.HotCompanySafetyManager;
import com.hotwj.platform.resourceManagement.companySafetyManager.mapper.HotCompanySafetyManagerMapper;
import com.hotwj.platform.resourceManagement.personnelConfig.domain.HotPersonnelConfig;
import com.hotwj.platform.resourceManagement.personnelConfig.mapper.HotPersonnelConfigMapper;
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.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysUserService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 通知下发
 *
 * @author shihongwei
 * @date 2026-01-13
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/noticeManagerment/notificationIssue")
@Tag(name = "通知下发", description = "通知下发管理")
public class HotNotificationIssueController extends BaseController {

    private final IHotNotificationIssueService hotNotificationIssueService;
    private final ISysCompanyService sysCompanyService;
    private final IHotAdminNoticeService hotAdminNoticeService;
    private final IHotSystemNotificationService hotSystemNotificationService;
    private final HotCompanySafetyManagerMapper hotCompanySafetyManagerMapper;
    private final HotPersonnelConfigMapper hotPersonnelConfigMapper;
    private final ISysUserService sysUserService;

    /**
     * 查询通知下发列表
     */
    //@SaCheckPermission("noticeManagerment:notificationIssue:list")
    @GetMapping("/list")
    @Operation(summary = "分页查询通知下发列表")
    public TableDataInfo<HotNotificationIssueVo> list(HotNotificationIssueBo bo, PageQuery pageQuery) {
        return hotNotificationIssueService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出通知下发列表
     */
    //@SaCheckPermission("noticeManagerment:notificationIssue:export")
    @Log(title = "通知下发", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @Operation(summary = "导出通知下发列表")
    public void export(HotNotificationIssueBo bo, HttpServletResponse response) {
        List<HotNotificationIssueVo> list = hotNotificationIssueService.queryList(bo);
        ExcelUtil.exportExcel(list, "通知下发", HotNotificationIssueVo.class, response);
    }

    /**
     * 获取通知下发详细信息
     *
     * @param id 主键
     */
    //@SaCheckPermission("noticeManagerment:notificationIssue:query")
    @GetMapping("/{id}")
    @Operation(summary = "获取通知下发详细信息")
    public R<HotNotificationIssueVo> getInfo(@NotNull(message = "主键不能为空")
                                             @Parameter(name = "id", description = "主键", required = true, example = "1")
                                             @PathVariable Long id) {
        return R.ok(hotNotificationIssueService.queryById(id));
    }

    /**
     * 新增通知下发
     */
    //@SaCheckPermission("noticeManagerment:notificationIssue:add")
    @Log(title = "通知下发", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    @Operation(summary = "新增通知下发")
    public R<Void> add(@Validated(AddGroup.class) @RequestBody HotNotificationIssueBo bo) {
        return toAjax(hotNotificationIssueService.insertByBo(bo));
    }

    /**
     * 修改通知下发
     */
    //@SaCheckPermission("noticeManagerment:notificationIssue:edit")
    @Log(title = "通知下发", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    @Operation(summary = "修改通知下发")
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody HotNotificationIssueBo bo) {
        return toAjax(hotNotificationIssueService.updateByBo(bo));
    }

    /**
     * 删除通知下发
     *
     * @param ids 主键串
     */
    //@SaCheckPermission("noticeManagerment:notificationIssue:remove")
    @Log(title = "通知下发", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    @Operation(summary = "删除通知下发")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @Parameter(name = "ids", description = "主键串", required = true, example = "1,2,3")
                          @PathVariable Long[] ids) {
        return toAjax(hotNotificationIssueService.deleteWithValidByIds(List.of(ids), true));
    }


    //@SaCheckPermission("noticeManagerment:notificationIssue:list")
    @GetMapping("/companyStatus")
    @Operation(summary = "查询辖区企业对于指定通知文件的状态")
    public R<List<CompanyNoticeStatusVo>> companyStatus(@RequestParam("districtCode") String districtCode,
                                                        @RequestParam("issueId") Long issueId,
                                                        @RequestParam(value = "companyName", required = false) String companyName,
                                                        @RequestParam(value = "responsibleName", required = false) String responsibleName,
                                                        @RequestParam(value = "responsibleMobile", required = false) String responsibleMobile,
                                                        @RequestParam(value = "companyStatus", required = false) Long companyStatus) {
        HotNotificationIssueVo issue = hotNotificationIssueService.queryById(issueId);
        if (issue == null) {
            return R.ok(new ArrayList<>());
        }
        SysCompanyBo companyBo = new SysCompanyBo();
        companyBo.setRegionCode(districtCode);
        companyBo.setCompanyName(companyName);
        companyBo.setResponsibleName(responsibleName);
        companyBo.setResponsibleMobile(responsibleMobile);
        companyBo.setStatus(companyStatus);
        List<SysCompanyVo> companies = sysCompanyService.queryList(companyBo);
        List<CompanyNoticeStatusVo> result = new ArrayList<>();
        if (companies != null) {
            for (SysCompanyVo c : companies) {
                HotAdminNoticeBo recordBo = new HotAdminNoticeBo();
                recordBo.setCompanyId(c.getId());
                recordBo.setNoticeId(issueId);
                List<HotAdminNoticeVo> records = hotAdminNoticeService.queryList(recordBo);
                HotAdminNoticeVo record = (records != null && !records.isEmpty()) ? records.get(0) : null;
                CompanyNoticeStatusVo vo = new CompanyNoticeStatusVo();
                vo.setCompanyId(c.getId());
                vo.setCompanyName(c.getCompanyName());
                vo.setCompanyStatus(c.getStatus());
                vo.setManagerName(c.getResponsibleName());
                vo.setManagerPhone(c.getResponsibleMobile());
                vo.setIsIssued(record != null ? 1L : 0L);
                vo.setIsReceived(record != null ? record.getIsReceived() : 0L);
                vo.setReceivedTime(record != null ? record.getReceiveTime() : null);
                vo.setNotifyType(issue.getNotifyType());
                result.add(vo);
            }
        }
        return R.ok(result);
    }

    //@SaCheckPermission("noticeManagerment:notificationIssue:issue")
    @PostMapping("/issue")
    @Operation(summary = "下发文件到具体的单位")
    @RepeatSubmit()
    public R<Void> issueToCompanies(@Validated @RequestBody IssueRequest req) {
        HotNotificationIssueVo issue = hotNotificationIssueService.queryById(req.getIssueId());
        if (issue == null) {
            return R.fail("通知下发不存在");
        }
        boolean hasIssued = false;
        for (Long companyId : req.getCompanyIds()) {
            if (companyId == null) {
                continue;
            }
            // 判断是否已经下发过
            HotAdminNoticeBo checkBo = new HotAdminNoticeBo();
            checkBo.setCompanyId(companyId);
            checkBo.setNoticeId(req.getIssueId());
            List<HotAdminNoticeVo> exists = hotAdminNoticeService.queryList(checkBo);
            if (exists != null && !exists.isEmpty()) {
                continue;
            }

            HotAdminNoticeBo bo = new HotAdminNoticeBo();
            bo.setCompanyId(companyId);
            bo.setNoticeId(req.getIssueId());
            bo.setFileName(issue.getFileName());
            bo.setNotifyType(issue.getNotifyType());
            bo.setAttachmentUrl(issue.getAttachmentUrl());
            bo.setIssueTime(new Date());
            bo.setIsReceived(0L);
            bo.setReceiveTime(null);
            bo.setDeadlineTime(issue.getReplyDeadline() != null ? issue.getReplyDeadline().toString() : null);
            hotAdminNoticeService.insertByBo(bo);
            sendIssueNotificationToCompanyHead(companyId, issue);
            hasIssued = true;
        }

        // 更新下发公司ids
        Set<Long> existingIds = new HashSet<>();
        if (issue.getIssueCompanyIds() != null && !issue.getIssueCompanyIds().isEmpty()) {
            String[] split = issue.getIssueCompanyIds().split(",");
            for (String s : split) {
                if (s != null && !s.trim().isEmpty()) {
                    try {
                        existingIds.add(Long.parseLong(s.trim()));
                    } catch (NumberFormatException e) {
                        // ignore
                    }
                }
            }
        }
        for (Long id : req.getCompanyIds()) {
            if (id != null) {
                existingIds.add(id);
            }
        }
        String newIssueCompanyIds = existingIds.stream()
            .map(String::valueOf)
            .collect(Collectors.joining(","));

        HotNotificationIssueBo updateBo = new HotNotificationIssueBo();
        updateBo.setId(issue.getId());
        updateBo.setIssueCompanyIds(newIssueCompanyIds);
        hotNotificationIssueService.updateByBo(updateBo);
        if (hasIssued) {
            sendIssueSseToHeadquarters();
        }

        return R.ok();
    }

    private void sendIssueNotificationToCompanyHead(Long companyId, HotNotificationIssueVo issue) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            return;
        }
        String loginPort = loginUser.getLoginPort();
        if (!StringUtils.equals(loginPort, ISysUserLoginPortService.GOVERNMENT_PORT)
                && !StringUtils.equals(loginPort, ISysUserLoginPortService.HEADQUARTERS_PORT)) {
            return;
        }
        String receiverId = findCompanyHeadReceiverId(companyId);
        if (StringUtils.isBlank(receiverId)) {
            return;
        }
        HotSystemNotificationGroupBo notificationBo = new HotSystemNotificationGroupBo();
        notificationBo.setLevel("普通");
        notificationBo.setSourceType("行管通知");
        notificationBo.setSenderType(StringUtils.equals(loginPort, ISysUserLoginPortService.GOVERNMENT_PORT) ? "GOVERNMENT" : "SYSTEM");
        notificationBo.setSenderName(loginUser.getUsername());
        if (StringUtils.equals(loginPort, ISysUserLoginPortService.GOVERNMENT_PORT)
                && StringUtils.isNotBlank(loginUser.getBusinessUserId())
                && StringUtils.isNumeric(loginUser.getBusinessUserId())) {
            notificationBo.setSenderId(Long.valueOf(loginUser.getBusinessUserId()));
        }
        notificationBo.setReceiverType("管理员");
        notificationBo.setReceiverId(receiverId);
        notificationBo.setContent("收到新的行管通知《" + StringUtils.blankToDefault(issue.getFileName(), "未命名通知") + "》，请及时查看并处理。");
        notificationBo.setIsDeleted(0L);
        hotSystemNotificationService.insertByBo(notificationBo);
    }

    private String findCompanyHeadReceiverId(Long companyId) {
        if (companyId == null) {
            return null;
        }
        List<HotCompanySafetyManager> heads = hotCompanySafetyManagerMapper.selectList(
                Wrappers.<HotCompanySafetyManager>lambdaQuery()
                        .eq(HotCompanySafetyManager::getCompanyId, companyId)
                        .eq(HotCompanySafetyManager::getCompanyHead, 1L)
                        .eq(HotCompanySafetyManager::getIsDeleted, 0L)
                        .eq(HotCompanySafetyManager::getIsResigned, 0L)
                        .eq(HotCompanySafetyManager::getStatus, 1L)
                        .orderByDesc(HotCompanySafetyManager::getCreateTime)
        );
        if (heads != null && !heads.isEmpty()) {
            return String.valueOf(heads.get(0).getId());
        }
        List<HotCompanySafetyManager> managers = hotCompanySafetyManagerMapper.selectList(
                Wrappers.<HotCompanySafetyManager>lambdaQuery()
                        .eq(HotCompanySafetyManager::getCompanyId, companyId)
                        .eq(HotCompanySafetyManager::getIsDeleted, 0L)
                        .eq(HotCompanySafetyManager::getIsResigned, 0L)
                        .eq(HotCompanySafetyManager::getStatus, 1L)
                        .orderByDesc(HotCompanySafetyManager::getCreateTime)
        );
        if (managers == null || managers.isEmpty()) {
            return null;
        }
        return String.valueOf(managers.get(0).getId());
    }

    private void sendIssueSseToHeadquarters() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null || !StringUtils.equals(loginUser.getLoginPort(), ISysUserLoginPortService.GOVERNMENT_PORT)) {
            return;
        }
        List<HotPersonnelConfig> hqUsers = hotPersonnelConfigMapper.selectList(
                Wrappers.<HotPersonnelConfig>lambdaQuery()
                        .eq(HotPersonnelConfig::getUnitId, 1L)
                        .eq(HotPersonnelConfig::getIsEnabled, 1L)
                        .eq(HotPersonnelConfig::getIsDeleted, 0L)
        );
        if (hqUsers == null || hqUsers.isEmpty()) {
            return;
        }
        Set<Long> userIds = new LinkedHashSet<>();
        for (HotPersonnelConfig user : hqUsers) {
            if (user == null || StringUtils.isBlank(user.getMobile())) {
                continue;
            }
            SysUserVo sysUser = sysUserService.selectUserByPhonenumber(user.getMobile());
            if (sysUser != null && sysUser.getUserId() != null) {
                userIds.add(sysUser.getUserId());
            }
        }
        if (userIds.isEmpty()) {
            return;
        }
        SseMessageDto dto = new SseMessageDto();
        dto.setUserIds(new ArrayList<>(userIds));
        dto.setMessage(JsonUtils.toJsonString(Map.of("isSilent", true)));
        SseMessageUtils.publishMessage(dto);
    }
}
