package service

import (
	"context"
	"net/http"

	"cmr-backend/internal/apperr"
	"cmr-backend/internal/store/postgres"
)

type ProfileService struct {
	store *postgres.Store
}

type ProfileResult struct {
	User struct {
		ID        string  `json:"id"`
		PublicID  string  `json:"publicId"`
		Status    string  `json:"status"`
		Nickname  *string `json:"nickname,omitempty"`
		AvatarURL *string `json:"avatarUrl,omitempty"`
	} `json:"user"`
	Bindings struct {
		HasMobile      bool                 `json:"hasMobile"`
		HasWechatMini  bool                 `json:"hasWechatMini"`
		HasWechatUnion bool                 `json:"hasWechatUnion"`
		Items          []ProfileBindingItem `json:"items"`
	} `json:"bindings"`
	RecentSessions []EntrySessionSummary `json:"recentSessions"`
}

type ProfileBindingItem struct {
	IdentityType string  `json:"identityType"`
	Provider     string  `json:"provider"`
	Status       string  `json:"status"`
	CountryCode  *string `json:"countryCode,omitempty"`
	Mobile       *string `json:"mobile,omitempty"`
	MaskedLabel  string  `json:"maskedLabel"`
}

func NewProfileService(store *postgres.Store) *ProfileService {
	return &ProfileService{store: store}
}

func (s *ProfileService) GetProfile(ctx context.Context, userID string) (*ProfileResult, error) {
	if userID == "" {
		return nil, apperr.New(http.StatusUnauthorized, "unauthorized", "user is required")
	}

	user, err := s.store.GetUserByID(ctx, s.store.Pool(), userID)
	if err != nil {
		return nil, err
	}
	if user == nil {
		return nil, apperr.New(http.StatusNotFound, "user_not_found", "user not found")
	}

	identities, err := s.store.ListIdentitiesByUserID(ctx, userID)
	if err != nil {
		return nil, err
	}

	sessions, err := s.store.ListSessionsByUserID(ctx, userID, 5)
	if err != nil {
		return nil, err
	}

	result := &ProfileResult{}
	result.User.ID = user.ID
	result.User.PublicID = user.PublicID
	result.User.Status = user.Status
	result.User.Nickname = user.Nickname
	result.User.AvatarURL = user.AvatarURL

	for _, identity := range identities {
		item := ProfileBindingItem{
			IdentityType: identity.IdentityType,
			Provider:     identity.Provider,
			Status:       identity.Status,
			CountryCode:  identity.CountryCode,
			Mobile:       identity.Mobile,
			MaskedLabel:  maskIdentity(identity),
		}
		result.Bindings.Items = append(result.Bindings.Items, item)

		switch identity.Provider {
		case "mobile":
			result.Bindings.HasMobile = true
		case "wechat_mini":
			result.Bindings.HasWechatMini = true
		case "wechat_unionid":
			result.Bindings.HasWechatUnion = true
		}
	}

	for i := range sessions {
		result.RecentSessions = append(result.RecentSessions, buildEntrySessionSummary(&sessions[i]))
	}

	return result, nil
}

func maskIdentity(identity postgres.LoginIdentity) string {
	if identity.Provider == "mobile" && identity.Mobile != nil {
		value := *identity.Mobile
		if len(value) >= 7 {
			return value[:3] + "****" + value[len(value)-4:]
		}
		return value
	}

	if identity.Provider == "wechat_mini" {
		return "WeChat Mini bound"
	}
	if identity.Provider == "wechat_unionid" {
		return "WeChat Union bound"
	}
	return identity.Provider
}
