package com.zcloud.zcGbsServicer.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.zcloud.zcGbsServicer.api.FireAlarmMeetingRoomServiceI;
import com.zcloud.zcGbsServicer.command.convertor.FireAlarmMeetingRoomCoConvertor;
import com.zcloud.zcGbsServicer.dto.FireAlarmMeetingRoomAddCmd;
import com.zcloud.zcGbsServicer.dto.FireAlarmMeetingRoomPageQry;
import com.zcloud.zcGbsServicer.dto.FireAlarmMeetingRoomUpdateCmd;
import com.zcloud.zcGbsServicer.dto.clientobject.FireAlarmMeetingRoomCO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmMeetingRoomDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmMeetingUserDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeUserDO;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmMeetingRoomRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmMeetingUserRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeUserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class FireAlarmMeetingRoomServiceImpl extends FireAlarmServiceSupport implements FireAlarmMeetingRoomServiceI {

    private final FireAlarmMeetingRoomRepository fireAlarmMeetingRoomRepository;
    private final FireAlarmMeetingRoomCoConvertor fireAlarmMeetingRoomCoConvertor;
    private final HstVideoPlatformClient hstVideoPlatformClient;
    private final FireBrigadeUserRepository fireBrigadeUserRepository;
    private final FireBrigadeRepository fireBrigadeRepository;
    private final FireAlarmMeetingUserRepository fireAlarmMeetingUserRepository;

    @Override
    public PageResponse<FireAlarmMeetingRoomCO> listPage(FireAlarmMeetingRoomPageQry qry) {
        Map<String, Object> params = new HashMap<>();
        params.put("pageIndex", qry.getPageIndex());
        params.put("pageSize", qry.getPageSize());
        params.put("roomCode", qry.getRoomCode());
        params.put("roomName", qry.getRoomName());
        params.put("roomStatus", qry.getRoomStatus());
        PageResponse<FireAlarmMeetingRoomDO> page = fireAlarmMeetingRoomRepository.listPage(params);
        return PageResponse.of(fireAlarmMeetingRoomCoConvertor.converDOsToCOs(page.getData()),
                page.getTotalCount(), page.getPageSize(), page.getPageIndex());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<FireAlarmMeetingRoomCO> add(FireAlarmMeetingRoomAddCmd cmd) {
        List<FireAlarmMeetingRoomDO> existingRooms = fireAlarmMeetingRoomRepository.listAll();
        if (existingRooms != null && !existingRooms.isEmpty()) {
            throw new BizException("已有固定会议室，不能重复创建");
        }

        Map<String, Object> requestBody = new LinkedHashMap<>();
        requestBody.put("roomName", cmd.getRoomName());
        if (StrUtil.isNotBlank(cmd.getRoomCode())) {
            requestBody.put("roomCode", cmd.getRoomCode());
        }
        if (StrUtil.isNotBlank(cmd.getRoomPasswordCipher())) {
            requestBody.put("password", cmd.getRoomPasswordCipher());
        }
        Map<String, Object> response = hstVideoPlatformClient.addRoomInfo(requestBody);
        hstVideoPlatformClient.ensureSuccess(response, "创建第三方固定会议室");
        Map<String, Object> data = castMap(response.get("data"));

        FireAlarmMeetingRoomDO room = new FireAlarmMeetingRoomDO();
        room.setId(nextId());
        room.setFireAlarmMeetingRoomId(nextBizId());
        room.setRebuildCount(0);
        room.setThirdRoomId(selectText(asText(data.get("roomId")), cmd.getThirdRoomId()));
        room.setThirdRoomNo(selectText(asText(data.get("roomNo")), cmd.getThirdRoomNo()));
        fillCreateAudit(room);
        fillRoom(room, cmd);
        fireAlarmMeetingRoomRepository.save(room);

        syncAuthUsersForNewRoom(room);

        return SingleResponse.of(fireAlarmMeetingRoomCoConvertor.converDOToCO(room));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(FireAlarmMeetingRoomUpdateCmd cmd) {
        FireAlarmMeetingRoomDO room = fireAlarmMeetingRoomRepository.getById(cmd.getId());
        if (room == null) {
            throw new BizException("会议室不存在");
        }
        if (fireAlarmMeetingRoomRepository.existsByRoomCode(cmd.getRoomCode(), cmd.getId())) {
            throw new BizException("会议室编码已存在");
        }
        fillUpdateAudit(room);
        fillRoom(room, cmd);
        fireAlarmMeetingRoomRepository.updateById(room);
    }

    @Override
    public FireAlarmMeetingRoomCO get(Long id) {
        FireAlarmMeetingRoomDO room = fireAlarmMeetingRoomRepository.getById(id);
        if (room == null) {
            throw new BizException("会议室不存在");
        }
        return fireAlarmMeetingRoomCoConvertor.converDOToCO(room);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Long id) {
        FireAlarmMeetingRoomDO room = fireAlarmMeetingRoomRepository.getById(id);
        if (room == null) {
            throw new BizException("会议室不存在");
        }
        fireAlarmMeetingRoomRepository.removeById(id);
    }

    private void fillRoom(FireAlarmMeetingRoomDO room, FireAlarmMeetingRoomAddCmd cmd) {
        room.setRoomCode(cmd.getRoomCode());
        room.setRoomName(cmd.getRoomName());
        room.setThirdRoomId(cmd.getThirdRoomId());
        room.setThirdRoomNo(cmd.getThirdRoomNo());
        room.setRoomPasswordCipher(cmd.getRoomPasswordCipher());
        room.setRoomStatus(cmd.getRoomStatus());
        room.setRemarks(cmd.getRemarks());
    }

    private void syncAuthUsersForNewRoom(FireAlarmMeetingRoomDO room) {
        String roomId = selectText(room.getThirdRoomId(), room.getThirdRoomNo());
        if (StrUtil.isBlank(roomId)) {
            return;
        }

        List<FireBrigadeUserDO> brigadeUsers = fireBrigadeUserRepository.listAll();
        if (brigadeUsers == null || brigadeUsers.isEmpty()) {
            return;
        }

        Map<Long, FireAlarmMeetingUserDO> meetingUserMap = fireAlarmMeetingUserRepository.listAll()
                .stream()
                .filter(u -> u.getLocalUserId() != null && StrUtil.isNotBlank(u.getThirdUserName()))
                .collect(Collectors.toMap(FireAlarmMeetingUserDO::getLocalUserId, u -> u, (a, b) -> a));

        Set<String> brigadeIds = brigadeUsers.stream()
                .map(FireBrigadeUserDO::getFireBrigadeId)
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toSet());
        Map<String, FireBrigadeDO> brigadeMap = new HashMap<>();
        for (String brigadeId : brigadeIds) {
            FireBrigadeDO brigade = fireBrigadeRepository.getByFireBrigadeId(brigadeId);
            if (brigade != null) {
                brigadeMap.put(brigadeId, brigade);
            }
        }

        for (FireBrigadeUserDO brigadeUser : brigadeUsers) {
            if (brigadeUser.getUserId() == null) {
                continue;
            }
            FireAlarmMeetingUserDO meetingUser = meetingUserMap.get(brigadeUser.getUserId());
            if (meetingUser == null) {
                continue;
            }

            FireBrigadeDO brigade = brigadeMap.get(brigadeUser.getFireBrigadeId());
            boolean isLeader = brigade != null && brigade.getLeaderUserId() != null
                    && brigade.getLeaderUserId().equals(brigadeUser.getUserId());
            int permission = isLeader ? 3 : 2;

            Map<String, Object> authBody = new LinkedHashMap<>();
            authBody.put("roomUserStr", roomId + "," + permission);
            authBody.put("userName", meetingUser.getThirdUserName());
            try {
                Map<String, Object> authResp = hstVideoPlatformClient.authRoom(authBody);
                hstVideoPlatformClient.ensureSuccess(authResp, "用户授权新会议室");
            } catch (BizException ex) {
                throw new BizException("用户授权新会议室失败", ex);
            }
        }
    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> castMap(Object value) {
        if (!(value instanceof Map)) {
            return new HashMap<>();
        }
        return (Map<String, Object>) value;
    }

    private String asText(Object value) {
        return value == null ? null : String.valueOf(value);
    }

    private String selectText(String preferred, String fallback) {
        return StrUtil.isNotBlank(preferred) ? preferred : fallback;
    }

    private long nextId() {
        return IdUtil.getSnowflake(1, 1).nextId();
    }

    private String nextBizId() {
        return UUID.randomUUID().toString().replace("-", "");
    }
}
