package com.huimv.employment.service.conversation;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huimv.employment.common.exception.BizException;
import com.huimv.employment.common.exception.ErrorCode;
import com.huimv.employment.dao.entity.FeConversation;
import com.huimv.employment.dao.mapper.FeConversationMapper;
import com.huimv.employment.service.conversation.dto.ConversationCreateRequest;
import com.huimv.employment.service.conversation.dto.ConversationSummaryResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * AI 对话会话业务层。会话仅归属用户，不与企业绑定。
 */
@Service
public class ConversationService {

    private static final Logger log = LoggerFactory.getLogger(ConversationService.class);

    private static final String STATUS_ACTIVE = "active";
    private static final String CHAT_TYPE_EMPLOYMENT = "employment";

    private static final Set<String> ALLOWED_CHAT_TYPES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
            "employment", "knowledge", "order", "cost", "attendance", "emergency"
    )));

    /** 与表字段 {@code conversation_no} VARCHAR(32) 一致 */
    private static final int CONVERSATION_NO_MAX_LEN = 32;

    private final FeConversationMapper feConversationMapper;

    public ConversationService(FeConversationMapper feConversationMapper) {
        this.feConversationMapper = feConversationMapper;
    }

    /**
     * 查询指定用户的 AI 对话会话列表。
     */
    public List<ConversationSummaryResponse> listByUser(Long userId, String status, String chatType) {
        if (userId == null) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<FeConversation> wrapper = new LambdaQueryWrapper<FeConversation>()
                .eq(FeConversation::getUserId, userId)
                .eq(StringUtils.hasText(status), FeConversation::getStatus, status)
                .eq(StringUtils.hasText(chatType), FeConversation::getChatType, chatType)
                .orderByDesc(FeConversation::getLastMessageAt)
                .orderByDesc(FeConversation::getCreateTime);
        return feConversationMapper.selectList(wrapper).stream()
                .map(this::toSummary)
                .collect(Collectors.toList());
    }

    /**
     * 新建 AI 对话会话。
     * <p>{@code conversationNo} 不传时自动生成，作为后续 AI {@code session_id}。</p>
     */
    @Transactional(rollbackFor = Exception.class)
    public ConversationSummaryResponse create(Long userId, ConversationCreateRequest request) {
        if (userId == null) {
            throw new BizException(ErrorCode.UNAUTHORIZED);
        }
        String chatType = resolveChatType(request != null ? request.getChatType() : null);
        String conversationNo = resolveNewConversationNo(request != null ? request.getConversationNo() : null);
        assertConversationNoAvailable(conversationNo);

        LocalDateTime now = LocalDateTime.now();
        FeConversation created = new FeConversation();
        created.setConversationNo(conversationNo);
        created.setUserId(userId);
        if (request != null && StringUtils.hasText(request.getTitle())) {
            created.setTitle(request.getTitle().trim());
        }
        created.setChatType(chatType);
        created.setStatus(STATUS_ACTIVE);
        created.setLastMessageAt(now);
        created.setCreateTime(now);
        created.setUpdateTime(now);
        try {
            feConversationMapper.insert(created);
        } catch (DuplicateKeyException ex) {
            throw new BizException(ErrorCode.BAD_REQUEST, "会话编号已存在，请更换后重试");
        }
        return toSummary(created);
    }

    /**
     * 按会话编号（= AI session_id / conversation_no）查询会话。
     */
    public FeConversation requireBySessionId(String sessionId) {
        if (!StringUtils.hasText(sessionId)) {
            throw new BizException(ErrorCode.BAD_REQUEST, "session_id 不能为空");
        }
        String conversationNo = normalizeConversationNo(sessionId.trim());
        FeConversation conversation = feConversationMapper.selectOne(new LambdaQueryWrapper<FeConversation>()
                .eq(FeConversation::getConversationNo, conversationNo)
                .last("LIMIT 1"));
        if (conversation == null) {
            throw new BizException(ErrorCode.NOT_FOUND, "会话不存在");
        }
        return conversation;
    }

    /**
     * 校验会话归属，供消息列表等只读接口使用（含已归档会话）。
     */
    public FeConversation requireOwned(Long userId, Long conversationId) {
        if (userId == null || conversationId == null) {
            throw new BizException(ErrorCode.NOT_FOUND, "会话不存在");
        }
        FeConversation conversation = feConversationMapper.selectById(conversationId);
        if (conversation == null || !userId.equals(conversation.getUserId())) {
            throw new BizException(ErrorCode.NOT_FOUND, "会话不存在");
        }
        return conversation;
    }

    /**
     * 校验会话归属与状态，供落库聊天接口使用。
     */
    public FeConversation requireOwnedActive(Long userId, Long conversationId) {
        FeConversation conversation = requireOwned(userId, conversationId);
        if (!STATUS_ACTIVE.equals(conversation.getStatus())) {
            throw new BizException(ErrorCode.BAD_REQUEST, "会话已归档，无法继续对话");
        }
        return conversation;
    }

    /**
     * 消息入库后刷新会话 {@code last_message_at}；首条 user 消息可自动生成标题。
     */
    @Transactional(rollbackFor = Exception.class)
    public void refreshAfterMessage(Long conversationId, String userTextForTitle) {
        if (conversationId == null) {
            return;
        }
        LocalDateTime now = LocalDateTime.now();
        FeConversation update = new FeConversation();
        update.setId(conversationId);
        update.setLastMessageAt(now);
        update.setUpdateTime(now);
        if (StringUtils.hasText(userTextForTitle)) {
            FeConversation current = feConversationMapper.selectById(conversationId);
            if (current != null && !StringUtils.hasText(current.getTitle())) {
                update.setTitle(buildTitleFromUserText(userTextForTitle));
            }
        }
        feConversationMapper.updateById(update);
    }

    /**
     * 用户发起 AI 对话时刷新会话记录。
     * <p>已存在则更新 {@code last_message_at}；不存在则按用户新建（无需企业绑定）。</p>
     */
    @Transactional(rollbackFor = Exception.class)
    public void touchFromChat(Long userId, String sessionId) {
        if (userId == null || !StringUtils.hasText(sessionId)) {
            return;
        }
        String conversationNo = normalizeConversationNo(sessionId.trim());
        FeConversation existing = feConversationMapper.selectOne(new LambdaQueryWrapper<FeConversation>()
                .eq(FeConversation::getConversationNo, conversationNo)
                .eq(FeConversation::getUserId, userId)
                .last("LIMIT 1"));
        LocalDateTime now = LocalDateTime.now();
        if (existing != null) {
            FeConversation update = new FeConversation();
            update.setId(existing.getId());
            update.setLastMessageAt(now);
            update.setUpdateTime(now);
            feConversationMapper.updateById(update);
            return;
        }
        insertConversation(userId, conversationNo, null, CHAT_TYPE_EMPLOYMENT, now);
    }

    private String resolveChatType(String chatType) {
        if (!StringUtils.hasText(chatType)) {
            return CHAT_TYPE_EMPLOYMENT;
        }
        String normalized = chatType.trim();
        if (!ALLOWED_CHAT_TYPES.contains(normalized)) {
            throw new BizException(ErrorCode.BAD_REQUEST, "不支持的对话类型：" + normalized);
        }
        return normalized;
    }

    private String resolveNewConversationNo(String conversationNo) {
        if (!StringUtils.hasText(conversationNo)) {
            return UUID.randomUUID().toString().replace("-", "");
        }
        return normalizeConversationNo(conversationNo.trim());
    }

    private void assertConversationNoAvailable(String conversationNo) {
        Long count = feConversationMapper.selectCount(new LambdaQueryWrapper<FeConversation>()
                .eq(FeConversation::getConversationNo, conversationNo));
        if (count != null && count > 0) {
            throw new BizException(ErrorCode.BAD_REQUEST, "会话编号已存在，请更换后重试");
        }
    }

    private void insertConversation(Long userId,
                                    String conversationNo,
                                    String title,
                                    String chatType,
                                    LocalDateTime now) {
        FeConversation created = new FeConversation();
        created.setConversationNo(conversationNo);
        created.setUserId(userId);
        created.setTitle(title);
        created.setChatType(chatType);
        created.setStatus(STATUS_ACTIVE);
        created.setLastMessageAt(now);
        created.setCreateTime(now);
        created.setUpdateTime(now);
        try {
            feConversationMapper.insert(created);
        } catch (DuplicateKeyException ex) {
            FeConversation retry = feConversationMapper.selectOne(new LambdaQueryWrapper<FeConversation>()
                    .eq(FeConversation::getConversationNo, conversationNo)
                    .eq(FeConversation::getUserId, userId)
                    .last("LIMIT 1"));
            if (retry != null) {
                FeConversation update = new FeConversation();
                update.setId(retry.getId());
                update.setLastMessageAt(now);
                update.setUpdateTime(now);
                feConversationMapper.updateById(update);
                return;
            }
            log.warn("会话编号冲突且无法复用 conversationNo={}", conversationNo);
            throw new BizException(ErrorCode.BAD_REQUEST, "会话编号已存在，请更换后重试");
        }
    }

    private ConversationSummaryResponse toSummary(FeConversation entity) {
        ConversationSummaryResponse response = new ConversationSummaryResponse();
        response.setId(entity.getId());
        response.setConversationNo(entity.getConversationNo());
        response.setTitle(entity.getTitle());
        response.setChatType(entity.getChatType());
        response.setStatus(entity.getStatus());
        response.setLastMessageAt(entity.getLastMessageAt());
        response.setCreateTime(entity.getCreateTime());
        return response;
    }

    private static String normalizeConversationNo(String sessionId) {
        if (sessionId.length() <= CONVERSATION_NO_MAX_LEN) {
            return sessionId;
        }
        return sessionId.substring(0, CONVERSATION_NO_MAX_LEN);
    }

    private static String buildTitleFromUserText(String userText) {
        if (!StringUtils.hasText(userText)) {
            return null;
        }
        String trimmed = userText.trim();
        return trimmed.length() <= 200 ? trimmed : trimmed.substring(0, 200);
    }
}
