// forecast_read.go executes hourly forecast and period queries.
// Layer: adapters/outbound/postgres forecast feature.
package postgres

import (
	"context"
	"database/sql"
	"errors"
	"fmt"

	"gitea.maximumdirect.net/ejr/weatherfeeder/model"
)

func (r *Repository) LatestHourlyForecast(ctx context.Context) (*model.WeatherForecastRun, error) {
	if r == nil || r.db == nil {
		return nil, fmt.Errorf("postgres repository is not configured")
	}

	var row forecastParentRow
	err := r.db.QueryRowContext(ctx, queryLatestHourlyForecast).Scan(
		&row.EventID,
		&row.LocationID,
		&row.LocationName,
		&row.IssuedAt,
		&row.UpdatedAt,
		&row.Product,
		&row.Latitude,
		&row.Longitude,
		&row.ElevationMeters,
	)
	if errors.Is(err, sql.ErrNoRows) {
		return nil, nil
	}
	if err != nil {
		return nil, fmt.Errorf("query latest hourly forecast: %w", err)
	}

	run := mapForecastParentRow(row)

	periods, err := r.loadForecastPeriods(ctx, row.EventID)
	if err != nil {
		return nil, err
	}
	run.Periods = periods

	return &run, nil
}

func (r *Repository) loadForecastPeriods(ctx context.Context, eventID string) ([]model.WeatherForecastPeriod, error) {
	rows, err := r.db.QueryContext(ctx, queryForecastPeriods, eventID)
	if err != nil {
		return nil, fmt.Errorf("query forecast periods: %w", err)
	}
	defer rows.Close()

	out := make([]model.WeatherForecastPeriod, 0)
	for rows.Next() {
		var row forecastPeriodRow
		if err := rows.Scan(
			&row.PeriodIndex,
			&row.StartTime,
			&row.EndTime,
			&row.Name,
			&row.IsDay,
			&row.ConditionCode,
			&row.ConditionText,
			&row.ProviderRawDescription,
			&row.TextDescription,
			&row.DetailedText,
			&row.IconURL,
			&row.TemperatureC,
			&row.TemperatureCMin,
			&row.TemperatureCMax,
			&row.DewpointC,
			&row.RelativeHumidityPercent,
			&row.WindDirectionDegrees,
			&row.WindSpeedKmh,
			&row.WindGustKmh,
			&row.BarometricPressurePa,
			&row.VisibilityMeters,
			&row.ApparentTemperatureC,
			&row.CloudCoverPercent,
			&row.ProbabilityOfPrecipitationPercent,
			&row.PrecipitationAmountMM,
			&row.SnowfallDepthMM,
			&row.UVIndex,
		); err != nil {
			return nil, fmt.Errorf("scan forecast period row: %w", err)
		}
		out = append(out, mapForecastPeriodRow(row))
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate forecast period rows: %w", err)
	}
	return out, nil
}
