package geo

import (
	"log"
	"os"
	"strings"

	"github.com/lionsoul2014/ip2region/binding/golang/xdb"
)

// Geo 基于 ip2region v4 离线库的 IP 地区解析器（纯本地，无外部依赖）
type Geo struct {
	searcher *xdb.Searcher
}

// New 按顺序尝试数据文件路径加载；全部失败时返回可用但禁用的实例（地区解析优雅降级）
func New(paths ...string) *Geo {
	var dbPath string
	for _, p := range paths {
		if _, err := os.Stat(p); err == nil {
			dbPath = p
			break
		}
	}
	if dbPath == "" {
		log.Printf("[geo] 未找到 ip2region 数据文件（尝试: %v），地区解析已禁用", paths)
		return &Geo{}
	}

	handle, err := os.Open(dbPath)
	if err != nil {
		log.Printf("[geo] 打开 %s 失败: %v", dbPath, err)
		return &Geo{}
	}
	defer handle.Close()

	header, err := xdb.LoadHeader(handle)
	if err != nil {
		log.Printf("[geo] 读取 %s 头部失败: %v", dbPath, err)
		return &Geo{}
	}
	version, err := xdb.VersionFromHeader(header)
	if err != nil {
		log.Printf("[geo] 识别 %s 版本失败: %v", dbPath, err)
		return &Geo{}
	}

	// 整库载入内存，查询性能最好（约 11MB）
	buff, err := xdb.LoadContentFromFile(dbPath)
	if err != nil {
		log.Printf("[geo] 加载 %s 数据失败: %v", dbPath, err)
		return &Geo{}
	}
	searcher, err := xdb.NewWithBuffer(version, buff)
	if err != nil {
		log.Printf("[geo] 初始化搜索器失败: %v", err)
		return &Geo{}
	}

	log.Printf("[geo] ip2region 已加载（%.0f MB，%s）", float64(len(buff))/1024/1024, dbPath)
	return &Geo{searcher: searcher}
}

// Search 返回友好地区名（如 "广东省深圳市 电信"、"新加坡"）；解析失败返回 ""
func (g *Geo) Search(ip string) string {
	if g == nil || g.searcher == nil || ip == "" {
		return ""
	}
	region, err := g.searcher.Search(ip)
	if err != nil {
		return ""
	}
	return Format(region)
}

// Format 把 ip2region v4 原始格式 "国家|省|市|ISP|国家码" 转为友好显示
// 例：中国|江苏省|南京市|0|CN → "江苏省南京市"；中国|上海|上海市|电信|CN → "上海市 电信"；
//     United States|California|0|Google LLC|US → "United States California · Google LLC"
func Format(region string) string {
	parts := strings.Split(region, "|")
	if len(parts) < 5 {
		return region
	}
	country, province, city, isp := parts[0], parts[1], parts[2], parts[3]
	if country == "" || country == "0" || country == "Reserved" {
		return "" // 保留地址/内网/IPv6 不在 v4 库中
	}
	if isp == "0" {
		isp = ""
	}

	if country == "中国" {
		loc := ""
		switch {
		case province != "" && province != "0" && city != "" && city != "0":
			if city == province || strings.Contains(city, province) {
				loc = city // 直辖市："上海市"
			} else {
				loc = province + city // "江苏省南京市"
			}
		case province != "" && province != "0":
			loc = province
		default:
			loc = "中国"
		}
		if isp != "" {
			loc += " " + isp
		}
		return loc
	}

	// 国外：国家 + 州/市（英文）
	loc := country
	switch {
	case province != "" && province != "0":
		loc += " " + province
	case city != "" && city != "0":
		loc += " " + city
	}
	if isp != "" {
		loc += " · " + isp
	}
	return loc
}
