package services import ( "database/sql" "fmt" _ "github.com/lib/pq" "go-weather/models" "time" ) func ConnectDB(connStr string) (*sql.DB, error) { db, err := sql.Open("postgres", connStr) if err != nil { return nil, fmt.Errorf("failed to connect to db: %v", err) } err = db.Ping() if err != nil { return nil, fmt.Errorf("failed to connect to db: %v", err) } fmt.Println("connected to PostgreSQL") return db, nil } type DatabaseService struct { db *sql.DB } func NewDatabaseService(db *sql.DB) *DatabaseService { return &DatabaseService{db: db} } func (s *DatabaseService) CreateTable() error { _, err := s.db.Exec(` CREATE TABLE IF NOT EXISTS weather_readings ( id SERIAL PRIMARY KEY, city TEXT NOT NULL, temp DOUBLE PRECISION NOT NULL, feels_like DOUBLE PRECISION NOT NULL, humidity INTEGER NOT NULL, conditions TEXT NOT NULL, fetched_at TIMESTAMP WITH TIME ZONE NOT NULL ) `) if err != nil { fmt.Errorf("failed to create table: %v", err) } fmt.Println("weather_readings table ready") return nil } func (s *DatabaseService) SaveReading(weather models.WeatherResponse) (int, error) { conditions := "" if len(weather.Weather) > 0 { conditions = weather.Weather[0].Description } var id int err := s.db.QueryRow( `INSERT INTO weather_readings (city, temp, feels_like, humidity, conditions, fetched_at) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id`, weather.Name, weather.Main.Temp, weather.Main.FeelsLike, weather.Main.Humidity, conditions, time.Now(), ).Scan(&id) if err != nil { return 0, fmt.Errorf("failed to save reading: %w", err) } return id, nil } func (s *DatabaseService) GetReadings(city string, limit int) ([]models.Reading, error) { rows, err := s.db.Query( `SELECT id, city, temp, feels_like, humidity, conditions, fetched_at FROM weather_readings WHERE city ILIKE $1 ORDER BY fetched_at DESC LIMIT $2`, city, limit, ) if err != nil { return nil, fmt.Errorf("Query failed: %w", err) } defer rows.Close() var readings []models.Reading for rows.Next() { var r models.Reading err := rows.Scan(&r.ID, &r.City, &r.Temp, &r.FeelsLike, &r.Humidity, &r.Conditions, &r.FetchedAt) if err != nil { return nil, fmt.Errorf("scan failed: %w", err) } readings = append(readings, r) } return readings, nil }