package repository import ( "context" "fmt" "time" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/jackc/pgx/v5/pgtype" "github.com/SamuelTariku/FortuneBet-Backend/internal/ports" ) // Interface for creating new old repository repo interface // We need to have an external definition of the repository or else we can't reuse the interface func NewOldRepositoryStore(s *Store) ports.OldReportRepository { return s } // type ReportRepository interface { // GenerateReport(timeFrame domain.ReportTimeFrame, start, end time.Time) (*domain.Report, error) // SaveReport(report *domain.Report) error // FindReportsByTimeFrame(timeFrame domain.ReportTimeFrame, limit int) ([]*domain.Report, error) // GetTotalCashOutInRange(ctx context.Context, from, to time.Time) (float64, error) // GetTotalCashMadeInRange(ctx context.Context, from, to time.Time) (float64, error) // GetTotalCashBacksInRange(ctx context.Context, from, to time.Time) (float64, error) // GetTotalBetsMadeInRange(ctx context.Context, from, to time.Time) (int64, error) // GetVirtualGameSummaryInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetVirtualGameSummaryInRangeRow, error) // GetAllTicketsInRange(ctx context.Context, from, to time.Time) (dbgen.GetAllTicketsInRangeRow, error) // GetWalletTransactionsInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetWalletTransactionsInRangeRow, error) // GetCompanyWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetCompanyWiseReportRow, error) // GetBranchWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetBranchWiseReportRow, error) // } // type ReportRepo struct { // store *Store // } // func NewReportRepo(store *Store) ReportRepository { // return &ReportRepo{store: store} // } func (s *Store) GenerateReport(timeFrame domain.ReportTimeFrame, start, end time.Time) (*domain.Report, error) { // Implement SQL queries to calculate metrics var report domain.Report // Total Bets err := s.conn.QueryRow( context.Background(), `SELECT COUNT(*) FROM bets WHERE created_at BETWEEN $1 AND $2`, start, end).Scan(&report.TotalBets) if err != nil { return nil, err } // Total Cash In err = s.conn.QueryRow( context.Background(), `SELECT COALESCE(SUM(amount), 0) FROM transactions WHERE type = 'stake' AND created_at BETWEEN $1 AND $2`, start, end).Scan(&report.TotalCashIn) if err != nil { return nil, err } // Similar queries for Cash Out and Cash Back... report.TimeFrame = timeFrame report.PeriodStart = start report.PeriodEnd = end report.GeneratedAt = time.Now() return &report, nil } func (s *Store) SaveReport(report *domain.Report) error { _, err := s.conn.Exec( context.Background(), `INSERT INTO reports (id, time_frame, period_start, period_end, total_bets, total_cash_in, total_cash_out, total_cash_back, generated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`, report.ID, report.TimeFrame, report.PeriodStart, report.PeriodEnd, report.TotalBets, report.TotalCashIn, report.TotalCashOut, report.TotalCashBack, report.GeneratedAt) return err } func (s *Store) FindReportsByTimeFrame(timeFrame domain.ReportTimeFrame, limit int) ([]*domain.Report, error) { rows, err := s.conn.Query( context.Background(), `SELECT id, time_frame, period_start, period_end, total_bets, total_cash_in, total_cash_out, total_cash_back, generated_at FROM reports WHERE time_frame = $1 ORDER BY generated_at DESC LIMIT $2`, timeFrame, limit) if err != nil { return nil, err } defer rows.Close() var reports []*domain.Report for rows.Next() { var report domain.Report err := rows.Scan( &report.ID, &report.TimeFrame, &report.PeriodStart, &report.PeriodEnd, &report.TotalBets, &report.TotalCashIn, &report.TotalCashOut, &report.TotalCashBack, &report.GeneratedAt, ) if err != nil { return nil, err } reports = append(reports, &report) } if err := rows.Err(); err != nil { return nil, err } return reports, nil } func (s *Store) GetTotalBetsMadeInRange(ctx context.Context, from, to time.Time) (int64, error) { params := dbgen.GetTotalBetsMadeInRangeParams{ From: ToPgTimestamp(from), To: ToPgTimestamp(to), } return s.queries.GetTotalBetsMadeInRange(ctx, params) } func (s *Store) GetTotalCashBacksInRange(ctx context.Context, from, to time.Time) (float64, error) { params := dbgen.GetTotalCashBacksInRangeParams{ From: ToPgTimestamp(from), To: ToPgTimestamp(to), } value, err := s.queries.GetTotalCashBacksInRange(ctx, params) if err != nil { return 0, err } return parseFloat(value) } func (s *Store) GetTotalCashMadeInRange(ctx context.Context, from, to time.Time) (float64, error) { params := dbgen.GetTotalCashMadeInRangeParams{ From: ToPgTimestamp(from), To: ToPgTimestamp(to), } value, err := s.queries.GetTotalCashMadeInRange(ctx, params) if err != nil { return 0, err } return parseFloat(value) } func (s *Store) GetTotalCashOutInRange(ctx context.Context, from, to time.Time) (float64, error) { params := dbgen.GetTotalCashOutInRangeParams{ From: ToPgTimestamp(from), To: ToPgTimestamp(to), } value, err := s.queries.GetTotalCashOutInRange(ctx, params) if err != nil { return 0, err } return parseFloat(value) } func (s *Store) GetWalletTransactionsInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetWalletTransactionsInRangeRow, error) { params := dbgen.GetWalletTransactionsInRangeParams{ CreatedAt: ToPgTimestamp(from), CreatedAt_2: ToPgTimestamp(to), } return s.queries.GetWalletTransactionsInRange(ctx, params) } func (s *Store) GetAllTicketsInRange(ctx context.Context, from, to time.Time) (dbgen.GetAllTicketsInRangeRow, error) { params := dbgen.GetAllTicketsInRangeParams{ CreatedAt: ToPgTimestamp(from), CreatedAt_2: ToPgTimestamp(to), } return s.queries.GetAllTicketsInRange(ctx, params) } func (s *Store) GetVirtualGameSummaryInRange(ctx context.Context, from, to time.Time) ([]dbgen.GetVirtualGameSummaryInRangeRow, error) { params := dbgen.GetVirtualGameSummaryInRangeParams{ CreatedAt: ToPgTimestamptz(from), CreatedAt_2: ToPgTimestamptz(to), } return s.queries.GetVirtualGameSummaryInRange(ctx, params) } func ToPgTimestamp(t time.Time) pgtype.Timestamp { return pgtype.Timestamp{Time: t, Valid: true} } func ToPgTimestamptz(t time.Time) pgtype.Timestamptz { return pgtype.Timestamptz{Time: t, Valid: true} } func parseFloat(value interface{}) (float64, error) { switch v := value.(type) { case float64: return v, nil case int64: return float64(v), nil case pgtype.Numeric: if !v.Valid { return 0, nil } f, err := v.Float64Value() if err != nil { return 0, fmt.Errorf("failed to convert pgtype.Numeric to float64: %w", err) } return f.Float64, nil case nil: return 0, nil default: return 0, fmt.Errorf("unexpected type %T for value: %+v", v, v) } } // func (s *Store) GetCompanyWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetCompanyWiseReportRow, error) { // params := dbgen.GetCompanyWiseReportParams{ // From: ToPgTimestamp(from), // To: ToPgTimestamp(to), // } // return s.queries.GetCompanyWiseReport(ctx, params) // } // func (s *Store) GetBranchWiseReport(ctx context.Context, from, to time.Time) ([]dbgen.GetBranchWiseReportRow, error) { // params := dbgen.GetBranchWiseReportParams{ // From: ToPgTimestamp(from), // To: ToPgTimestamp(to), // } // return s.queries.GetBranchWiseReport(ctx, params) // }