package model

import (
	"encoding/json"
	"fmt"

	"github.com/tech/sendico/pkg/merrors"
)

type RecipientStatus int

const (
	RecipientStatusReady RecipientStatus = iota
	RecipientStatusRegistered
	RecipientStatusNotRegistered
)

var recipientStatusToString = map[RecipientStatus]string{
	RecipientStatusReady:         "ready",
	RecipientStatusRegistered:    "registered",
	RecipientStatusNotRegistered: "notRegistered",
}

var recipientStatusFromString = map[string]RecipientStatus{
	"ready":         RecipientStatusReady,
	"registered":    RecipientStatusRegistered,
	"notRegistered": RecipientStatusNotRegistered,
}

func (s RecipientStatus) String() string {
	if v, ok := recipientStatusToString[s]; ok {
		return v
	}
	return "ready" // дефолт, можно поменять
}

// JSON: храним как строку ("ready" / "registered" / "notRegistered")
func (s RecipientStatus) MarshalJSON() ([]byte, error) {
	return json.Marshal(s.String())
}

func (s *RecipientStatus) UnmarshalJSON(data []byte) error {
	var val string
	if err := json.Unmarshal(data, &val); err != nil {
		return err
	}
	v, ok := recipientStatusFromString[val]
	if !ok {
		return merrors.InvalidArgument(fmt.Sprintf("unknown RecipientStatus: %q", val))
	}
	*s = v
	return nil
}

// RecipientType { internal, external }

type RecipientType int

const (
	RecipientTypeInternal RecipientType = iota
	RecipientTypeExternal
)

var recipientTypeToString = map[RecipientType]string{
	RecipientTypeInternal: "internal",
	RecipientTypeExternal: "external",
}

var recipientTypeFromString = map[string]RecipientType{
	"internal": RecipientTypeInternal,
	"external": RecipientTypeExternal,
}

func (t RecipientType) String() string {
	if v, ok := recipientTypeToString[t]; ok {
		return v
	}
	return "internal"
}

func (t RecipientType) MarshalJSON() ([]byte, error) {
	return json.Marshal(t.String())
}

func (t *RecipientType) UnmarshalJSON(data []byte) error {
	var val string
	if err := json.Unmarshal(data, &val); err != nil {
		return err
	}
	v, ok := recipientTypeFromString[val]
	if !ok {
		return merrors.InvalidArgument(fmt.Sprintf("unknown RecipientType: %q", val))
	}
	*t = v
	return nil
}

type Recipient struct {
	PermissionBound `bson:",inline" json:",inline"`
	Describable     `bson:",inline" json:",inline"`
	Email           string  `bson:"email" json:"email"`
	AvatarURL       *string `bson:"avatarUrl,omitempty" json:"avatarUrl,omitempty"`

	Status RecipientStatus `bson:"status" json:"status"`
	Type   RecipientType   `bson:"type" json:"type"`
}
