package org.xyzh.workcase.controller;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;
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.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.xyzh.api.workcase.dto.TbChatRoomDTO;
import org.xyzh.api.workcase.dto.TbChatRoomMemberDTO;
import org.xyzh.api.workcase.dto.TbChatRoomMessageDTO;
import org.xyzh.api.workcase.dto.TbCustomerServiceDTO;
import org.xyzh.api.workcase.dto.TbVideoMeetingDTO;
import org.xyzh.api.workcase.dto.TbWordCloudDTO;
import org.xyzh.api.workcase.service.ChatRoomService;
import org.xyzh.api.workcase.service.WorkcaseChatService;
import org.xyzh.api.workcase.vo.ChatMemberVO;
import org.xyzh.api.workcase.vo.ChatRoomMessageVO;
import org.xyzh.api.workcase.vo.ChatRoomVO;
import org.xyzh.api.workcase.vo.CustomerServiceVO;
import org.xyzh.api.workcase.vo.VideoMeetingVO;
import org.xyzh.common.auth.utils.JwtTokenUtil;
import org.xyzh.common.auth.utils.LoginUtil;
import org.xyzh.common.core.domain.LoginDomain;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageRequest;
import org.xyzh.common.utils.validation.ValidationParam;
import org.xyzh.common.utils.validation.ValidationResult;
import org.xyzh.common.utils.validation.ValidationUtils;

import io.swagger.v3.oas.annotations.Operation;

import java.util.Arrays;
import java.util.Date;
import java.util.Map;

import io.swagger.v3.oas.annotations.tags.Tag;

/**
 * @description    工单对话控制器
 *                 - AI对话管理（智能问答）
 *                 - ChatRoom聊天室管理（实时IM）
 *                 - 微信客服消息接收
 *                 - 词云管理
 * @filename    WorkcaseChatController.java
 * @author    yslg
 * @copyright xyzh
 * @since 2025-12-19
 */
@Tag(name = "工单对话")
@Validated
@RestController
@RequestMapping("/workcase/chat")
public class WorkcaseChatController {

    @Autowired
    private WorkcaseChatService workcaseChatService;

    @Autowired
    private ChatRoomService chatRoomService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    // ========================= ChatRoom聊天室管理（实时IM） =========================

