package tipos_eventos

import (
	"context"
	"errors"
	"strconv"

	"photum-backend/internal/db/generated"

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

type Service struct {
	queries *generated.Queries
}

func NewService(queries *generated.Queries) *Service {
	return &Service{queries: queries}
}

// Event CRUD

func (s *Service) Create(ctx context.Context, nome string, regiao string) (*generated.TiposEvento, error) {
	event, err := s.queries.CreateTipoEvento(ctx, generated.CreateTipoEventoParams{
		Nome:   nome,
		Regiao: pgtype.Text{String: regiao, Valid: true},
	})
	if err != nil {
		return nil, err
	}
	return &event, nil
}

func (s *Service) List(ctx context.Context, regiao string) ([]generated.TiposEvento, error) {
	return s.queries.ListTiposEventos(ctx, pgtype.Text{String: regiao, Valid: true})
}

func (s *Service) GetByID(ctx context.Context, id string, regiao string) (*generated.TiposEvento, error) {
	uuidVal, err := uuid.Parse(id)
	if err != nil {
		return nil, errors.New("invalid id")
	}
	event, err := s.queries.GetTipoEventoByID(ctx, generated.GetTipoEventoByIDParams{
		ID:     pgtype.UUID{Bytes: uuidVal, Valid: true},
		Regiao: pgtype.Text{String: regiao, Valid: true},
	})
	if err != nil {
		return nil, err
	}
	return &event, nil
}

func (s *Service) Update(ctx context.Context, id, nome string, regiao string) (*generated.TiposEvento, error) {
	uuidVal, err := uuid.Parse(id)
	if err != nil {
		return nil, errors.New("invalid id")
	}
	event, err := s.queries.UpdateTipoEvento(ctx, generated.UpdateTipoEventoParams{
		ID:     pgtype.UUID{Bytes: uuidVal, Valid: true},
		Nome:   nome,
		Regiao: pgtype.Text{String: regiao, Valid: true},
	})
	if err != nil {
		return nil, err
	}
	return &event, nil
}

func (s *Service) Delete(ctx context.Context, id string, regiao string) error {
	uuidVal, err := uuid.Parse(id)
	if err != nil {
		return errors.New("invalid id")
	}
	return s.queries.DeleteTipoEvento(ctx, generated.DeleteTipoEventoParams{
		ID:     pgtype.UUID{Bytes: uuidVal, Valid: true},
		Regiao: pgtype.Text{String: regiao, Valid: true},
	})
}

// Pricing Logic

type PriceInput struct {
	TipoEventoID         string  `json:"tipo_evento_id"`
	FuncaoProfissionalID string  `json:"funcao_profissional_id"`
	Valor                float64 `json:"valor"`
}

func (s *Service) SetPrice(ctx context.Context, input PriceInput, regiao string) (*generated.PrecosTiposEvento, error) {
	eventoUUID, err := uuid.Parse(input.TipoEventoID)
	if err != nil {
		return nil, errors.New("invalid tipo_evento_id")
	}
	funcaoUUID, err := uuid.Parse(input.FuncaoProfissionalID)
	if err != nil {
		return nil, errors.New("invalid funcao_profissional_id")
	}

	precio, err := s.queries.CreatePrecoEvento(ctx, generated.CreatePrecoEventoParams{
		TipoEventoID:         pgtype.UUID{Bytes: eventoUUID, Valid: true},
		FuncaoProfissionalID: pgtype.UUID{Bytes: funcaoUUID, Valid: true},
		Valor:                toPgNumeric(input.Valor),
		Regiao:               pgtype.Text{String: regiao, Valid: true},
	})
	if err != nil {
		return nil, err
	}
	return &precio, nil
}

func (s *Service) ListPrices(ctx context.Context, eventoID string) ([]generated.ListPrecosByEventoIDRow, error) {
	eventoUUID, err := uuid.Parse(eventoID)
	if err != nil {
		return nil, errors.New("invalid evento_id")
	}
	return s.queries.ListPrecosByEventoID(ctx, pgtype.UUID{Bytes: eventoUUID, Valid: true})
}

// Helper (Assuming user doesn't have it in shared utils or similar)
func toPgNumeric(f float64) pgtype.Numeric {
	var n pgtype.Numeric
	// Convert to string first to ensure precise scanning
	s := strconv.FormatFloat(f, 'f', -1, 64)
	if err := n.Scan(s); err != nil {
		// Fallback or log if needed, but for valid floats this should work.
		// Returning invalid (NULL) numeric if scan fails.
		return pgtype.Numeric{Valid: false}
	}
	return n
}
