package main

// One-shot generator: reads the FIPS county CSV and emits
// internal/awardref/uscounties_gen.go. Not part of the build.

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strings"
	"unicode/utf8"

	"hamlog/internal/award"
)

// dxccForState maps the two US "states" that are separate DXCC entities.
func dxccForState(st string) int {
	switch st {
	case "AK":
		return 6
	case "HI":
		return 110
	default:
		return 291
	}
}

// territories we exclude entirely — plus DC, which USA-CA does not count as a
// county.
var skipState = map[string]bool{"PR": true, "GU": true, "VI": true, "AS": true, "MP": true, "NA": true, "DC": true}

// excludedUSACA reports county-equivalents that the CQ USA-CA award does NOT
// count as counties: the independent cities of Virginia and Carson City (NV).
// (Baltimore MD and St. Louis MO ARE counted, so they are kept.) A contact in
// one of these counts toward a bordering county under the award rules.
func excludedUSACA(state, name string) bool {
	n := strings.ToLower(strings.TrimSpace(name))
	switch state {
	case "VA":
		return strings.HasSuffix(n, " city")
	case "NV":
		return n == "carson city"
	}
	return false
}

func main() {
	f, err := os.Open(os.Args[1])
	if err != nil {
		panic(err)
	}
	defer f.Close()

	type row struct{ code, name string; dxcc int }
	var rows []row
	seen := map[string]bool{}
	sc := bufio.NewScanner(f)
	sc.Scan() // header
	for sc.Scan() {
		line := sc.Text()
		// The FIPS CSV is not reliably UTF-8, and the one county whose name is
		// not ASCII (Doña Ana, NM) came through mangled once already — it landed
		// in the reference as "NM/DO̱AANA", a code no log could ever match,
		// silently costing that county for every operator. Refuse the row rather
		// than emit a broken one.
		if !utf8.ValidString(line) {
			fmt.Fprintf(os.Stderr, "cntygen: skipping non-UTF-8 line: %q\n", line)
			continue
		}
		parts := strings.SplitN(line, ",", 3)
		if len(parts) < 3 {
			continue
		}
		name := strings.TrimSpace(parts[1])
		st := strings.TrimSpace(parts[2])
		if skipState[st] || len(st) != 2 || strings.EqualFold(name, "UNITED STATES") {
			continue
		}
		if excludedUSACA(st, name) {
			continue
		}
		// State header rows have an all-caps state NAME and state code "NA"
		// (already skipped). County rows have a 2-letter state code.
		code := award.USCountyKey(st, name)
		if code == "" || seen[code] {
			continue
		}
		seen[code] = true
		rows = append(rows, row{code: code, name: name + ", " + st, dxcc: dxccForState(st)})
	}
	sort.Slice(rows, func(i, j int) bool { return rows[i].code < rows[j].code })

	var b strings.Builder
	b.WriteString("// Code generated by cmd/cntygen from FIPS county data. DO NOT EDIT.\n")
	b.WriteString("package awardref\n\n")
	b.WriteString("// usCounties is the US Counties (USA-CA) reference list: one entry per county\n")
	b.WriteString("// in the 50 states, keyed by the canonical \"STATE,COUNTY\" match code that\n")
	b.WriteString("// award.usCountyKey produces from a QSO's state + cnty fields.\n")
	fmt.Fprintf(&b, "func usCounties() []Ref {\n\treturn []Ref{\n")
	for _, r := range rows {
		fmt.Fprintf(&b, "\t\tref(%q, %q, %d),\n", r.code, r.name, r.dxcc)
	}
	b.WriteString("\t}\n}\n")

	if err := os.WriteFile(os.Args[2], []byte(b.String()), 0o644); err != nil {
		panic(err)
	}
	fmt.Printf("wrote %d counties to %s\n", len(rows), os.Args[2])
}
