package repository

import (
	"context"

	dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
	"github.com/jackc/pgx/v5/pgtype"
)

func convertDBTicket(ticket dbgen.Ticket) domain.Ticket {
	return domain.Ticket{
		ID:        ticket.ID,
		Amount:    domain.Currency(ticket.Amount),
		TotalOdds: ticket.TotalOdds,
	}
}

func convertDBTicketOutcomes(ticket dbgen.TicketWithOutcome) domain.GetTicket {

	var outcomes []domain.TicketOutcome = make([]domain.TicketOutcome, 0, len(ticket.Outcomes))

	for _, outcome := range ticket.Outcomes {
		outcomes = append(outcomes, domain.TicketOutcome{
			ID:           outcome.ID,
			TicketID:     outcome.TicketID,
			EventID:      outcome.EventID,
			OddID:        outcome.OddID,
			HomeTeamName: outcome.HomeTeamName,
			AwayTeamName: outcome.AwayTeamName,
			MarketID:     outcome.MarketID,
			MarketName:   outcome.MarketName,
			Odd:          outcome.Odd,
			OddName:      outcome.OddName,
			OddHeader:    outcome.OddHeader,
			OddHandicap:  outcome.OddHandicap,
			Status:       domain.OutcomeStatus(outcome.Status),
			Expires:      outcome.Expires.Time,
		})
	}
	return domain.GetTicket{
		ID:        ticket.ID,
		Amount:    domain.Currency(ticket.Amount),
		TotalOdds: ticket.TotalOdds,
		Outcomes:  outcomes,
	}
}

func convertDBCreateTicketOutcome(ticketOutcome domain.CreateTicketOutcome) dbgen.CreateTicketOutcomeParams {
	return dbgen.CreateTicketOutcomeParams{
		TicketID:     ticketOutcome.TicketID,
		EventID:      ticketOutcome.EventID,
		OddID:        ticketOutcome.OddID,
		HomeTeamName: ticketOutcome.HomeTeamName,
		AwayTeamName: ticketOutcome.AwayTeamName,
		MarketID:     ticketOutcome.MarketID,
		MarketName:   ticketOutcome.MarketName,
		Odd:          ticketOutcome.Odd,
		OddName:      ticketOutcome.OddName,
		OddHeader:    ticketOutcome.OddHeader,
		OddHandicap:  ticketOutcome.OddHandicap,
		Expires: pgtype.Timestamp{
			Time:  ticketOutcome.Expires,
			Valid: true,
		},
	}
}

func convertCreateTicket(ticket domain.CreateTicket) dbgen.CreateTicketParams {
	return dbgen.CreateTicketParams{
		Amount:    int64(ticket.Amount),
		TotalOdds: ticket.TotalOdds,
		Ip:        ticket.IP,
	}
}

func (s *Store) CreateTicket(ctx context.Context, ticket domain.CreateTicket) (domain.Ticket, error) {

	newTicket, err := s.queries.CreateTicket(ctx, convertCreateTicket(ticket))
	if err != nil {
		return domain.Ticket{}, err
	}
	return convertDBTicket(newTicket), err

}

func (s *Store) CreateTicketOutcome(ctx context.Context, outcomes []domain.CreateTicketOutcome) (int64, error) {

	var dbParams []dbgen.CreateTicketOutcomeParams = make([]dbgen.CreateTicketOutcomeParams, 0, len(outcomes))
	for _, outcome := range outcomes {
		dbParams = append(dbParams, convertDBCreateTicketOutcome(outcome))
	}

	rows, err := s.queries.CreateTicketOutcome(ctx, dbParams)

	if err != nil {
		return rows, err
	}

	return rows, nil
}

func (s *Store) GetTicketByID(ctx context.Context, id int64) (domain.GetTicket, error) {
	ticket, err := s.queries.GetTicketByID(ctx, id)

	if err != nil {
		return domain.GetTicket{}, err
	}

	return convertDBTicketOutcomes(ticket), nil
}

func (s *Store) GetAllTickets(ctx context.Context) ([]domain.GetTicket, error) {
	tickets, err := s.queries.GetAllTickets(ctx)
	if err != nil {
		return nil, err
	}

	var result []domain.GetTicket = make([]domain.GetTicket, 0, len(tickets))
	for _, ticket := range tickets {
		result = append(result, convertDBTicketOutcomes(ticket))
	}

	return result, nil
}

func (s *Store) CountTicketByIP(ctx context.Context, IP string) (int64, error) {
	count, err := s.queries.CountTicketByIP(ctx, IP)

	if err != nil {
		return 0, err
	}

	return count, err
}

func (s *Store) UpdateTicketOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error {
	err := s.queries.UpdateTicketOutcomeStatus(ctx, dbgen.UpdateTicketOutcomeStatusParams{
		Status: int32(status),
		ID:     id,
	})
	return err
}

func (s *Store) DeleteOldTickets(ctx context.Context) error {
	return s.queries.DeleteOldTickets(ctx)
}

func (s *Store) DeleteTicket(ctx context.Context, id int64) error {
	return s.queries.DeleteTicket(ctx, id)
}
