package cadastro_fot

import (
	"net/http"

	"photum-backend/internal/db/generated"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/jackc/pgx/v5/pgtype"
)

type Handler struct {
	service *Service
}

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

type CadastroFotResponse struct {
	ID                string  `json:"id"`
	Fot               string  `json:"fot"`
	EmpresaID         string  `json:"empresa_id"`
	EmpresaNome       string  `json:"empresa_nome,omitempty"`
	CursoID           string  `json:"curso_id"`
	CursoNome         string  `json:"curso_nome,omitempty"`
	AnoFormaturaID    string  `json:"ano_formatura_id"`
	AnoFormaturaLabel string  `json:"ano_formatura_label,omitempty"`
	Instituicao       string  `json:"instituicao"`
	Cidade            string  `json:"cidade"`
	Estado            string  `json:"estado"`
	Observacoes       string  `json:"observacoes"`
	GastosCaptacao    float64 `json:"gastos_captacao"`
	PreVenda          bool    `json:"pre_venda"`
	Finalizada        bool    `json:"finalizada"`
}

func fromPgNumeric(n pgtype.Numeric) float64 {
	f, _ := n.Float64Value()
	return f.Float64
}

// Map Create result (no joins)
func toResponse(c generated.CadastroFot) CadastroFotResponse {
	return CadastroFotResponse{
		ID:             uuid.UUID(c.ID.Bytes).String(),
		Fot:            c.Fot,
		EmpresaID:      uuid.UUID(c.EmpresaID.Bytes).String(),
		CursoID:        uuid.UUID(c.CursoID.Bytes).String(),
		AnoFormaturaID: uuid.UUID(c.AnoFormaturaID.Bytes).String(),
		Instituicao:    c.Instituicao.String,
		Cidade:         c.Cidade.String,
		Estado:         c.Estado.String,
		Observacoes:    c.Observacoes.String,
		GastosCaptacao: fromPgNumeric(c.GastosCaptacao),
		PreVenda:       c.PreVenda.Bool,
		Finalizada:     c.Finalizada.Bool,
	}
}

// Map List result (with joins)
func toListResponse(r generated.ListCadastroFotRow) CadastroFotResponse {
	return CadastroFotResponse{
		ID:                uuid.UUID(r.ID.Bytes).String(),
		Fot:               r.Fot,
		EmpresaID:         uuid.UUID(r.EmpresaID.Bytes).String(),
		EmpresaNome:       r.EmpresaNome,
		CursoID:           uuid.UUID(r.CursoID.Bytes).String(),
		CursoNome:         r.CursoNome,
		AnoFormaturaID:    uuid.UUID(r.AnoFormaturaID.Bytes).String(),
		AnoFormaturaLabel: r.AnoFormaturaLabel,
		Instituicao:       r.Instituicao.String,
		Cidade:            r.Cidade.String,
		Estado:            r.Estado.String,
		Observacoes:       r.Observacoes.String,
		GastosCaptacao:    fromPgNumeric(r.GastosCaptacao),
		PreVenda:          r.PreVenda.Bool,
		Finalizada:        r.Finalizada.Bool,
	}
}

// Map GetByID result
func toGetResponse(r generated.GetCadastroFotByIDRow) CadastroFotResponse {
	return CadastroFotResponse{
		ID:                uuid.UUID(r.ID.Bytes).String(),
		Fot:               r.Fot,
		EmpresaID:         uuid.UUID(r.EmpresaID.Bytes).String(),
		EmpresaNome:       r.EmpresaNome,
		CursoID:           uuid.UUID(r.CursoID.Bytes).String(),
		CursoNome:         r.CursoNome,
		AnoFormaturaID:    uuid.UUID(r.AnoFormaturaID.Bytes).String(),
		AnoFormaturaLabel: r.AnoFormaturaLabel,
		Instituicao:       r.Instituicao.String,
		Cidade:            r.Cidade.String,
		Estado:            r.Estado.String,
		Observacoes:       r.Observacoes.String,
		GastosCaptacao:    fromPgNumeric(r.GastosCaptacao),
		PreVenda:          r.PreVenda.Bool,
		Finalizada:        r.Finalizada.Bool,
	}
}

// Create godoc
// @Summary      Create a new FOT record
// @Tags         cadastro_fot
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        request body CreateInput true "FOT Data"
// @Success      201  {object}  CadastroFotResponse
// @Router       /api/cadastro-fot [post]
func (h *Handler) Create(c *gin.Context) {
	var req CreateInput
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	regiao := c.GetString("regiao")
	if regiao == "" {
		regiao = c.GetHeader("x-regiao")
	}
	if regiao == "" {
		regiao = "SP"
	}
	res, err := h.service.Create(c.Request.Context(), req, regiao)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, toResponse(*res))
}

