package models

import (
	"fmt"
	"time"

	"gorm.io/gorm"
)

type UserRole string

const (
    ROLE_ADMIN  UserRole = "ADMIN"
    ROLE_CLIENT UserRole = "CLIENT"
)

type User struct {
    ID                  uint                `gorm:"primaryKey"`
    CreatedAt           time.Time
    UpdatedAt           time.Time
    DeletedAt           gorm.DeletedAt      `gorm:"index"`

	Password string `gorm:"not null"` // hashé avec bcrypt
    Email               string              `gorm:"uniqueIndex;not null"`
    SSOID               string              `gorm:"uniqueIndex;not null"`
    Role                UserRole            `gorm:"type:enum('ADMIN','CLIENT');default:'CLIENT';not null"`
    IsActive            bool                `gorm:"default:true"`

    WhatsappToken          string `gorm:"type:text"`           // token Meta spécifique au client
    WhatsappPhoneNumberID  string `gorm:"type:varchar(50)"`    // ID du numéro WhatsApp Business


    MonthlyCredits      uint                `gorm:"default:100"`
    CurrentMonthCredits uint                `gorm:"default:100"`
    LastRecharge        *time.Time          `gorm:"default:null"`

    Consumption         []Consumption
    MonthlyConsumptions []MonthlyConsumption
}


type Consumption struct {
    ID           uint           `gorm:"primaryKey"`
    CreatedAt    time.Time
    UpdatedAt    time.Time

    UserID       uint           `gorm:"index;not null"`
    MessageType  string         `gorm:"type:varchar(20);not null"` // ex: text, image, button
    Description  string         `gorm:"type:text"`
    CreditsUsed  uint           `gorm:"not null"`
}

type MonthlyConsumption struct {
    ID           uint      `gorm:"primaryKey"`
    CreatedAt    time.Time
    UpdatedAt    time.Time

    UserID       uint      `gorm:"index;not null"`
    Month        string    `gorm:"type:char(7);index;not null"` // Format YYYY-MM
    TotalUsed    uint      `gorm:"not null"`                    // Crédits utilisés ce mois
}
type Template struct {
	Name       string              `json:"name"`
	Language   TemplateLanguage    `json:"language"`
	Components []TemplateComponent `json:"components"`
}

type TemplateLanguage struct {
	Code string `json:"code"`
}

type TemplateComponent struct {
	Type       string              `json:"type"`
	Parameters []TemplateParameter `json:"parameters"`
}

type TemplateParameter struct {
	Type string `json:"type"`
	Text string `json:"text"`
}

type WhatsappMessage struct {
	MessagingProduct string     `json:"messaging_product"` // always "whatsapp"
	To               string     `json:"to"`                 // recipient phone number
	Type             string     `json:"type"`               // message type (text, image, video, etc.)
	Context          *Context   `json:"context,omitempty"`  // for replies
	RecipientType    string     `json:"recipient_type,omitempty"` // optional
	Text             *Text      `json:"text,omitempty"`
	Image            *Media     `json:"image,omitempty"`
	Video            *Media     `json:"video,omitempty"`
	Document         *Media     `json:"document,omitempty"`
	Audio            *Media     `json:"audio,omitempty"`
	Sticker          *Media     `json:"sticker,omitempty"`
	Location         *Location  `json:"location,omitempty"`
	Contacts         []Contact  `json:"contacts,omitempty"`
	Interactive      *Interactive `json:"interactive,omitempty"`
	Reaction         *Reaction  `json:"reaction,omitempty"`
	Template         *Template    `json:"template,omitempty"` // ✅ Ajoute ce champ
}

type Address struct {
	Street     string `json:"street,omitempty"`
	City       string `json:"city,omitempty"`
	State      string `json:"state,omitempty"`
	Zip        string `json:"zip,omitempty"`
	Country    string `json:"country,omitempty"`
	CountryCode string `json:"country_code,omitempty"`
	Type       string `json:"type,omitempty"` // home, work
}
type Contact struct {
	Addresses []Address `json:"addresses,omitempty"`
	Name      *Name     `json:"name,omitempty"`
	Emails    []Email   `json:"emails,omitempty"`
	Phones    []Phone   `json:"phones,omitempty"`
}

type Name struct {
	FormattedName string `json:"formatted_name"`
	FirstName     string `json:"first_name,omitempty"`
	LastName      string `json:"last_name,omitempty"`
}

