package models

import (
	"GoMembership/internal/constants"
	"time"

	"github.com/alexedwards/argon2id"
	"gorm.io/gorm"
)

type User struct {
	DateOfBirth    time.Time `gorm:"not null" json:"date_of_birth" validate:"required,age"`
	Company        string       `json:"company" validate:"omitempty,omitnil,safe_content"`
	Phone          string       `json:"phone" validate:"omitempty,omitnil,safe_content"`
	Notes          *string      `json:"notes,safe_content"`
	FirstName      string       `gorm:"not null" json:"first_name" validate:"required,safe_content"`
	Password       string       `json:"password" validate:"required_unless=RoleID 0,safe_content"`
	Email          string       `gorm:"unique;not null" json:"email" validate:"required,email,safe_content"`
	LastName       string       `gorm:"not null" json:"last_name" validate:"required,safe_content"`
	ProfilePicture string       `json:"profile_picture" validate:"omitempty,omitnil,image,safe_content"`
	Address        string       `gorm:"not null" json:"address" validate:"required,safe_content"`
	ZipCode        string       `gorm:"not null" json:"zip_code" validate:"required,alphanum,safe_content"`
	City           string       `form:"not null" json:"city" validate:"required,alphaunicode,safe_content"`
	Consents       []Consent    `gorm:"constraint:OnUpdate:CASCADE"`
	BankAccount    BankAccount  `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"bank_account"`
	Verification   Verification `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
	Membership     Membership   `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"membership"`
	ID             int64        `gorm:"primaryKey" json:"id"`
	PaymentStatus  int8         `json:"payment_status"`
	Status         int8         `json:"status"`
	RoleID         int8         `json:"role_id"`
	gorm.Model
}

// BeforeCreate sets the default value for Status
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
	if u.Status == 0 { // Assuming 0 is an unset value
		u.Status = constants.UnverifiedStatus
		u.PaymentStatus = constants.AwaitingPaymentStatus
	}
	return
}

func (u *User) PasswordMatches(plaintextPassword string) (bool, error) {
	match, err := argon2id.ComparePasswordAndHash(plaintextPassword, u.Password)
	if err != nil {
		return false, err
	}

	return match, nil
}

func (u *User) Safe() map[string]interface{} {
	return map[string]interface{}{
		"email":         u.Email,
		"first_name":    u.FirstName,
		"last_name":     u.LastName,
		"phone":         u.Phone,
		"notes":         u.Notes,
		"address":       u.Address,
		"zip_code":      u.ZipCode,
		"city":          u.City,
		"status":        u.Status,
		"id":            u.ID,
		"role_id":       u.RoleID,
		"date_of_birth": u.DateOfBirth,
		"membership": map[string]interface{}{
			"id":         u.Membership.ID,
			"start_date": u.Membership.StartDate,
			"end_date":   u.Membership.EndDate,
			"status":     u.Membership.Status,
			"subscription_model": map[string]interface{}{
				"id":                 u.Membership.SubscriptionModel.ID,
				"name":               u.Membership.SubscriptionModel.Name,
				"details":            u.Membership.SubscriptionModel.Details,
				"conditions":         u.Membership.SubscriptionModel.Conditions,
				"monthly_fee":        u.Membership.SubscriptionModel.MonthlyFee,
				"hourly_rate":        u.Membership.SubscriptionModel.HourlyRate,
				"included_per_year":  u.Membership.SubscriptionModel.IncludedPerYear,
				"included_per_month": u.Membership.SubscriptionModel.IncludedPerMonth,
			},
		},
		"bank_account": map[string]interface{}{
			"id":                  u.BankAccount.ID,
			"mandate_date_signed": u.BankAccount.MandateDateSigned,
			"bank":                u.BankAccount.Bank,
			"account_holder_name": u.BankAccount.AccountHolderName,
			"iban":                u.BankAccount.IBAN,
			"bic":                 u.BankAccount.BIC,
			"mandate_reference":   u.BankAccount.MandateReference,
		},
	}
}
