package handlers

import (
	"encoding/json"
	"log"
	"messageService/internal/app/models"
	"messageService/internal/app/services"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
)

func RegisterMessageRoutes(router *mux.Router, svc services.MessageService, streamSvc services.StreamClient) {
	router.HandleFunc("/messages", GetAllMessages(svc, streamSvc)).Methods("GET")
	router.HandleFunc("/messages/{id}", GetMessage(svc, streamSvc)).Methods("GET")
	router.HandleFunc("/messages/all/{streamId}", GetMessagesByStreamID(svc, streamSvc)).Methods("GET")
	router.HandleFunc("/messages", CreateMessage(svc)).Methods("POST")
	router.HandleFunc("/messages/{id}", UpdateMessage(svc)).Methods("PUT")
	router.HandleFunc("/messages/{id}", DeleteMessage(svc)).Methods("DELETE")
}

// GetAllMessages godoc
// @Summary Получить все сообщения
// @Description Возвращает список всех сообщений
// @Tags messages
// @Accept  json
// @Produce  json
// @Success 200 {array} models.Message
// @Router /messages [get]
func GetAllMessages(svc services.MessageService, streamSvc services.StreamClient) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		messages, err := svc.GetAllMessages()
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		var response []models.MessageResponse
		for _, message := range messages {
			stream, err := streamSvc.GetStreamTitleByID(message.StreamID)
			log.Printf("Result: %s", stream)
			if err != nil {
				http.Error(w, "Stream not found", http.StatusNotFound)
				return
			}
			response = append(response, models.MessageResponse{
				ID:          message.ID,
				Content:     message.Content,
				StreamTitle: stream,
				CreatedAt:   message.CreatedAt,
			})
		}

		err = json.NewEncoder(w).Encode(response)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}

// GetMessagesByStreamID godoc
// @Summary Получить список сообщений по StreamID
// @Description Возвращает список сообщений с указанным StreamID
// @Tags messages
// @Accept  json
// @Produce  json
// @Param streamId path int true "StreamID сообщения"
// @Success 200 {array} models.MessageResponse
// @Router /messages/all/{streamId} [get]
func GetMessagesByStreamID(svc services.MessageService, streamSvc services.StreamClient) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		idStr := mux.Vars(r)["streamId"]
		id, err := strconv.Atoi(idStr)
		if err != nil {
			http.Error(w, "Invalid StreamID", http.StatusBadRequest)
			return
		}

		messages, err := svc.GetMessagesByStreamID(uint(id))
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		var response []models.MessageResponse
		for _, message := range messages {
			stream, err := streamSvc.GetStreamTitleByID(message.StreamID)
			if err != nil {
				http.Error(w, "Stream not found", http.StatusNotFound)
				return
			}
			response = append(response, models.MessageResponse{
				ID:          message.ID,
				Content:     message.Content,
				StreamTitle: stream,
				CreatedAt:   message.CreatedAt,
			})
		}

		err = json.NewEncoder(w).Encode(response)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}

// GetMessage godoc
// @Summary Получить сообщение по ID
// @Description Возвращает сообщение с указанным ID
// @Tags messages
// @Accept  json
// @Produce  json
// @Param id path int true "ID сообщения"
// @Success 200 {object} models.Message
// @Router /messages/{id} [get]
func GetMessage(svc services.MessageService, streamSvc services.StreamClient) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		idStr := mux.Vars(r)["id"]
		id, err := strconv.Atoi(idStr)
		if err != nil {
			http.Error(w, "Invalid ID", http.StatusBadRequest)
			return
		}

		message, err := svc.GetMessageByID(uint(id))
		if err != nil {
			http.Error(w, "Message not found", http.StatusNotFound)
			return
		}

		var response models.MessageResponse
		stream, err := streamSvc.GetStreamTitleByID(message.StreamID)
		if err != nil {
			http.Error(w, "Stream not found", http.StatusNotFound)
			return
		}

		response = models.MessageResponse{
			ID:          message.ID,
			Content:     message.Content,
			StreamTitle: stream,
			CreatedAt:   message.CreatedAt,
		}

		err = json.NewEncoder(w).Encode(response)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}

// CreateMessage godoc
// @Summary Создать сообщение
// @Description Создает новое сообщение
// @Tags messages
// @Accept  json
// @Produce  json
// @Param message body models.Message true "Данные сообщения"
// @Success 200 {object} models.Message
// @Router /messages [post]
func CreateMessage(svc services.MessageService) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var message models.Message
		err := json.NewDecoder(r.Body).Decode(&message)
		if err != nil {
			http.Error(w, "Failed to decode request body", http.StatusBadRequest)
			return
		}
		err = svc.CreateMessage(&message)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.WriteHeader(http.StatusCreated)
		err = json.NewEncoder(w).Encode(message)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}

// UpdateMessage godoc
// @Summary Обновить данные сообщения
// @Description Обновляет данные сообщения по ID
// @Tags messages
// @Accept  json
// @Produce  json
// @Param id path int true "ID сообщения"
// @Param message body models.Message true "Обновленные данные сообщения"
// @Success 200 {object} models.Message
// @Router /messages/{id} [put]
func UpdateMessage(svc services.MessageService) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var message models.Message
		idStr := mux.Vars(r)["id"]
		id, err := strconv.Atoi(idStr)
		if err != nil {
			http.Error(w, "Invalid ID", http.StatusBadRequest)
			return
		}

		if err := json.NewDecoder(r.Body).Decode(&message); err != nil {
			http.Error(w, "Failed to decode request body", http.StatusBadRequest)
			return
		}
		message.ID = uint(id)
		err = svc.UpdateMessage(&message)
		if err != nil {
			http.Error(w, "Message not found", http.StatusNotFound)
			return
		}
		err = json.NewEncoder(w).Encode(message)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}

// DeleteMessage godoc
// @Summary Удалить сообщение
// @Description Удаляет сообщение по ID
// @Tags messages
// @Accept  json
// @Produce  json
// @Param id path int true "ID сообщения"
// @Success 204 "No Content"
// @Router /messages/{id} [delete]
func DeleteMessage(svc services.MessageService) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		idStr := mux.Vars(r)["id"]
		id, err := strconv.Atoi(idStr)
		if err != nil {
			http.Error(w, "Invalid ID", http.StatusBadRequest)
			return
		}
		err = svc.DeleteMessage(uint(id))
		if err != nil {
			http.Error(w, "Message not found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusNoContent)
	}
}