type Email struct {
	Email string `json:"email"`
	Type  string `json:"type,omitempty"` // work, home
}

type Phone struct {
	Phone string `json:"phone"`
	Type  string `json:"type,omitempty"`
}
type Media struct {
	ID       string `json:"id,omitempty"`       // media ID from upload
	Link     string `json:"link,omitempty"`     // direct URL
	Caption  string `json:"caption,omitempty"`  // for image/video
	Filename string `json:"filename,omitempty"` // for documents
	MimeType string `json:"mime_type,omitempty"`
}
type Location struct {
	Latitude     float64 `json:"latitude"`
	Longitude    float64 `json:"longitude"`
	Name         string  `json:"name,omitempty"`
	Address      string  `json:"address,omitempty"`
	Url          string  `json:"url,omitempty"`
	IsLive       bool    `json:"is_live,omitempty"` // si demande de localisation en direct
}
type Text struct {
	Body string `json:"body"`
	PreviewURL bool `json:"preview_url,omitempty"`
}
type Context struct {
	MessageID string `json:"message_id"`
}
type Reaction struct {
	MessageID string `json:"message_id"`
	Emoji     string `json:"emoji"`
}
type StatusIndicator struct {
	Status string `json:"status"` // "read" or "typing"
	To     string `json:"to"`
}
type Interactive struct {
	Type   string       `json:"type"` // button | list | flow
	Body   *BodyContent `json:"body"`
	Action *Action      `json:"action"`
}

type BodyContent struct {
	Text string `json:"text"`
}

type Action struct {
	Button     string        `json:"button,omitempty"`
	Buttons    []ReplyButton `json:"buttons,omitempty"`
	Sections   []Section     `json:"sections,omitempty"` // for list
	CatalogID  string        `json:"catalog_id,omitempty"` // for flow
	ProductID  string        `json:"product_retailer_id,omitempty"` // for flow
}

type ReplyButton struct {
	Type    string      `json:"type"` // reply
	Reply   ButtonReply `json:"reply"`
}

type ButtonReply struct {
	ID    string `json:"id"`
	Title string `json:"title"`
}

type Section struct {
	Title string     `json:"title,omitempty"`
	Rows  []ListItem `json:"rows"`
}

type ListItem struct {
	ID          string `json:"id"`
	Title       string `json:"title"`
	Description string `json:"description,omitempty"`
}
type StatusMessage struct {
	MessagingProduct string `json:"messaging_product"`
	To               string `json:"to"`
	Type             string `json:"type"` // "typing_on", "typing_off", "read"
}
type Conversation struct {
	ID         uint           `gorm:"primaryKey"`
	CreatedAt  time.Time
	UpdatedAt  time.Time
	UserID     uint           `gorm:"index;not null"`
	From       string         `gorm:"not null"`
	To         string         `gorm:"not null"`
	MessageID  string         `gorm:"uniqueIndex;not null"`
	Type       string         `gorm:"not null"`
	Content    string         `gorm:"type:text"`
	Direction  string         `gorm:"not null"` // inbound/outbound
	Status     string         `gorm:"type:varchar(20)"` // sent, delivered, read, failed
}

func NewTextMessage(to string, body string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "text",
		Text:             &Text{Body: body},
	}
}

func NewImageMessage(to, mediaID, caption string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "image",
		Image:            &Media{ID: mediaID, Caption: caption},
	}
}

func NewVideoMessage(to, mediaID, caption string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "video",
		Video:            &Media{ID: mediaID, Caption: caption},
	}
}

func NewAudioMessage(to, mediaID string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "audio",
		Audio:            &Media{ID: mediaID},
	}
}

func NewDocumentMessage(to, mediaID, filename string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "document",
		Document:         &Media{ID: mediaID, Filename: filename},
	}
}

func NewStickerMessage(to, mediaID string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "sticker",
		Sticker:          &Media{ID: mediaID},
	}
}

func NewContactMessage(to string, contact Contact) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "contacts",
		Contacts:         []Contact{contact},
	}
}

func NewLocationMessage(to string, lat, lng float64, name, address string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "location",
		Location:         &Location{Latitude: lat, Longitude: lng, Name: name, Address: address},
	}
}

func NewReactionMessage(to, msgID, emoji string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "reaction",
		Reaction:         &Reaction{MessageID: msgID, Emoji: emoji},
	}
}

func NewReplyMessage(to, msgID, body string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "text",
		Context:          &Context{MessageID: msgID},
		Text:             &Text{Body: body},
	}
}

