// Package account — buyer address book for the B2B storefront.
//
// The live backend historically had no /account group, so the storefront kept
// its address book in the browser's localStorage. This module makes addresses
// first-class server entities scoped to the authenticated user (same scoping
// as /cart). Checkout keeps taking the address as free text; the book only
// stores reusable addresses.
package account

import "errors"

var (
	// ErrNotFound is returned when the address does not exist or does not
	// belong to the requesting user.
	ErrNotFound = errors.New("address not found")
	// ErrInvalid is returned when the payload fails validation.
	ErrInvalid = errors.New("invalid address")
)

// Address is the JSON shape exchanged with the storefront. snake_case on the
// wire, matching every other backend resource.
type Address struct {
	ID                int64    `json:"id"`
	Label             string   `json:"label"`
	ContactName       string   `json:"contact_name"`
	Phone             string   `json:"phone"`
	Line1             string   `json:"line1"`
	Line2             *string  `json:"line2"`
	City              string   `json:"city"`
	Province          *string  `json:"province"`
	PostalCode        string   `json:"postal_code"`
	Country           string   `json:"country"`
	Latitude          *float64 `json:"latitude"`
	Longitude         *float64 `json:"longitude"`
	IsDefaultShipping bool     `json:"is_default_shipping"`
	IsDefaultBilling  bool     `json:"is_default_billing"`
}

// AddressInput is the create/update payload. Pointers distinguish "absent"
// from "empty" for optional fields.
type AddressInput struct {
	Label             string   `json:"label"`
	ContactName       string   `json:"contact_name"`
	Phone             string   `json:"phone"`
	Line1             string   `json:"line1"`
	Line2             *string  `json:"line2"`
	City              string   `json:"city"`
	Province          *string  `json:"province"`
	PostalCode        string   `json:"postal_code"`
	Country           string   `json:"country"`
	Latitude          *float64 `json:"latitude"`
	Longitude         *float64 `json:"longitude"`
	IsDefaultShipping bool     `json:"is_default_shipping"`
	IsDefaultBilling  bool     `json:"is_default_billing"`
}

// validate enforces the column limits from migrations/000096 so a payload can
// never fail mid-INSERT with a database length error. Returns a message the
// handler can surface verbatim.
func (in *AddressInput) validate() (string, bool) {
	max := func(n int, s string) bool { return len(s) <= n }
	switch {
	case !max(100, in.Label):
		return "label maksimal 100 karakter", false
	case !max(255, in.ContactName):
		return "nama penerima maksimal 255 karakter", false
	case !max(50, in.Phone):
		return "nomor telepon maksimal 50 karakter", false
	case in.Line1 == "":
		return "alamat (line1) wajib diisi", false
	case !max(150, in.City):
		return "kota maksimal 150 karakter", false
	case in.Province != nil && !max(150, *in.Province):
		return "provinsi maksimal 150 karakter", false
	case !max(20, in.PostalCode):
		return "kode pos maksimal 20 karakter", false
	case in.Country != "" && !max(100, in.Country):
		return "negara maksimal 100 karakter", false
	case (in.Latitude == nil) != (in.Longitude == nil):
		return "latitude dan longitude harus dikirim berpasangan", false
	}
	return "", true
}
