package models

import (
	"time"

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

// User represents an end user (customer) who makes payments
type User struct {
	ID        uuid.UUID      `json:"id" gorm:"type:char(36);primary_key"`
	ClientID  uuid.UUID      `json:"client_id" gorm:"type:char(36);not null"`
	Client    Client         `json:"client" gorm:"foreignKey:ClientID"`
	Name      string         `json:"name" gorm:"type:varchar(255);not null"`
	Username  string         `json:"username" gorm:"type:varchar(255);not null"`
	Password  string         `json:"-" gorm:"type:varchar(255);not null"` // Hidden from JSON
	Email     *string        `json:"email" gorm:"type:varchar(255)"`
	Phone     string         `json:"phone" gorm:"type:varchar(20);not null"`
	CreatedAt time.Time      `json:"created_at"`
	UpdatedAt time.Time      `json:"updated_at"`
	DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}

// Client represents a SAAS client/tenant (business)
type Client struct {
	ID uuid.UUID `json:"id" gorm:"type:char(36);primary_key"`

	// Basic Business Information
	Name               string  `json:"name" gorm:"type:varchar(255);not null"`       // Business name
	BusinessName       *string `json:"business_name" gorm:"type:varchar(255)"`       // Alternative/trading name
	BusinessType       *string `json:"business_type" gorm:"type:varchar(100)"`       // e.g., "LLC", "Corporation", "Sole Proprietorship"
	Industry           *string `json:"industry" gorm:"type:varchar(100)"`            // e.g., "Telecommunications", "Retail", "Hospitality"
	RegistrationNumber *string `json:"registration_number" gorm:"type:varchar(100)"` // Business registration number
	TaxID              *string `json:"tax_id" gorm:"type:varchar(100)"`              // Tax identification number
	VATNumber          *string `json:"vat_number" gorm:"type:varchar(100)"`          // VAT registration number

	// Contact Information
	Email          string  `json:"email" gorm:"type:varchar(255);uniqueIndex;not null"`
	Phone          *string `json:"phone" gorm:"type:varchar(20)"`
	AlternatePhone *string `json:"alternate_phone" gorm:"type:varchar(20)"`
	Website        *string `json:"website" gorm:"type:varchar(255)"`

	// Contact Person
	ContactPersonName  *string `json:"contact_person_name" gorm:"type:varchar(255)"`
	ContactPersonEmail *string `json:"contact_person_email" gorm:"type:varchar(255)"`
	ContactPersonPhone *string `json:"contact_person_phone" gorm:"type:varchar(20)"`

	// Address Information
	Address    *string `json:"address" gorm:"type:varchar(500)"` // Street address
	City       *string `json:"city" gorm:"type:varchar(100)"`
	State      *string `json:"state" gorm:"type:varchar(100)"` // State/Province
	Country    *string `json:"country" gorm:"type:varchar(100)"`
	PostalCode *string `json:"postal_code" gorm:"type:varchar(20)"`

	// Additional Information
	Description *string `json:"description" gorm:"type:text"` // Business description
	Notes       *string `json:"notes" gorm:"type:text"`       // Internal notes

	// Status & Metadata
	Status    string         `json:"status" gorm:"type:varchar(50);default:'active'"`
	IsActive  bool           `json:"is_active" gorm:"default:true"`
	CreatedAt time.Time      `json:"created_at"`
	UpdatedAt time.Time      `json:"updated_at"`
	DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}

// PaymentCredentials stores M-Pesa credentials for each client
type PaymentCredentials struct {
	ID             uuid.UUID      `json:"id" gorm:"type:char(36);primary_key"`
	ClientID       uuid.UUID      `json:"client_id" gorm:"type:char(36);not null"`
	Client         Client         `json:"client" gorm:"foreignKey:ClientID"`
	Provider       string         `json:"provider" gorm:"type:varchar(50);not null"` // e.g., "mpesa", "airtel_money"
	ConsumerKey    string         `json:"consumer_key" gorm:"type:varchar(255);not null"`
	ConsumerSecret string         `json:"consumer_secret" gorm:"type:varchar(255);not null"`
	ShortCode      string         `json:"short_code" gorm:"type:varchar(20);not null"`
	PassKey        string         `json:"pass_key" gorm:"type:varchar(255);not null"`
	BaseURL        string         `json:"base_url" gorm:"type:varchar(500);not null"`
	CallbackURL    string         `json:"callback_url" gorm:"type:varchar(500)"`
	IsActive       bool           `json:"is_active" gorm:"default:true"`
	CreatedAt      time.Time      `json:"created_at"`
	UpdatedAt      time.Time      `json:"updated_at"`
	DeletedAt      gorm.DeletedAt `json:"-" gorm:"index"`
}

// Transaction represents a payment transaction
type Transaction struct {
	ID               uuid.UUID        `json:"id" gorm:"type:char(36);primary_key"`
	ClientID         uuid.UUID        `json:"client_id" gorm:"type:char(36);not null"`
	Client           Client           `json:"client" gorm:"foreignKey:ClientID"`
	UserID           *uuid.UUID       `json:"user_id" gorm:"type:char(36);default:null"`
	User             *User            `json:"user,omitempty" gorm:"foreignKey:UserID"`
	PackageID        *uuid.UUID       `json:"package_id" gorm:"type:char(36);default:null"`
	InternetPackage  *InternetPackage `json:"internet_package,omitempty" gorm:"foreignKey:PackageID"`
	CheckoutID       string           `json:"checkout_id" gorm:"type:varchar(100);uniqueIndex;not null"`
	Amount           float64          `json:"amount" gorm:"not null"`
	Currency         string           `json:"currency" gorm:"type:varchar(10);default:'KES'"`
	PaymentMethod    string           `json:"payment_method" gorm:"type:varchar(50);not null"`
	PaymentStatus    string           `json:"payment_status" gorm:"type:varchar(20);default:'pending'"`
	PhoneNumber      string           `json:"phone_number" gorm:"type:varchar(20);not null"`
	Reference        string           `json:"reference" gorm:"type:varchar(100)"`
	MpesaReceipt     string           `json:"mpesa_receipt" gorm:"type:varchar(50)"`
	Description      string           `json:"description" gorm:"type:varchar(500)"`
	Metadata         *string          `json:"metadata" gorm:"type:json"` // Store additional data as JSON
	Provider         string           `json:"provider" gorm:"type:varchar(50);not null"`
	ProviderResponse *string          `json:"provider_response" gorm:"type:json"`
	CreatedAt        time.Time        `gorm:"type:timestamp with time zone"`
	UpdatedAt        time.Time        `gorm:"type:timestamp with time zone"`
	DeletedAt        gorm.DeletedAt   `json:"-" gorm:"index"`
}

// InternetPackage represents internet packages/plans
type InternetPackage struct {
	ID       uuid.UUID `json:"id" gorm:"type:char(36);primary_key"`
	ClientID uuid.UUID `json:"client_id" gorm:"type:char(36);not null"`
	Client   Client    `json:"client" gorm:"foreignKey:ClientID"`

	// Basic Configuration
	PackageType     string `json:"package_type" gorm:"type:varchar(50);not null"` // Hotspot, PPPoE, Trial, Bundles
	Name            string `json:"name" gorm:"type:varchar(255);not null"`
	Description     string `json:"description" gorm:"type:varchar(500)"`
	Duration        string `json:"duration" gorm:"type:varchar(50)"` // e.g., "1 hour", "1 month"
	DurationMinutes int    `json:"duration_minutes" gorm:"type:int"`

	// Speed & Performance
	UploadSpeed   string `json:"upload_speed" gorm:"type:varchar(100)"`   // e.g., "1M", "10M"
	DownloadSpeed string `json:"download_speed" gorm:"type:varchar(100)"` // e.g., "1M", "10M"
	Speed         string `json:"speed" gorm:"type:varchar(100)"`          // Legacy field, kept for backward compatibility

	// Pricing & Devices
	Amount     float64  `json:"amount" gorm:"not null"`
	Currency   string   `json:"currency" gorm:"type:varchar(10);default:'KES'"`
	Devices    *int     `json:"devices" gorm:"type:int;default:1"`     // Simultaneous devices allowed per user
	TotalLimit *float64 `json:"total_limit" gorm:"type:decimal(10,2)"` // Total limit in GB (for Bundles)

	// Burst Features
	BurstEnabled   bool    `json:"burst_enabled" gorm:"default:false"`
	BurstLimit     *string `json:"burst_limit" gorm:"type:varchar(100)"`     // e.g., "2M"
	BurstThreshold *string `json:"burst_threshold" gorm:"type:varchar(100)"` // e.g., "512k"
	BurstTime      *int    `json:"burst_time" gorm:"type:int"`               // Duration in seconds

	// Schedule Features
	ScheduleEnabled   bool    `json:"schedule_enabled" gorm:"default:false"`
	ScheduleStartTime *string `json:"schedule_start_time" gorm:"type:varchar(10)"` // HH:MM format
	ScheduleEndTime   *string `json:"schedule_end_time" gorm:"type:varchar(10)"`   // HH:MM format
	AvailableDays     *string `json:"available_days" gorm:"type:json"`             // JSON array of days: ["Monday", "Tuesday", ...]

	// Visibility & Metadata
	HiddenFromClient bool    `json:"hidden_from_client" gorm:"default:false"`
	Features         *string `json:"features" gorm:"type:json"` // JSON array of features
	Category         string  `json:"category" gorm:"type:varchar(50)"`
	Popular          *bool   `json:"popular" gorm:"type:boolean;default:false"`
	IsActive         bool    `json:"is_active" gorm:"default:true"`

	// Timestamps
	CreatedAt time.Time      `json:"created_at"`
	UpdatedAt time.Time      `json:"updated_at"`
	DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}

// PaymentCallback represents M-Pesa callback data (embedded in transaction)
type PaymentCallback struct {
	CheckoutID   string    `json:"checkout_id"`
	ResultCode   int       `json:"result_code"`
	ResultDesc   string    `json:"result_desc"`
	Amount       float64   `json:"amount"`
	MpesaReceipt string    `json:"mpesa_receipt"`
	PhoneNumber  string    `json:"phone_number"`
	RawData      string    `json:"raw_data"`
	Processed    bool      `json:"processed"`
	ProcessedAt  time.Time `json:"processed_at"`
}

// MpesaAccessToken represents cached M-Pesa access tokens
type MpesaAccessToken struct {
	ID        uuid.UUID `json:"id" gorm:"type:char(36);primary_key"`
	ClientID  uuid.UUID `json:"client_id" gorm:"type:char(36);not null"`
	Client    Client    `json:"client" gorm:"foreignKey:ClientID"`
	Token     string    `json:"token" gorm:"type:text;not null"`
	ExpiresAt time.Time `json:"expires_at" gorm:"not null"`
	CreatedAt time.Time `json:"created_at"`
}

// TableName methods for custom table names
func (User) TableName() string {
	return "users"
}

func (Client) TableName() string {
	return "clients"
}

func (PaymentCredentials) TableName() string {
	return "payment_credentials"
}

func (Transaction) TableName() string {
	return "transactions"
}

func (InternetPackage) TableName() string {
	return "internet_packages"
}

func (MpesaAccessToken) TableName() string {
	return "mpesa_access_tokens"
}

// BeforeCreate hook to generate UUIDs
func (u *User) BeforeCreate(tx *gorm.DB) error {
	if u.ID == uuid.Nil {
		u.ID = uuid.New()
	}
	return nil
}

func (c *Client) BeforeCreate(tx *gorm.DB) error {
	if c.ID == uuid.Nil {
		c.ID = uuid.New()
	}
	return nil
}

func (pc *PaymentCredentials) BeforeCreate(tx *gorm.DB) error {
	if pc.ID == uuid.Nil {
		pc.ID = uuid.New()
	}
	return nil
}

func (t *Transaction) BeforeCreate(tx *gorm.DB) error {
	if t.ID == uuid.Nil {
		t.ID = uuid.New()
	}
	return nil
}

func (ip *InternetPackage) BeforeCreate(tx *gorm.DB) error {
	if ip.ID == uuid.Nil {
		ip.ID = uuid.New()
	}
	return nil
}

func (at *MpesaAccessToken) BeforeCreate(tx *gorm.DB) error {
	if at.ID == uuid.Nil {
		at.ID = uuid.New()
	}
	return nil
}
