package postgres import ( "context" "database/sql" "fmt" "time" "gitea.maximumdirect.net/ejr/weatherapi/internal/core/ports" "github.com/jackc/pgx/v5/pgxpool" ) type ForecastRepository struct { pool *pgxpool.Pool } func NewForecastRepository(pool *pgxpool.Pool) *ForecastRepository { return &ForecastRepository{pool: pool} } func (r *ForecastRepository) ListForecastPeriodsAt(ctx context.Context, ts time.Time, limit int) ([]ports.ForecastPeriodMetric, error) { rows, err := r.pool.Query(ctx, queryForecastPeriodsAt, ts, limit) if err != nil { return nil, fmt.Errorf("query forecast periods at timestamp: %w", err) } defer rows.Close() out := make([]ports.ForecastPeriodMetric, 0) for rows.Next() { var row ports.ForecastPeriodMetric var name sql.NullString var isDay sql.NullBool var conditionText sql.NullString var providerRawDescription sql.NullString var textDescription sql.NullString var detailedText sql.NullString var iconURL sql.NullString var temperature sql.NullFloat64 var temperatureMin sql.NullFloat64 var temperatureMax sql.NullFloat64 var dewpoint sql.NullFloat64 var humidity sql.NullFloat64 var windDirection sql.NullFloat64 var windSpeed sql.NullFloat64 var windGust sql.NullFloat64 var pressure sql.NullFloat64 var visibility sql.NullFloat64 var apparent sql.NullFloat64 var cloudCover sql.NullFloat64 var precipProbability sql.NullFloat64 var precipAmount sql.NullFloat64 var snowfallDepth sql.NullFloat64 var uvIndex sql.NullFloat64 if err := rows.Scan( &row.PeriodIndex, &row.StartTime, &row.EndTime, &name, &isDay, &row.ConditionCode, &conditionText, &providerRawDescription, &textDescription, &detailedText, &iconURL, &temperature, &temperatureMin, &temperatureMax, &dewpoint, &humidity, &windDirection, &windSpeed, &windGust, &pressure, &visibility, &apparent, &cloudCover, &precipProbability, &precipAmount, &snowfallDepth, &uvIndex, ); err != nil { return nil, fmt.Errorf("scan forecast period row: %w", err) } row.Name = ptrString(name) row.IsDay = ptrBool(isDay) row.ConditionText = ptrString(conditionText) row.ProviderRawDescription = ptrString(providerRawDescription) row.TextDescription = ptrString(textDescription) row.DetailedText = ptrString(detailedText) row.IconURL = ptrString(iconURL) row.TemperatureC = ptrFloat64(temperature) row.TemperatureCMin = ptrFloat64(temperatureMin) row.TemperatureCMax = ptrFloat64(temperatureMax) row.DewpointC = ptrFloat64(dewpoint) row.RelativeHumidityPercent = ptrFloat64(humidity) row.WindDirectionDegrees = ptrFloat64(windDirection) row.WindSpeedKmh = ptrFloat64(windSpeed) row.WindGustKmh = ptrFloat64(windGust) row.BarometricPressurePa = ptrFloat64(pressure) row.VisibilityMeters = ptrFloat64(visibility) row.ApparentTemperatureC = ptrFloat64(apparent) row.CloudCoverPercent = ptrFloat64(cloudCover) row.ProbabilityOfPrecipitationPercent = ptrFloat64(precipProbability) row.PrecipitationAmountMm = ptrFloat64(precipAmount) row.SnowfallDepthMm = ptrFloat64(snowfallDepth) row.UVIndex = ptrFloat64(uvIndex) out = append(out, row) } if err := rows.Err(); err != nil { return nil, fmt.Errorf("iterate forecast period rows: %w", err) } return out, nil }