// List godoc
// @Summary      List all FOT records
// @Tags         cadastro_fot
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        empresa_id query string false "Filter by Company ID"
// @Success      200  {array}  CadastroFotResponse
// @Router       /api/cadastro-fot [get]
func (h *Handler) List(c *gin.Context) {
	empresaID := c.Query("empresa_id")
	regiao := c.GetString("regiao")
	if regiao == "" {
		regiao = c.GetHeader("x-regiao")
	}
	if regiao == "" {
		regiao = "SP"
	}

	var response []CadastroFotResponse

	if empresaID != "" {
		rows, err := h.service.ListByEmpresa(c.Request.Context(), empresaID, regiao)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}
		// Conversion for specific row type
		for _, r := range rows {
			response = append(response, CadastroFotResponse{
				ID:                uuid.UUID(r.ID.Bytes).String(),
				Fot:               r.Fot,
				EmpresaID:         uuid.UUID(r.EmpresaID.Bytes).String(),
				EmpresaNome:       r.EmpresaNome,
				CursoID:           uuid.UUID(r.CursoID.Bytes).String(),
				CursoNome:         r.CursoNome,
				AnoFormaturaID:    uuid.UUID(r.AnoFormaturaID.Bytes).String(),
				AnoFormaturaLabel: r.AnoFormaturaLabel,
				Instituicao:       r.Instituicao.String,
				Cidade:            r.Cidade.String,
				Estado:            r.Estado.String,
				Observacoes:       r.Observacoes.String,
				GastosCaptacao:    fromPgNumeric(r.GastosCaptacao),
				PreVenda:          r.PreVenda.Bool,
				Finalizada:        r.Finalizada.Bool,
			})
		}
	} else {
		rows, err := h.service.List(c.Request.Context(), regiao)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}
		for _, r := range rows {
			response = append(response, toListResponse(r))
		}
	}

	c.JSON(http.StatusOK, response)
}

// Get godoc
// @Summary      Get FOT record by ID
// @Tags         cadastro_fot
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id   path      string  true  "ID"
// @Success      200  {object}  CadastroFotResponse
// @Router       /api/cadastro-fot/{id} [get]
func (h *Handler) Get(c *gin.Context) {
	id := c.Param("id")
	regiao := c.GetString("regiao")
	res, err := h.service.GetByID(c.Request.Context(), id, regiao)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Record not found"})
		return
	}
	c.JSON(http.StatusOK, toGetResponse(*res))
}

// Update godoc
// @Summary      Update FOT record
// @Tags         cadastro_fot
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id       path      string       true  "ID"
// @Param        request  body      CreateInput  true  "Data"
// @Success      200      {object}  CadastroFotResponse
// @Router       /api/cadastro-fot/{id} [put]
func (h *Handler) Update(c *gin.Context) {
	id := c.Param("id")
	var req CreateInput
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	regiao := c.GetString("regiao")
	res, err := h.service.Update(c.Request.Context(), id, req, regiao)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, toResponse(*res))
}

// Delete godoc
// @Summary      Delete FOT record
// @Tags         cadastro_fot
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id   path      string  true  "ID"
// @Success      204
// @Router       /api/cadastro-fot/{id} [delete]
func (h *Handler) Delete(c *gin.Context) {
	id := c.Param("id")
	regiao := c.GetString("regiao")
	err := h.service.Delete(c.Request.Context(), id, regiao)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusNoContent, nil)
}

// Import godoc
// @Summary      Import FOT data
// @Tags         cadastro_fot
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        request body []ImportInput true "List of FOTs"
// @Success      200 {object} ImportResult
// @Router       /api/import/fot [post]
func (h *Handler) Import(c *gin.Context) {
	var req []ImportInput
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	regiao := c.GetString("regiao")
	res := h.service.BatchImport(c.Request.Context(), req, regiao)
	c.JSON(http.StatusOK, res)
}

// ToggleFinalizada godoc
// @Summary      Toggle FOT finalized status
// @Tags         cadastro_fot
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id   path      string  true  "ID"
// @Param        status body object{finalizada=boolean} true "Status"
// @Success      200  {object}  CadastroFotResponse
// @Router       /api/cadastro-fot/{id}/finalize [post]
func (h *Handler) ToggleFinalizada(c *gin.Context) {
	id := c.Param("id")
	var req struct {
		Finalizada bool `json:"finalizada"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	regiao := c.GetString("regiao")
	// Using headers/context for region if not set
	if regiao == "" {
		regiao = c.GetHeader("x-regiao")
	}
	if regiao == "" {
		regiao = "SP"
	}

	res, err := h.service.ToggleFinalizada(c.Request.Context(), id, req.Finalizada, regiao)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, toResponse(*res))
}
