package database

import (
	"context"
	"crypto/md5"
	"database/sql"
	"encoding/hex"
	"fmt"
	"math"
	"time"
)

// UpsertRadarTile stores a radar tile into table `radar_tiles`.
// Assumes the table exists with schema compatible to columns used below.
func UpsertRadarTile(ctx context.Context, db *sql.DB, product string, dt time.Time, z, y, x int, width, height int, data []byte) error {
	if width == 0 {
		width = 256
	}
	if height == 0 {
		height = 256
	}
	step := 360.0 / math.Pow(2, float64(z))
	west := -180.0 + float64(x)*step
	south := -90.0 + float64(y)*step
	east := west + step
	north := south + step
	res := step / float64(width)

	sum := md5.Sum(data)
	md5hex := hex.EncodeToString(sum[:])

	q := `
    INSERT INTO radar_tiles (
        product, dt, z, y, x, width, height,
        west, south, east, north, res_deg,
        data, checksum_md5
    ) VALUES (
        $1,$2,$3,$4,$5,$6,$7,
        $8,$9,$10,$11,$12,
        $13,$14
    )
    ON CONFLICT (product, dt, z, y, x)
    DO UPDATE SET
        width = EXCLUDED.width,
        height = EXCLUDED.height,
        west = EXCLUDED.west,
        south = EXCLUDED.south,
        east = EXCLUDED.east,
        north = EXCLUDED.north,
        res_deg = EXCLUDED.res_deg,
        data = EXCLUDED.data,
        checksum_md5 = EXCLUDED.checksum_md5`

	_, err := db.ExecContext(ctx, q,
		product, dt, z, y, x, width, height,
		west, south, east, north, res,
		data, md5hex,
	)
	if err != nil {
		return fmt.Errorf("upsert radar tile (%s %s z=%d y=%d x=%d): %w", product, dt.Format(time.RFC3339), z, y, x, err)
	}
	return nil
}