    @Operation(summary = "创建聊天室（转人工时调用）")
    @PreAuthorize("hasAuthority('workcase:room:create')")
    @PostMapping("/room")
    public ResultDomain<TbChatRoomDTO> createChatRoom(@RequestBody TbChatRoomDTO chatRoom) {
        ValidationResult vr = ValidationUtils.validate(chatRoom, Arrays.asList(
            ValidationUtils.requiredString("guestId", "来客ID"),
            ValidationUtils.requiredString("deviceCode", "设备代码")
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        chatRoom.setCreator(chatRoom.getGuestId());
        try {
            return chatRoomService.createChatRoom(chatRoom);
        } catch (Exception e) {
            return ResultDomain.failure(e.getMessage());
        }
    }

    @Operation(summary = "更新聊天室")
    @PreAuthorize("hasAuthority('workcase:room:update')")
    @PutMapping("/room")
    public ResultDomain<TbChatRoomDTO> updateChatRoom(@RequestBody TbChatRoomDTO chatRoom) {
        ValidationResult vr = ValidationUtils.validate(chatRoom, Arrays.asList(
            ValidationUtils.requiredString("roomId", "聊天室ID")
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return chatRoomService.updateChatRoom(chatRoom);
    }

    @Operation(summary = "关闭聊天室")
    @PreAuthorize("hasAuthority('workcase:room:close')")
    @PostMapping("/room/{roomId}/close")
    public ResultDomain<Boolean> closeChatRoom(@PathVariable(value = "roomId") String roomId, @RequestParam String closedBy) {
        return chatRoomService.closeChatRoom(roomId, closedBy);
    }

        /**
     * 提交聊天室服务评分
     * @param roomId 聊天室ID
     * @param commentLevel 评分（1-5星）
     * @return 提交结果
     */
    @Operation(summary = "提交聊天室服务评分")
    @PreAuthorize("hasAuthority('workcase:room:view')")
    @PostMapping("/room/{roomId}/comment")
    public ResultDomain<Boolean> submitComment(
            @PathVariable("roomId") String roomId,
            @RequestBody Map<String, Integer> body) {

        Integer commentLevel = body.get("commentLevel");
        if (commentLevel == null || commentLevel < 1 || commentLevel > 5) {
            return ResultDomain.failure("评分必须在1-5之间");
        }

        // 获取当前登录用户ID
        String userId = LoginUtil.getCurrentUserId();

        // 调用服务层提交评分
        return chatRoomService.submitCommentLevel(roomId, commentLevel, userId);
    }

    @Operation(summary = "获取聊天室详情")
    @PreAuthorize("hasAuthority('workcase:room:view')")
    @GetMapping("/room/{roomId}")
    public ResultDomain<TbChatRoomDTO> getChatRoomById(@PathVariable(value = "roomId") String roomId) {
        return chatRoomService.getChatRoomById(roomId);
    }

    @Operation(summary = "分页查询聊天室")
    @PreAuthorize("hasAuthority('workcase:room:view')")
    @PostMapping("/room/page")
    public ResultDomain<ChatRoomVO> getChatRoomPage(
            @RequestBody PageRequest<TbChatRoomDTO> pageRequest) {
        ValidationResult vr = ValidationUtils.validate(pageRequest, Arrays.asList(
            ValidationUtils.requiredNumber("pageParam.page", "页码", 1, null),
            ValidationUtils.requiredNumber("pageParam.pageSize", "每页数量", 1, 100)
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        
        LoginDomain loginDomain = LoginUtil.getCurrentLogin();
        String userId = loginDomain.getUser().getUserId();
        if("guest".equals(loginDomain.getUser().getStatus())){
            pageRequest.getFilter().setGuestId(userId);
        }
        return chatRoomService.getChatRoomPage(pageRequest, userId);
    }

    // ========================= ChatRoom成员管理 =========================

    @Operation(summary = "添加聊天室成员")
    @PreAuthorize("hasAuthority('workcase:room:member')")
    @PostMapping("/room/member")
    public ResultDomain<TbChatRoomMemberDTO> addChatRoomMember(@RequestBody TbChatRoomMemberDTO member) {
        ValidationResult vr = ValidationUtils.validate(member, Arrays.asList(
            ValidationUtils.requiredString("roomId", "聊天室ID"),
            ValidationUtils.requiredString("userId", "用户ID")
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return chatRoomService.addChatRoomMember(member);
    }

    @Operation(summary = "移除聊天室成员")
    @PreAuthorize("hasAuthority('workcase:room:member')")
    @DeleteMapping("/room/member/{memberId}")
    public ResultDomain<Boolean> removeChatRoomMember(@PathVariable(value = "memberId") String memberId) {
        return chatRoomService.removeChatRoomMember(memberId);
    }

    @Operation(summary = "获取聊天室成员列表")
    @PreAuthorize("hasAuthority('workcase:room:member')")
    @GetMapping("/room/{roomId}/members")
    public ResultDomain<ChatMemberVO> getChatRoomMemberList(@PathVariable(value = "roomId") String roomId) {
        return chatRoomService.getChatRoomMemberList(roomId);
    }

    @Operation(summary = "获取当前用户在指定聊天室的未读消息数")
    @PreAuthorize("hasAuthority('workcase:room:member')")
    @GetMapping("/room/{roomId}/unread")
    public ResultDomain<Integer> getUnreadCount(
            @PathVariable(value = "roomId") String roomId,
            @RequestParam(value = "userId") String userId) {
        return chatRoomService.getUnreadCount(roomId, userId);
    }

    // ========================= ChatRoom消息管理 =========================

    @Operation(summary = "发送聊天室消息")
    @PreAuthorize("hasAuthority('workcase:room:message')")
    @PostMapping("/room/message")
    public ResultDomain<TbChatRoomMessageDTO> sendMessage(@RequestBody TbChatRoomMessageDTO message) {
        ValidationResult vr = ValidationUtils.validate(message, Arrays.asList(
            ValidationUtils.requiredString("roomId", "聊天室ID"),
            ValidationUtils.requiredString("senderId", "发送者ID"),
            ValidationUtils.requiredString("content", "消息内容"),
            ValidationUtils.requiredString("senderName", "发送者名称")
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return chatRoomService.sendMessage(message);
    }

    @Operation(summary = "分页查询聊天室消息")
    @PreAuthorize("hasAuthority('workcase:room:message')")
    @PostMapping("/room/message/page")
    public ResultDomain<ChatRoomMessageVO> getChatMessagePage(@RequestBody PageRequest<TbChatRoomMessageDTO> pageRequest) {
        ValidationResult vr = ValidationUtils.validate(pageRequest, Arrays.asList(
            ValidationUtils.requiredNumber("pageParam.page", "页码", 1, null),
            ValidationUtils.requiredNumber("pageParam.pageSize", "每页数量", 1, 100)
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return chatRoomService.getChatMessagePage(pageRequest);
    }

    @Operation(summary = "删除聊天室消息")
    @PreAuthorize("hasAuthority('workcase:room:message')")
    @DeleteMapping("/room/message/{messageId}")
    public ResultDomain<Boolean> deleteRoomMessage(@PathVariable(value = "messageId") String messageId) {
        return chatRoomService.deleteMessage(messageId);
    }

    // ========================= 客服人员管理 =========================

    @Operation(summary = "添加客服人员")
    @PostMapping("/customer-service")
    public ResultDomain<TbCustomerServiceDTO> addCustomerService(@RequestBody TbCustomerServiceDTO customerService) {
        ValidationResult vr = ValidationUtils.validate(customerService, Arrays.asList(
            ValidationUtils.requiredString("userId", "员工ID")
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return chatRoomService.addCustomerService(customerService);
    }

    @Operation(summary = "更新客服人员")
    @PutMapping("/customer-service")
    public ResultDomain<TbCustomerServiceDTO> updateCustomerService(@RequestBody TbCustomerServiceDTO customerService) {
        ValidationResult vr = ValidationUtils.validate(customerService, Arrays.asList(
            ValidationUtils.requiredString("userId", "员工ID")
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return chatRoomService.updateCustomerService(customerService);
    }

    @Operation(summary = "删除客服人员")
    @DeleteMapping("/customer-service/{userId}")
    public ResultDomain<Boolean> deleteCustomerService(@PathVariable(value = "userId") String userId) {
        return chatRoomService.deleteCustomerService(userId);
    }

    @Operation(summary = "分页查询客服人员")
    @PostMapping("/customer-service/page")
    public ResultDomain<CustomerServiceVO> getCustomerServicePage(@RequestBody PageRequest<TbCustomerServiceDTO> pageRequest) {
        ValidationResult vr = ValidationUtils.validate(pageRequest, Arrays.asList(
            ValidationUtils.requiredNumber("pageParam.page", "页码", 1, null),
            ValidationUtils.requiredNumber("pageParam.pageSize", "每页数量", 1, 100)
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return chatRoomService.getCustomerServicePage(pageRequest);
    }

    @Operation(summary = "更新客服在线状态")
    @PostMapping("/customer-service/{userId}/status/{status}")
    public ResultDomain<Boolean> updateCustomerServiceStatus(@PathVariable(value = "userId") String userId, @PathVariable(value = "status") String status) {
        return chatRoomService.updateCustomerServiceStatus(userId, status);
    }

    @Operation(summary = "获取可接待客服列表")
    @GetMapping("/customer-service/available")
    public ResultDomain<CustomerServiceVO> getAvailableCustomerServices() {
        return chatRoomService.getAvailableCustomerServices();
    }

    @Operation(summary = "自动分配客服")
    @PostMapping("/room/{roomId}/assign")
    public ResultDomain<CustomerServiceVO> assignCustomerService(@PathVariable(value = "roomId") String roomId) {
        return chatRoomService.assignCustomerService(roomId);
    }

    // ========================= 视频会议管理（Jitsi Meet） =========================

    @Autowired
    private org.xyzh.api.workcase.service.VideoMeetingService videoMeetingService;

    @Operation(summary = "创建视频会议")
    @PreAuthorize("hasAuthority('meeting:create:own')")
    @PostMapping("/meeting/create")
    public ResultDomain<VideoMeetingVO> createVideoMeeting(
            @RequestBody TbVideoMeetingDTO meetingDTO) {
        ValidationResult vr = ValidationUtils.validate(meetingDTO, Arrays.asList(
            ValidationUtils.requiredString("roomId", "聊天室ID"),
            ValidationUtils.requiredString("meetingName", "会议名称"),
            // 校验开始时间不为空
            ValidationParam.builder()
                .fieldName("startTime")
                .fieldLabel("会议开始时间")
                .required()
                .build(),
            // 校验结束时间不为空
            ValidationParam.builder()
                .fieldName("endTime")
                .fieldLabel("会议结束时间")
                .required()
                .build(),
            // 校验开始时间小于结束时间（使用 fieldCompare 比较两个字段）
            ValidationUtils.fieldCompare(
                "startTime",
                "endTime",
                "会议时间",
                (startTime, endTime) -> {
                    if (startTime instanceof Date && endTime instanceof Date) {
                        return ((Date) startTime).before((Date) endTime);
                    }
                    return true;
                },
                "会议开始时间不能晚于结束时间"
            )
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }

        try {
            return videoMeetingService.createMeeting(meetingDTO);
        } catch (Exception e) {
            return ResultDomain.failure(e.getMessage());
        }
    }

    @Operation(summary = "获取会议信息")
    @PreAuthorize("hasAuthority('meeting:url:any')")
    @GetMapping("/meeting/{meetingId}")
    public ResultDomain<VideoMeetingVO> getMeetingInfo(
            @PathVariable(value = "meetingId") String meetingId) {
        String userId = LoginUtil.getCurrentUserId();

        try {
            return videoMeetingService.getMeetingInfo(meetingId, userId);
        } catch (Exception e) {
            return ResultDomain.failure(e.getMessage());
        }
    }

    @Operation(summary = "加入会议（生成用户专属JWT）")
    @PreAuthorize("hasAuthority('meeting:join:any')")
    @PostMapping("/meeting/{meetingId}/join")
    public ResultDomain<VideoMeetingVO> joinMeeting(
            @PathVariable(value = "meetingId") String meetingId) {
        String userId = LoginUtil.getCurrentUserId();

        // 验证加入权限
        ResultDomain<Boolean> accessCheck = videoMeetingService.validateMeetingAccess(meetingId, userId);
        if (!accessCheck.getSuccess() || !accessCheck.getData()) {
            return ResultDomain.failure("您无权加入此会议");
        }

        // 生成用户专属的iframe URL（包含JWT Token）
        try {
            return videoMeetingService.generateUserMeetingUrl(meetingId, userId);
        } catch (Exception e) {
            return ResultDomain.failure(e.getMessage());
        }
    }

    @Operation(summary = "开始会议")
    @PreAuthorize("hasAuthority('meeting:create:own')")
    @PostMapping("/meeting/{meetingId}/start")
    public ResultDomain<Boolean> startMeeting(@PathVariable(value = "meetingId") String meetingId) {
        try {
            return videoMeetingService.startMeeting(meetingId);
        } catch (Exception e) {
            return ResultDomain.failure(e.getMessage());
        }
    }

    @Operation(summary = "结束会议")
    @PreAuthorize("hasAuthority('meeting:create:own')")
    @PostMapping("/meeting/{meetingId}/end")
    public ResultDomain<VideoMeetingVO> endMeeting(
            @PathVariable(value = "meetingId") String meetingId) {
        try {
            return videoMeetingService.endMeeting(meetingId);
        } catch (Exception e) {
            return ResultDomain.failure(e.getMessage());
        }
    }

    @Operation(summary = "获取聊天室当前活跃会议")
    @PreAuthorize("hasAuthority('meeting:url:any')")
    @GetMapping("/meeting/room/{roomId}/active")
    public ResultDomain<VideoMeetingVO> getActiveMeetingByRoom(
            @PathVariable(value = "roomId") String roomId) {
        try {
            return videoMeetingService.getActiveMeetingByRoom(roomId);
        } catch (Exception e) {
            return ResultDomain.failure(e.getMessage());
        }
    }

    @Operation(summary = "会议入口（支持URL参数token认证，用于小程序和外部链接）")
    @GetMapping("/meeting/{meetingId}/entry")
    public ResultDomain<VideoMeetingVO> getMeetingEntry(
            @PathVariable(value = "meetingId") String meetingId,
            @RequestParam(value = "token", required = false) String token,
            HttpServletRequest request) {
        // 优先从URL参数获取token，其次从Header获取
        if (token == null || token.trim().isEmpty()) {
            token = request.getHeader("Authorization");
        }
        
        try {
            return videoMeetingService.getMeetingEntryByToken(meetingId, token);
        } catch (Exception e) {
            return ResultDomain.failure(e.getMessage());
        }
    }

    @Operation(summary = "生成会议入口URL（用于分享给小程序用户）")
    @PreAuthorize("hasAuthority('meeting:url:any')")
    @GetMapping("/meeting/{meetingId}/share-url")
    public ResultDomain<String> generateMeetingShareUrl(
            @PathVariable(value = "meetingId") String meetingId,
            @RequestParam(value = "baseUrl", defaultValue = "") String baseUrl,
            HttpServletRequest request) {
        // 如果没有提供baseUrl，则从请求中构建
        if (baseUrl == null || baseUrl.trim().isEmpty()) {
            String scheme = request.getScheme();
            String serverName = request.getServerName();
            int serverPort = request.getServerPort();
            String contextPath = request.getContextPath();
            
            if ((scheme.equals("http") && serverPort == 80) || 
                (scheme.equals("https") && serverPort == 443)) {
                baseUrl = scheme + "://" + serverName + contextPath + "/workcase";
            } else {
                baseUrl = scheme + "://" + serverName + ":" + serverPort + contextPath + "/workcase";
            }
        }
        
        try {
            return videoMeetingService.generateMeetingEntryUrl(meetingId, baseUrl);
        } catch (Exception e) {
            return ResultDomain.failure(e.getMessage());
        }
    }

    // ========================= 微信客服消息回调 =========================

    // @Operation(summary = "微信客服消息回调验证（GET）")
    // @GetMapping("/kefu/callback")
    // public String kefuCallbackVerify(
    //         @RequestParam("msg_signature") String msgSignature,
    //         @RequestParam("timestamp") String timestamp,
    //         @RequestParam("nonce") String nonce,
    //         @RequestParam("echostr") String echostr) {
    //     // TODO: 验证签名并返回 echostr
    //     // 实际应使用微信提供的加解密工具验证
    //     return echostr;
    // }

    // @Operation(summary = "微信客服消息回调（POST）")
    // @PostMapping("/kefu/callback")
    // public String kefuCallback(
    //         @RequestParam("msg_signature") String msgSignature,
    //         @RequestParam("timestamp") String timestamp,
    //         @RequestParam("nonce") String nonce,
    //         @RequestBody String xmlBody) {
    //     // TODO: 解密消息，调用同步接口拉取消息
    //     // 收到回调后，应调用 kefuMessageService.syncMessages() 拉取新消息
    //     // 然后通过 processMessages() 处理消息
    //     return "success";
    // }

    // ========================= 词云管理 =========================

    @Operation(summary = "添加词云")
    @PostMapping("/wordcloud")
    public ResultDomain<TbWordCloudDTO> addWordCloud(@RequestBody TbWordCloudDTO wordCloud) {
        ValidationResult vr = ValidationUtils.validate(wordCloud, Arrays.asList(
            ValidationUtils.requiredString("word", "词语"),
            ValidationUtils.requiredString("category", "分类")
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return workcaseChatService.addWordCloud(wordCloud);
    }

    @Operation(summary = "更新词云")
    @PutMapping("/wordcloud")
    public ResultDomain<TbWordCloudDTO> updateWordCloud(@RequestBody TbWordCloudDTO wordCloud) {
        ValidationResult vr = ValidationUtils.validate(wordCloud, Arrays.asList(
            ValidationUtils.requiredString("wordCloudId", "词云ID")
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return workcaseChatService.updateWordCloud(wordCloud);
    }

    @Operation(summary = "查询词云列表")
    @PostMapping("/wordcloud/list")
    public ResultDomain<TbWordCloudDTO> getWordCloudList(@RequestBody TbWordCloudDTO filter) {
        return workcaseChatService.getWordCloudList(filter);
    }

    @Operation(summary = "分页查询词云")
    @PostMapping("/wordcloud/page")
    public ResultDomain<TbWordCloudDTO> getWordCloudPage(@RequestBody PageRequest<TbWordCloudDTO> pageRequest) {
        ValidationResult vr = ValidationUtils.validate(pageRequest, Arrays.asList(
            ValidationUtils.requiredNumber("pageParam.page", "页码", 1, null),
            ValidationUtils.requiredNumber("pageParam.pageSize", "每页数量", 1, 100)
        ));
        if (!vr.isValid()) {
            return ResultDomain.failure(vr.getAllErrors());
        }
        return workcaseChatService.getWordCloudPage(pageRequest);
    }

}
