package roomapi

import (
	"net/http"
	"strconv"
	"strings"

	"hyapp/services/gateway-service/internal/auth"
	"hyapp/services/gateway-service/internal/transport/http/httpkit"

	userv1 "hyapp.local/api/proto/user/v1"
)

const (
	roomFilterTypeAll     = "all"
	roomFilterTypeRegion  = "region"
	roomFilterTypeCountry = "country"

	// 区域筛选目录只暴露当前可用的业务区域；禁用区域继续保留在后台治理面，不下发给客户端。
	roomFilterRegionStatusActive = "active"
)

// roomFilterCatalogData 是首页筛选控件的稳定目录。
// filter_type 告诉 Flutter 应读取哪个查询字段：region 使用 region_id，country 使用 country_code，all 不传两者。
type roomFilterCatalogData struct {
	All       roomAllFilterData       `json:"all"`
	Regions   []roomRegionFilterData  `json:"regions"`
	Countries []roomCountryFilterData `json:"countries"`
}

type roomAllFilterData struct {
	FilterType string `json:"filter_type"`
	QueryKey   string `json:"query_key"`
	QueryValue string `json:"query_value"`
}

type roomRegionFilterData struct {
	FilterType string `json:"filter_type"`
	QueryKey   string `json:"query_key"`
	QueryValue string `json:"query_value"`
	RegionID   int64  `json:"region_id"`
	RegionCode string `json:"region_code"`
	RegionName string `json:"region_name"`
	SortOrder  int32  `json:"sort_order"`
}

type roomCountryFilterData struct {
	FilterType         string `json:"filter_type"`
	QueryKey           string `json:"query_key"`
	QueryValue         string `json:"query_value"`
	ParentRegionID     int64  `json:"parent_region_id,omitempty"`
	CountryID          int64  `json:"country_id"`
	CountryCode        string `json:"country_code"`
	CountryName        string `json:"country_name"`
	CountryDisplayName string `json:"country_display_name"`
	CountryFlag        string `json:"country_flag"`
	SortOrder          int32  `json:"sort_order"`
}

// listRoomFilters 返回当前 App 可用的首页区域/国家筛选目录。
// 筛选目录按租户能力返回全部 active 区域或当前用户区域，不按应用名分支。
func (h *Handler) listRoomFilters(writer http.ResponseWriter, request *http.Request) {
	// 一个请求只解析一次能力；避免依赖检查和目录查询分别访问缓存/后台库。
	allRegionDiscovery := h.roomDiscoveryAllRegions(request)
	if h.userRegionClient == nil || h.userCountryClient == nil || (!allRegionDiscovery && h.userProfileClient == nil) {
		httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
		return
	}

	regions, err := h.roomFilterRegions(request, allRegionDiscovery)
	if err != nil {
		httpkit.WriteRPCError(writer, request, err)
		return
	}
	countryResp, err := h.userCountryClient.ListRegistrationCountries(request.Context(), &userv1.ListRegistrationCountriesRequest{
		Meta: httpkit.UserMeta(request, ""),
	})
	if err != nil {
		httpkit.WriteRPCError(writer, request, err)
		return
	}

	httpkit.WriteOK(writer, request, roomFilterCatalogDataFromProto(regions, countryResp.GetCountries()))
}

func (h *Handler) roomFilterRegions(request *http.Request, allRegionDiscovery bool) ([]*userv1.Region, error) {
	if allRegionDiscovery {
		resp, err := h.userRegionClient.ListRegions(request.Context(), &userv1.ListRegionsRequest{
			Meta:   httpkit.UserMeta(request, ""),
			Status: roomFilterRegionStatusActive,
		})
		if err != nil {
			return nil, err
		}
		return resp.GetRegions(), nil
	}
	userResp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{
		Meta:   httpkit.UserMeta(request, ""),
		UserId: auth.UserIDFromContext(request.Context()),
	})
	if err != nil {
		return nil, err
	}
	if userResp.GetUser().GetRegionId() <= 0 {
		return []*userv1.Region{}, nil
	}
	regionResp, err := h.userRegionClient.GetRegion(request.Context(), &userv1.GetRegionRequest{
		Meta:     httpkit.UserMeta(request, ""),
		RegionId: userResp.GetUser().GetRegionId(),
	})
	if err != nil {
		return nil, err
	}
	region := regionResp.GetRegion()
	if region == nil || strings.TrimSpace(region.GetStatus()) != roomFilterRegionStatusActive {
		return []*userv1.Region{}, nil
	}
	return []*userv1.Region{region}, nil
}

func roomFilterCatalogDataFromProto(regions []*userv1.Region, countries []*userv1.Country) roomFilterCatalogData {
	data := roomFilterCatalogData{
		// All 的 query_key/query_value 显式为空；Flutter 可用同一套 option 逻辑，并在 key 为空时不附加筛选参数。
		All:       roomAllFilterData{FilterType: roomFilterTypeAll, QueryKey: "", QueryValue: ""},
		Regions:   make([]roomRegionFilterData, 0, len(regions)),
		Countries: make([]roomCountryFilterData, 0, len(countries)),
	}
	regionByCountry := make(map[string]int64)
	for _, region := range regions {
		if region == nil || region.GetRegionId() <= 0 || strings.TrimSpace(region.GetStatus()) != roomFilterRegionStatusActive {
			continue
		}
		data.Regions = append(data.Regions, roomRegionFilterData{
			FilterType: roomFilterTypeRegion,
			QueryKey:   "region_id",
			QueryValue: strconv.FormatInt(region.GetRegionId(), 10),
			RegionID:   region.GetRegionId(),
			RegionCode: strings.TrimSpace(region.GetRegionCode()),
			RegionName: strings.TrimSpace(region.GetName()),
			SortOrder:  region.GetSortOrder(),
		})
		for _, rawCountryCode := range region.GetCountries() {
			countryCode := normalizeRoomListCountryCode(rawCountryCode)
			if countryCode == "" {
				continue
			}
			if _, exists := regionByCountry[countryCode]; !exists {
				// 正常数据中一个国家只能有一个 active 区域；若上游短暂异常，保留产品排序最靠前的区域以确保响应确定。
				regionByCountry[countryCode] = region.GetRegionId()
			}
		}
	}

	for _, country := range countries {
		if country == nil {
			continue
		}
		countryCode := normalizeRoomListCountryCode(country.GetCountryCode())
		if countryCode == "" {
			continue
		}
		parentRegionID, mapped := regionByCountry[countryCode]
		if !mapped {
			// 只有 enabled 国家与 active 区域映射同时成立时才是可回传筛选值，避免客户端提交无法归属业务区域的国家。
			continue
		}
		countryFlag := strings.TrimSpace(country.GetFlag())
		if countryFlag == "" {
			countryFlag = roomProfileCountryFlag(countryCode)
		}
		data.Countries = append(data.Countries, roomCountryFilterData{
			FilterType:         roomFilterTypeCountry,
			QueryKey:           "country_code",
			QueryValue:         countryCode,
			ParentRegionID:     parentRegionID,
			CountryID:          country.GetCountryId(),
			CountryCode:        countryCode,
			CountryName:        strings.TrimSpace(country.GetCountryName()),
			CountryDisplayName: strings.TrimSpace(country.GetCountryDisplayName()),
			CountryFlag:        countryFlag,
			SortOrder:          country.GetSortOrder(),
		})
	}
	return data
}
