package com.ruoyi.web.controller.app;


import com.ruoyi.app.DTO.NFIDReadGroupDTO;
import com.ruoyi.app.DTO.PorkSideProduceDTO;
import com.ruoyi.app.domain.NFIDReadRecord;
import com.ruoyi.app.domain.NFIDReaderEvent;
import com.ruoyi.app.domain.PorkSideProduce;
import com.ruoyi.app.domain.request.ReqValidNFIDRecord;
import com.ruoyi.app.service.INFIDReadRecordService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.http.MediaType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * nfid识别记录Controller
 *
 */
@Api("nfid识别记录信息管理")
@RestController
@RequestMapping("/app/NFIDReadRecord")
public class NFIDReadRecordController extends BaseController
{
    @Autowired
    private INFIDReadRecordService NFIDReadRecordService;

    // 存储所有客户端的 SSE 连接（Key: 客户端ID，Value: SseEmitter）
    private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();

    private final ApplicationEventPublisher eventPublisher;

    // 注入事件发布器
    public NFIDReadRecordController(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }


    public static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);

    /**
     * 查询nfid识别记录列表
     */
    @ApiOperation("查询nfid识别记录列表")
    @PreAuthorize("@ss.hasPermi('app:NFIDReadRecord:list')")
    @GetMapping("/list")
    public TableDataInfo list()
    {
        startPage();
        List<NFIDReadRecord> list = NFIDReadRecordService.selectNFIDReadRecordList();
        return getDataTable(list);
    }

    /**
     * 查询nfid识别记录分组结果
     */
    @ApiOperation("查询nfid识别记录分组结果")
    @PreAuthorize("@ss.hasPermi('app:NFIDReadRecord:list')")
    @GetMapping("/groupList")
    public AjaxResult groupList()
    {
        List<NFIDReadGroupDTO> list = NFIDReadRecordService.selectNFIDReadByGroup();
        return success(list);
    }

    /**
     * 查询全部吊钩范围
     */
    @ApiOperation("查询全部吊钩范围")
    @PreAuthorize("@ss.hasPermi('app:NFIDReadRecord:list')")
    @GetMapping("/hookRange")
    public AjaxResult hookRange()
    {
        NFIDReadGroupDTO res = NFIDReadRecordService.selectHookRange();
        return success(res);
    }

    /**
     * 查询nfid识别记录分组详情清单
     */
    @ApiOperation("查询nfid识别记录分组详情清单")
    @PreAuthorize("@ss.hasPermi('app:NFIDReadRecord:list')")
    @GetMapping("/groupDetail")
    public AjaxResult groupDetail(ReqValidNFIDRecord req)
    {
        List<NFIDReadRecord> list = NFIDReadRecordService.selectNFIDReadRecordListByGroup(req);
        return success(list);
    }

    /**
     * 查询可用的nfid识别记录列表
     */
    @ApiOperation("查询可用的nfid识别记录列表")
    @PreAuthorize("@ss.hasPermi('app:NFIDReadRecord:list')")
    @GetMapping("/validList")
    public AjaxResult validList(ReqValidNFIDRecord req)
    {
        List<NFIDReadRecord> list = NFIDReadRecordService.selectValidNFIDReadRecord(req);
        return success(list);

    }

    /**
     * 新增nfid识别记录
     */
    @ApiOperation("新增nfid识别记录")
    @PreAuthorize("@ss.hasPermi('app:NFIDReadRecord:add')")
    @Log(title = "nfid识别记录", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated  @RequestBody NFIDReadRecord record)
    {

        return toAjax(NFIDReadRecordService.insertNFIDReadRecord(record));
    }

    /**
     * 客户端订阅识别记录数据
     */
    @GetMapping(value = "/subscribe/{readerId}/{clientId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter subscribe(@PathVariable String readerId,@PathVariable String clientId) {
            SseEmitter emitter = new SseEmitter(30_000L); // 超时时间 30 秒
            String key = readerId + ":" + clientId;
            emitters.put(key, emitter);
            //定期发送心跳
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(() -> {
                try {
                    while (true) {
                        emitter.send(SseEmitter.event()
                                .comment("ping") // 心跳消息
                                .reconnectTime(10_000)); // 重连时间建议
                        Thread.sleep(5_000); // 每10秒一次心跳
                    }
                } catch (Exception e) {
                    emitter.completeWithError(e);
                }
            });
            // 监听连接断开
            emitter.onCompletion(() -> emitters.remove(key));
            emitter.onTimeout(() -> emitters.remove(key));

            return emitter;
    }

    /**
     * 客户端主动取消订阅
     */
    @PostMapping("/unsubscribe/{readerId}/{clientId}")
    public void unsubscribe(@PathVariable String clientId) {
        SseEmitter emitter = emitters.get(clientId);
        if (emitter != null) {
            emitter.complete();
            emitters.remove(clientId);
        }
    }

    // 监听设备数据事件并广播 ,广播吊钩绑定的识别记录
    @EventListener
    public void handleHookBindData(NFIDReaderEvent event) {
        Object  data = event.getData();

        emitters.forEach((key, emitter) -> {
            String[] parts = key.split(":");
            String subject = parts[0];
            String clientId = parts[1];
            if (event.getSubject().equals(subject)) {
                if (data instanceof NFIDReadRecord) {
                    sendReaderData(emitter, (NFIDReadRecord) data, subject, key);
                } else if (data instanceof PorkSideProduceDTO) {
                    sendWeightData(emitter, (PorkSideProduceDTO) data, subject, key);
                }
            }
        });
    }

    //推送数据
    public void sendReaderData(SseEmitter emitter, NFIDReadRecord data, String subject,String key) {
        try {
            emitter.send(SseEmitter.event()
                    .data(data)
                    .id(String.valueOf(data.getCreateTime().getTime())) //使用时间戳作为ID
                    .name(subject));
        } catch (IOException e) {
            emitter.completeWithError(e);
            emitters.remove(key);  // 清理失效的Emitter
        }
    }

    //推送称重数据
    public void sendWeightData(SseEmitter emitter, PorkSideProduceDTO data, String subject, String key) {
        try {
            emitter.send(SseEmitter.event()
                    .data(data)
                    .id(String.valueOf(data.getCreateTime().getTime())) //使用时间戳作为ID
                    .name(subject));
        } catch (IOException e) {
            emitter.completeWithError(e);
            emitters.remove(key);  // 清理失效的Emitter
        }
    }
}
