package cadastro_fot

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}
}

type CreateInput struct {
	Fot            int32   `json:"fot"`
	EmpresaID      string  `json:"empresa_id"`
	CursoID        string  `json:"curso_id"`
	AnoFormaturaID string  `json:"ano_formatura_id"`
	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"`
}

func (s *Service) Create(ctx context.Context, input CreateInput) (*generated.CadastroFot, error) {
	empresaUUID, _ := uuid.Parse(input.EmpresaID)
	cursoUUID, _ := uuid.Parse(input.CursoID)
	anoUUID, _ := uuid.Parse(input.AnoFormaturaID)

	res, err := s.queries.CreateCadastroFot(ctx, generated.CreateCadastroFotParams{
		Fot:            input.Fot,
		EmpresaID:      pgtype.UUID{Bytes: empresaUUID, Valid: true},
		CursoID:        pgtype.UUID{Bytes: cursoUUID, Valid: true},
		AnoFormaturaID: pgtype.UUID{Bytes: anoUUID, Valid: true},
		Instituicao:    pgtype.Text{String: input.Instituicao, Valid: true},
		Cidade:         pgtype.Text{String: input.Cidade, Valid: true},
		Estado:         pgtype.Text{String: input.Estado, Valid: true},
		Observacoes:    pgtype.Text{String: input.Observacoes, Valid: true},
		GastosCaptacao: toPgNumeric(input.GastosCaptacao),
		PreVenda:       pgtype.Bool{Bool: input.PreVenda, Valid: true},
	})
	if err != nil {
		return nil, err
	}
	return &res, nil
}

func (s *Service) List(ctx context.Context) ([]generated.ListCadastroFotRow, error) {
	return s.queries.ListCadastroFot(ctx)
}

func (s *Service) ListByEmpresa(ctx context.Context, empresaID string) ([]generated.ListCadastroFotByEmpresaRow, error) {
	uuidVal, err := uuid.Parse(empresaID)
	if err != nil {
		return nil, errors.New("invalid empresa_id")
	}
	// Note: ListCadastroFotByEmpresaRow is nearly identical to ListCadastroFotRow but we use the generated type
	return s.queries.ListCadastroFotByEmpresa(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
}

func (s *Service) GetByID(ctx context.Context, id string) (*generated.GetCadastroFotByIDRow, error) {
	uuidVal, err := uuid.Parse(id)
	if err != nil {
		return nil, errors.New("invalid id")
	}
	item, err := s.queries.GetCadastroFotByID(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
	return &item, err
}

func (s *Service) Update(ctx context.Context, id string, input CreateInput) (*generated.CadastroFot, error) {
	uuidVal, err := uuid.Parse(id)
	if err != nil {
		return nil, errors.New("invalid id")
	}
	empresaUUID, _ := uuid.Parse(input.EmpresaID)
	cursoUUID, _ := uuid.Parse(input.CursoID)
	anoUUID, _ := uuid.Parse(input.AnoFormaturaID)

	item, err := s.queries.UpdateCadastroFot(ctx, generated.UpdateCadastroFotParams{
		ID:             pgtype.UUID{Bytes: uuidVal, Valid: true},
		Fot:            input.Fot,
		EmpresaID:      pgtype.UUID{Bytes: empresaUUID, Valid: true},
		CursoID:        pgtype.UUID{Bytes: cursoUUID, Valid: true},
		AnoFormaturaID: pgtype.UUID{Bytes: anoUUID, Valid: true},
		Instituicao:    pgtype.Text{String: input.Instituicao, Valid: true},
		Cidade:         pgtype.Text{String: input.Cidade, Valid: true},
		Estado:         pgtype.Text{String: input.Estado, Valid: true},
		Observacoes:    pgtype.Text{String: input.Observacoes, Valid: true},
		GastosCaptacao: toPgNumeric(input.GastosCaptacao),
		PreVenda:       pgtype.Bool{Bool: input.PreVenda, Valid: true},
	})
	return &item, err
}

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

// Helper to convert float to numeric robustly
func toPgNumeric(f float64) pgtype.Numeric {
	var n pgtype.Numeric
	s := strconv.FormatFloat(f, 'f', -1, 64)
	if err := n.Scan(s); err != nil {
		return pgtype.Numeric{Valid: false}
	}
	return n
}
