package logistica

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

type Handler struct {
	service *Service
}

func NewHandler(service *Service) *Handler {
	return &Handler{service: service}
}

// CreateCarro
func (h *Handler) CreateCarro(c *gin.Context) {
	var req CreateCarroInput
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	carro, err := h.service.CreateCarro(c.Request.Context(), req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"id": uuid.UUID(carro.ID.Bytes).String()})
}

// ListCarros
func (h *Handler) ListCarros(c *gin.Context) {
	agendaID := c.Query("agenda_id")
	if agendaID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "agenda_id is required"})
		return
	}

	carros, err := h.service.ListCarros(c.Request.Context(), agendaID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Fetch passengers for each car? Or let frontend do it on demand?
	// For main list, efficient to just list cars, or maybe passengers embedded.
	// For simplicity, let's embed passengers if possible, but list returns row.
	// We will return list of cars. The frontend can fetch passengers per car or we should use a transaction/composite query.
	// MVP: Check if we can just return the cars now.

	resp := make([]map[string]interface{}, len(carros))
	for i, car := range carros {
		var driverName string
		// Logic: if system driver name exists, use it. Else use custom name.
		if car.MotoristaNomeSistema.String != "" {
			driverName = car.MotoristaNomeSistema.String
		} else {
			driverName = car.NomeMotorista.String
		}

		var avatar string
		if car.MotoristaAvatar.Valid {
			avatar = car.MotoristaAvatar.String
		}

		resp[i] = map[string]interface{}{
			"id":            uuid.UUID(car.ID.Bytes).String(),
			"agenda_id":     uuid.UUID(car.AgendaID.Bytes).String(),
			"driver_id":     uuid.UUID(car.MotoristaID.Bytes).String(), // May be empty UUID or nil representation
			"driver_name":   driverName,
			"driver_avatar": avatar,
			"arrival_time":  car.HorarioChegada.String,
			"notes":         car.Observacoes.String,
		}
	}

	c.JSON(http.StatusOK, resp)
}

// DeleteCarro
func (h *Handler) DeleteCarro(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "id required"})
		return
	}
	if err := h.service.DeleteCarro(c.Request.Context(), id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "deleted"})
}

// UpdateCarro
func (h *Handler) UpdateCarro(c *gin.Context) {
	id := c.Param("id")
	var req UpdateCarroInput
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	_, err := h.service.UpdateCarro(c.Request.Context(), id, req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "updated"})
}

// Passengers
type AddPassengerInput struct {
	ProfissionalID string `json:"profissional_id"`
}

func (h *Handler) AddPassenger(c *gin.Context) {
	carID := c.Param("id")
	var req AddPassengerInput
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	err := h.service.AddPassageiro(c.Request.Context(), carID, req.ProfissionalID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "passenger added"})
}

func (h *Handler) RemovePassenger(c *gin.Context) {
	carID := c.Param("id")
	profID := c.Param("profID")
	err := h.service.RemovePassageiro(c.Request.Context(), carID, profID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "passenger removed"})
}

func (h *Handler) ListPassengers(c *gin.Context) {
	carID := c.Param("id")
	passengers, err := h.service.ListPassageiros(c.Request.Context(), carID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	resp := make([]map[string]interface{}, len(passengers))
	for i, p := range passengers {
		resp[i] = map[string]interface{}{
			"id":              uuid.UUID(p.ID.Bytes).String(),
			"profissional_id": uuid.UUID(p.ProfissionalID.Bytes).String(),
			"name":            p.Nome,
			"avatar_url":      p.AvatarUrl.String,
			"role":            p.FuncaoNome.String,
		}
	}
	c.JSON(http.StatusOK, resp)
}
