package com.petshop.backend.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.petshop.backend.entity.Conversation;
import com.petshop.backend.entity.Message;
import com.petshop.backend.entity.User;
import com.petshop.backend.repository.MessageRepository;
import com.petshop.backend.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

@Service
public class OpenRouterAiService {
    private static final Logger log = LoggerFactory.getLogger(OpenRouterAiService.class);
    private static final String BOT_USERNAME = "ai.bot";

    @Value("${openrouter.api-key:}")
    private String apiKey;

    @Value("${openrouter.model:openai/gpt-oss-120b:free}")
    private String model;

    private final String openRouterUrl = "https://openrouter.ai/api/v1/chat/completions";
    private final ChatService chatService;
    private final ChatRealtimeService chatRealtimeService;
    private final MessageRepository messageRepository;
    private final UserRepository userRepository;
    private final ObjectMapper objectMapper;
    private final HttpClient httpClient;

    public OpenRouterAiService(
        ChatService chatService,
        ChatRealtimeService chatRealtimeService,
        MessageRepository messageRepository,
        UserRepository userRepository
    ) {
        this.chatService = chatService;
        this.chatRealtimeService = chatRealtimeService;
        this.messageRepository = messageRepository;
        this.userRepository = userRepository;
        this.objectMapper = JsonMapper.builder().findAndAddModules().build();
        this.httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();
    }

    public void generateAndSendReply(Long conversationId, Long triggerMessageId) {
        CompletableFuture.runAsync(() -> generateReply(conversationId, triggerMessageId));
    }

    private void generateReply(Long conversationId, Long triggerMessageId) {
        try {
            if (triggerMessageId == null) {
                return;
            }
            if (apiKey == null || apiKey.isBlank()) {
                log.debug("Skipping OpenRouter reply for conversation {} because no API key is configured", conversationId);
                return;
            }
            if (model == null || model.isBlank()) {
                log.warn("Skipping OpenRouter reply for conversation {} because no model is configured", conversationId);
                return;
            }

            Conversation conversation = chatService.getConversationEntity(conversationId);
            if (conversation.getStatus() == Conversation.ConversationStatus.CLOSED) {
                return;
            }
            if (conversation.getHumanRequestedAt() != null) {
                return;
            }
            if (conversation.getMode() != Conversation.ConversationMode.AUTOMATED) {
                return;
            }

            User botUser = userRepository.findByUsername(BOT_USERNAME)
                .orElseThrow(() -> new IllegalStateException("Bot user not found"));

            Message triggerMessage = messageRepository.findById(triggerMessageId).orElse(null);
            if (triggerMessage == null || !conversationId.equals(triggerMessage.getConversationId())) {
                return;
            }

            List<Message> history = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId);
            if (history.isEmpty()) {
                return;
            }

            Message lastMessage = history.get(history.size() - 1);
            if (!triggerMessageId.equals(lastMessage.getId())) {
                return;
            }
            String lastContent = normalizeContent(lastMessage.getContent());
            if (lastContent.isBlank()) {
                return;
            }
            if (lastMessage.getSenderId() != null && lastMessage.getSenderId().equals(botUser.getId())) {
                return;
            }

            User lastSender = userRepository.findById(lastMessage.getSenderId()).orElse(null);
            if (lastSender == null || lastSender.getRole() != User.Role.CUSTOMER) {
                return;
            }

            List<Map<String, String>> messages = new ArrayList<>();
            messages.add(Map.of(
                "role", "system",
                "content", "You are a helpful pet shop assistant. Provide concise and friendly answers. Do not output markdown, just plain text."
            ));

            for (Message message : history) {
                messages.add(Map.of(
                    "role", resolveRole(message, botUser.getId()),
                    "content", normalizeContent(message.getContent())
                ));
            }

            Map<String, Object> requestBody = Map.of(
                "model", model,
                "messages", messages
            );

            String requestJson = objectMapper.writeValueAsString(requestBody);
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(openRouterUrl))
                .header("Content-Type", "application/json")
                .header("Authorization", "Bearer " + apiKey)
                .timeout(Duration.ofSeconds(30))
                .POST(HttpRequest.BodyPublishers.ofString(requestJson))
                .build();

            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() != 200) {
                log.warn("OpenRouter API returned {} for conversation {}", response.statusCode(), conversationId);
                return;
            }

            JsonNode responseNode = objectMapper.readTree(response.body());
            String replyContent = responseNode.path("choices").path(0).path("message").path("content").asText("");
            replyContent = normalizeContent(replyContent);
            if (replyContent.isBlank()) {
                return;
            }

            Conversation latestConversation = chatService.getConversationEntity(conversationId);
            if (latestConversation.getStatus() == Conversation.ConversationStatus.CLOSED
                || latestConversation.getHumanRequestedAt() != null
                || latestConversation.getMode() != Conversation.ConversationMode.AUTOMATED) {
                return;
            }

            List<Message> latestHistory = messageRepository.findByConversationIdOrderByTimestampAsc(conversationId);
            if (latestHistory.isEmpty() || !triggerMessageId.equals(latestHistory.get(latestHistory.size() - 1).getId())) {
                return;
            }

            var messageResponse = chatService.saveBotMessage(conversationId, replyContent);
            chatRealtimeService.publishMessage(conversationId, messageResponse);
            chatRealtimeService.publishConversationUpdate(conversationId);
        } catch (Exception ex) {
            log.error("Failed to generate OpenRouter reply for conversation {}", conversationId, ex);
        }
    }

    private String resolveRole(Message message, Long botUserId) {
        if (message.getSenderId() != null && message.getSenderId().equals(botUserId)) {
            return "assistant";
        }
        return "user";
    }

    private String normalizeContent(String content) {
        return content == null ? "" : content.trim();
    }
}
