package lookup

import (
	"encoding/xml"
	"testing"
)

// A real HamQTH answer, captured from the live API.
//
// Two things it settles. The email IS returned and must reach the QSO. And the
// element names are not the ones a reading of the documentation suggests:
// there is no <name> here at all, the full name is <adr_name>, and the picture
// is <picture> where QRZ calls it <image>. The stray <div> is an advert the
// server injects into its own XML; the parser has to shrug it off.
const hamqthEU1EU = `<?xml version="1.0"?>
<HamQTH xmlns="https://www.hamqth.com" version="2.8">
<div id="in-page-channel-node-id" data-channel-name="in_page_channel_Sux7_K"/>
<search>
<callsign>eu1eu</callsign>
<nick>Igor</nick>
<qth>Minsk-5</qth>
<country>Belarus</country>
<adif>27</adif>
<itu>29</itu>
<cq>16</cq>
<grid>KO33SV</grid>
<adr_name>Igor Vladimirovich Getman</adr_name>
<adr_street1>A/ya 143</adr_street1>
<adr_city>Minsk-5</adr_city>
<adr_zip>220005</adr_zip>
<adr_country>Belarus</adr_country>
<adr_adif>27</adr_adif>
<district>WAARB-LE</district>
<lotw>?</lotw>
<qsldirect>?</qsldirect>
<qsl>?</qsl>
<eqsl>Y</eqsl>
<email>eu1eu@mail.ru</email>
<latitude>53.88999938964844</latitude>
<longitude>27.59000015258789</longitude>
<continent>EU</continent>
<utc_offset>-2</utc_offset>
<picture>https://www.hamqth.com/images/default/ts-930_qith_old_radios.jpg</picture>
</search>
</HamQTH>`

func TestHamQTHParsesEveryUsefulField(t *testing.T) {
	var root hamqthRoot
	if err := xml.Unmarshal([]byte(hamqthEU1EU), &root); err != nil {
		t.Fatalf("parse: %v", err)
	}
	s := root.Search

	for _, c := range []struct{ name, got, want string }{
		{"callsign", s.Callsign, "eu1eu"},
		{"email", s.Email, "eu1eu@mail.ru"},
		{"grid", s.Grid, "KO33SV"},
		{"qth", s.QTH, "Minsk-5"},
		{"street", s.AdrStreet1, "A/ya 143"},
		{"city", s.AdrCity, "Minsk-5"},
		{"country", s.AdrCountry, "Belarus"},
		{"continent", s.Continent, "EU"},
		{"dxcc", s.DXCC, "27"},
		{"cq", s.CQ, "16"},
		{"itu", s.ITU, "29"},
	} {
		if c.got != c.want {
			t.Errorf("%s = %q, want %q", c.name, c.got, c.want)
		}
	}
}

// The fields the parser was blind to. Each is data OpsLog has somewhere to put.
func TestHamQTHParsesTheFieldsThatWereMissing(t *testing.T) {
	var root hamqthRoot
	if err := xml.Unmarshal([]byte(hamqthEU1EU), &root); err != nil {
		t.Fatalf("parse: %v", err)
	}
	s := root.Search

	// The postal name, the fallback when a record carries no nick and no name.
	if s.AdrName != "Igor Vladimirovich Getman" {
		t.Errorf("adr_name = %q", s.AdrName)
	}
	if s.LastName != "" {
		t.Errorf("this record has no <name>; got %q", s.LastName)
	}
	// The profile picture. Result.ImageURL existed and said "QRZ only" — HamQTH
	// sends one too, under a different element name.
	if s.Picture == "" {
		t.Error("picture not parsed")
	}
	if s.AdrZip != "220005" {
		t.Errorf("adr_zip = %q", s.AdrZip)
	}
}

// End to end: what the provider hands back must carry the email, the full name
// and the picture.
func TestHamQTHResultCarriesTheLot(t *testing.T) {
	r, err := parseHamQTHSearch([]byte(hamqthEU1EU))
	if err != nil {
		t.Fatalf("parse: %v", err)
	}
	if r.Email != "eu1eu@mail.ru" {
		t.Errorf("Email = %q — this is what was reported missing", r.Email)
	}
	// The nick, not the postal name: a log wants the name the operator goes by
	// on the air. adr_name is only the fallback when there is nothing else.
	if r.Name != "Igor" {
		t.Errorf("Name = %q, want the on-air nick", r.Name)
	}
	if r.ImageURL == "" {
		t.Error("ImageURL empty — HamQTH sent a picture")
	}
	if r.Grid != "KO33SV" {
		t.Errorf("Grid = %q", r.Grid)
	}
	if r.Lat < 53.8 || r.Lat > 53.9 {
		t.Errorf("Lat = %v", r.Lat)
	}
	if r.DXCC != 27 || r.CQZ != 16 || r.ITUZ != 29 {
		t.Errorf("dxcc/cq/itu = %d/%d/%d", r.DXCC, r.CQZ, r.ITUZ)
	}
	if r.Address != "A/ya 143" {
		t.Errorf("Address = %q", r.Address)
	}
}
