package models

import (
	"strconv"
	"time"

	"github.com/google/uuid"
	"gorm.io/gorm"
)

// Custom type to handle Price as string or float from JSON
type Price float64

func (p *Price) UnmarshalJSON(data []byte) error {
	if len(data) == 0 {
		return nil
	}
	s := string(data)
	// Remove quotes if it's a string
	if s[0] == '"' {
		s = s[1 : len(s)-1]
	}
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return err
	}
	*p = Price(f)
	return nil
}

// Base model with UUID and sync fields
type Base struct {
	ID           uint      `gorm:"primaryKey" json:"id"`
	UUID         string    `gorm:"uniqueIndex" json:"uuid"`
	Sincronizado bool      `gorm:"default:false" json:"sincronizado"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`
}

func (b *Base) BeforeCreate(tx *gorm.DB) (err error) {
	if b.UUID == "" {
		b.UUID = uuid.New().String()
	}
	return
}

type Mesa struct {
	Base
	Name     string `json:"name"`
	Location string `json:"location"`
	Active   bool   `gorm:"default:false" json:"active"`
}

type Client struct {
	Base
	Name      string    `json:"name"`
	Debt      Price     `gorm:"default:0" json:"debt"`
	CreatedAt time.Time `json:"created_at"`
	Active    bool      `gorm:"default:true" json:"active"`
	Contact   string    `json:"contact"`
}

type Category struct {
	Base
	Name   string `json:"name"`
	Active bool   `gorm:"default:true" json:"active"`
}

type Product struct {
	Base
	Name          string  `json:"name"`
	Description   string  `json:"description"`
	Image         string  `json:"image"` // URL or Path
	Price         Price   `json:"price"`
	Quantity      int     `gorm:"default:0" json:"quantity"`
	CategoryID    uint    `gorm:"column:category" json:"category"`
	Cuisine       bool    `gorm:"default:false" json:"cuisine"`
	Active        bool    `gorm:"default:true" json:"active"`
	UnitOfMeasure *uint   `gorm:"column:unit_of_measure" json:"unit_of_measure"`
}

type ProductComponent struct {
	Base
	CompositeProductID uint    `json:"composite_product"`
	ComponentProductID uint    `json:"component_product"`
	QuantityRequired   float64 `json:"quantity_required"`
}

type Comanda struct {
	Base
	MesaID    uint       `json:"mesa"`
	UserID    uint       `json:"user"`
	TypePayID *uint      `json:"type_pay"`
	ClientID  *uint      `json:"client"`
	Name      string     `json:"name"`
	Status    string     `json:"status"` // OPEN, CLOSED, FIADO
	DtOpen    time.Time  `json:"dt_open"`
	DtClose   *time.Time `json:"dt_close"`

	// Nested items from Django (not stored in comanda table)
	Items []ProductComanda `gorm:"foreignKey:ComandaID" json:"items"`
}

type ProductComanda struct {
	Base
	ComandaID    uint      `json:"comanda"`
	ProductID    uint      `json:"product"`
	ProductName  string    `gorm:"-" json:"product_name"`  // Read-only
	ProductPrice Price     `gorm:"-" json:"product_price"` // Read-only
	DateTime     time.Time `json:"data_time"`
	Applicant    string    `json:"applicant"`
	Obs          string    `gorm:"-" json:"obs"` // From Order
}

type Order struct {
	Base
	ProductComandaID *uint      `json:"productComanda"`
	ProductID        uint       `json:"id_product"`
	ComandaID        uint       `json:"id_comanda"`
	Obs              string     `json:"obs"`
	Queue            time.Time  `json:"queue"`
	Preparing        *time.Time `json:"preparing"`
	Finished         *time.Time `json:"finished"`
	Delivered        *time.Time `json:"delivered"`
	Canceled         *time.Time `json:"canceled"`
}

func (o *Order) BeforeCreate(tx *gorm.DB) (err error) {
	// Call Base.BeforeCreate to generate UUID
	if err := o.Base.BeforeCreate(tx); err != nil {
		return err
	}
	if o.Queue.IsZero() {
		o.Queue = time.Now()
	}
	return
}

type TypePay struct {
	Base
	Name   string `json:"name"`
	Active bool   `gorm:"default:true" json:"active"`
}

type Payment struct {
	Base
	Value       Price     `json:"value"`
	TypePayID   uint      `json:"type_pay"`
	ComandaID   uint      `json:"comanda"`
	ClientID    *uint     `json:"client"`
	Description string    `json:"description"`
	DateTime    time.Time `json:"datetime"`
}

type User struct {
	Base
	Username  string `gorm:"uniqueIndex" json:"username"`
	Password  string `json:"password"`
	Email     string `json:"email"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	IsStaff   bool   `json:"is_staff"`
	IsActive  bool   `json:"is_active"`
}

type SyncState struct {
	ID         uint `gorm:"primaryKey"`
	LastSyncID int  `gorm:"default:0"`
}

type ChangeLog struct {
	ID        int       `json:"id"`
	ModelName string    `json:"model_name"`
	ObjectID  uint      `json:"object_id"`
	Action    string    `json:"action"` // SAVE or DELETE
	Timestamp time.Time `json:"timestamp"`
}
