package location

import (
	"context"
	_ "embed"
	"fmt"
	"net"

	"go.uber.org/zap"

	geoip2 "github.com/oschwald/geoip2-golang"
	"github.com/tidbcloud/account/idl/pbgen/proto/central"
	"github.com/tidbcloud/tiinf/errs"
	"github.com/tidbcloud/tiinf/monitor/tilog"
)

var (
	_     central.LocationServiceServer = (*locationService)(nil)
	geoDB *geoip2.Reader

	//go:embed static/GeoLite2-Country_20251226.mmdb
	dbData []byte
)

func init() {
	var err error
	geoDB, err = geoip2.FromBytes(dbData)
	if err != nil {
		tilog.WithContextS(context.Background()).Fatal("failed to init geoip2 DB: %s", err)
		panic(err)
	}
}

type locationService struct {
	central.UnimplementedLocationServiceServer
}

func NewService() central.LocationServiceServer {
	return &locationService{}
}

func QueryCountryCodeByIP(ctx context.Context, ipAddr string) (string, error) {
	ip := net.ParseIP(ipAddr)
	tilog.Info(ctx, "ParseIP result", zap.Any("ip", ip))
	if ip == nil {
		return "", errs.NewForbidden("invalid ip", nil)
	}

	record, err := geoDB.City(ip)
	tilog.Info(ctx, "geoDB.City(ip)", zap.Any("record", record))
	if err != nil {
		return "", err
	}

	return record.Country.IsoCode, nil
}

func (l *locationService) IP2Location(ctx context.Context, req *central.IP2LocationReq) (*central.IP2LocationResp, error) {
	logger := tilog.WithContextS(ctx)
	resp := central.IP2LocationResp{}

	countryCode, err := QueryCountryCodeByIP(ctx, req.Ip)
	if err != nil {
		logger.Error("failed to query country code by ip %s: %s", req.Ip, err)
		return &resp, errs.NewInternalUnknown(fmt.Sprintf("failed to query country code by ip: %s", req.Ip), err)
	}

	resp.CountryCode = countryCode
	return &resp, nil
}
