//go:build ignore

package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"

	_ "github.com/jackc/pgx/v5/stdlib"
)

// One-off backfill for tenants/tenantlocations rows that were onboarded
// before the admin console geocoded addresses automatically, so their
// latitude/longitude columns were left blank. Geocodes each row's existing
// address via OpenStreetMap Nominatim (same keyless provider
// AddressAutocomplete.tsx already uses on the frontend) and writes the
// result back. Run manually: `go run scratch/backfill_location_coordinates.go`
// — do not wire this into any request path, it's a single pass over
// historical rows.
const nominatimURL = "https://nominatim.openstreetmap.org/search"

// Nominatim's usage policy caps free lookups at ~1 request/sec.
const rateLimit = 1100 * time.Millisecond

type nominatimRow struct {
	Lat string `json:"lat"`
	Lon string `json:"lon"`
}

func geocode(client *http.Client, address string) (lat, lon string, ok bool) {
	q := url.Values{}
	q.Set("format", "json")
	q.Set("limit", "1")
	q.Set("q", address)

	req, err := http.NewRequest("GET", nominatimURL+"?"+q.Encode(), nil)
	if err != nil {
		return "", "", false
	}
	// Required by Nominatim's usage policy — identifies the calling app.
	req.Header.Set("User-Agent", "fiesta-backend-backfill/1.0 (care@nearle.in)")

	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("  geocode request error: %v\n", err)
		return "", "", false
	}
	defer resp.Body.Close()

	var rows []nominatimRow
	if err := json.NewDecoder(resp.Body).Decode(&rows); err != nil || len(rows) == 0 {
		return "", "", false
	}
	return rows[0].Lat, rows[0].Lon, true
}

type row struct {
	id      int
	address string
}

func backfillTable(db *sql.DB, client *http.Client, table, idCol string) {
	fmt.Printf("\n=== %s ===\n", table)

	query := fmt.Sprintf(`
		SELECT %s,
		       TRIM(BOTH ', ' FROM CONCAT_WS(', ', address, suburb, city, state, postcode))
		FROM %s
		WHERE (latitude IS NULL OR latitude = '' OR latitude = '0')
		  AND (address IS NOT NULL AND address <> '')`, idCol, table)

	rows, err := db.Query(query)
	if err != nil {
		log.Fatalf("%s: query error: %v", table, err)
	}
	var targets []row
	for rows.Next() {
		var r row
		if err := rows.Scan(&r.id, &r.address); err != nil {
			log.Fatalf("%s: scan error: %v", table, err)
		}
		targets = append(targets, r)
	}
	rows.Close()

	fmt.Printf("Found %d row(s) missing coordinates.\n", len(targets))

	updated, skipped := 0, 0
	for i, r := range targets {
		if i > 0 {
			time.Sleep(rateLimit)
		}

		lat, lon, ok := geocode(client, r.address)
		if !ok {
			fmt.Printf("  [%s=%d] %q — geocode FAILED, left untouched\n", idCol, r.id, r.address)
			skipped++
			continue
		}

		res, err := db.Exec(
			fmt.Sprintf(`UPDATE %s SET latitude = $1, longitude = $2 WHERE %s = $3`, table, idCol),
			lat, lon, r.id,
		)
		if err != nil {
			fmt.Printf("  [%s=%d] update error: %v\n", idCol, r.id, err)
			skipped++
			continue
		}
		n, _ := res.RowsAffected()
		if n > 0 {
			fmt.Printf("  [%s=%d] %q -> lat=%s lon=%s\n", idCol, r.id, r.address, lat, lon)
			updated++
		}
	}

	fmt.Printf("%s: updated=%d skipped=%d\n", table, updated, skipped)
}

func main() {
	dsn := "host=66.116.207.225 port=5433 user=admin password=Package@123# dbname=nearledb sslmode=disable"
	db, err := sql.Open("pgx", dsn)
	if err != nil {
		log.Fatalf("open error: %v", err)
	}
	defer db.Close()

	if err := db.Ping(); err != nil {
		log.Fatalf("ping error: %v", err)
	}
	fmt.Println("Connected to nearledb.")

	client := &http.Client{Timeout: 10 * time.Second}

	backfillTable(db, client, "tenants", "tenantid")
	backfillTable(db, client, "tenantlocations", "locationid")

	fmt.Println(strings.Repeat("-", 40))
	fmt.Println("Done.")
}