func NewInteractiveButtons(to string, text string, buttons []ReplyButton) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "interactive",
		Interactive:      &Interactive{Type: "button", Body: &BodyContent{Text: text}, Action: &Action{Buttons: buttons}},
	}
}

func NewInteractiveList(to string, text string, sections []Section) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "interactive",
		Interactive:      &Interactive{Type: "list", Body: &BodyContent{Text: text}, Action: &Action{Sections: sections}},
	}
}

func NewFlowMessage(to, text, catalogID, productID string) WhatsappMessage {
	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "interactive",
		Interactive:      &Interactive{Type: "flow", Body: &BodyContent{Text: text}, Action: &Action{CatalogID: catalogID, ProductID: productID}},
	}
}

func NewTypingIndicator(to string) StatusMessage {
	return StatusMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "typing_on",
	}
}

func NewReadReceipt(to string) StatusMessage {
	return StatusMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "read",
	}
}
func BuildMessageFromPayload(payload map[string]interface{}) (interface{}, error) {
	to := fmt.Sprintf("%v", payload["to"])
	typeStr := fmt.Sprintf("%v", payload["type"])

	switch typeStr {
	case "text":
		if text, ok := payload["text"].(map[string]interface{}); ok {
			return NewTextMessage(to, fmt.Sprintf("%v", text["body"])), nil
		}
	case "image":
		if image, ok := payload["image"].(map[string]interface{}); ok {
			return NewImageMessage(to, fmt.Sprintf("%v", image["id"]), fmt.Sprintf("%v", image["caption"])), nil
		}
	case "video":
		if video, ok := payload["video"].(map[string]interface{}); ok {
			return NewVideoMessage(to, fmt.Sprintf("%v", video["id"]), fmt.Sprintf("%v", video["caption"])), nil
		}
	case "audio":
		if audio, ok := payload["audio"].(map[string]interface{}); ok {
			return NewAudioMessage(to, fmt.Sprintf("%v", audio["id"])), nil
		}
	case "document":
		if doc, ok := payload["document"].(map[string]interface{}); ok {
			return NewDocumentMessage(to, fmt.Sprintf("%v", doc["id"]), fmt.Sprintf("%v", doc["filename"])), nil
		}
	case "sticker":
		if st, ok := payload["sticker"].(map[string]interface{}); ok {
			return NewStickerMessage(to, fmt.Sprintf("%v", st["id"])), nil
		}
	case "location":
		if loc, ok := payload["location"].(map[string]interface{}); ok {
			lat := loc["latitude"].(float64)
			lng := loc["longitude"].(float64)
			return NewLocationMessage(to, lat, lng, fmt.Sprintf("%v", loc["name"]), fmt.Sprintf("%v", loc["address"])), nil
		}
	case "reaction":
		if react, ok := payload["reaction"].(map[string]interface{}); ok {
			return NewReactionMessage(to, fmt.Sprintf("%v", react["message_id"]), fmt.Sprintf("%v", react["emoji"])), nil
		}
	case "typing_on", "typing_off", "read":
		return StatusMessage{MessagingProduct: "whatsapp", To: to, Type: typeStr}, nil
	default:
		return nil, fmt.Errorf("unsupported message type: %s", typeStr)
	}

	return nil, fmt.Errorf("failed to build message")
}
func NewTemplateMessage(to, name, lang string, params []string) WhatsappMessage {
	paramList := make([]TemplateParameter, len(params))
	for i, p := range params {
		paramList[i] = TemplateParameter{
			Type: "text",
			Text: p,
		}
	}

	return WhatsappMessage{
		MessagingProduct: "whatsapp",
		To:               to,
		Type:             "template",
		Template: &Template{
			Name: name,
			Language: TemplateLanguage{Code: lang},
			Components: []TemplateComponent{
				{
					Type:       "body",
					Parameters: paramList,
				},
			},
		},
	}
}

// Enregistre une erreur de statut dans la table Conversation
func SaveMessageStatusError(db *gorm.DB, userID uint, recipient, msgID, status, errorMsg string) error {
	conv := Conversation{
		UserID:    userID,
		From:      "system",
		To:        recipient,
		MessageID: msgID,
		Type:      "status",
		Content:   errorMsg,
		Direction: "outbound",
		Status:    status,
		CreatedAt: time.Now(),
	}
	return db.Create(&conv).Error
}

