package dto

import (
	"github.com/shopspring/decimal"
	"github.com/treytartt/honeydue-api/internal/middleware"
)

// PaginationParams holds pagination query parameters
type PaginationParams struct {
	Page    int    `form:"page" validate:"omitempty,min=1"`
	PerPage int    `form:"per_page" validate:"omitempty,min=1,max=10000"`
	Search  string `form:"search"`
	SortBy  string `form:"sort_by"`
	SortDir string `form:"sort_dir" validate:"omitempty,oneof=asc desc"`
}

// GetPage returns the page number with default
func (p *PaginationParams) GetPage() int {
	if p.Page < 1 {
		return 1
	}
	return p.Page
}

// GetPerPage returns items per page with default
func (p *PaginationParams) GetPerPage() int {
	if p.PerPage < 1 {
		return 20
	}
	if p.PerPage > 10000 {
		return 10000
	}
	return p.PerPage
}

// GetOffset calculates the database offset
func (p *PaginationParams) GetOffset() int {
	return (p.GetPage() - 1) * p.GetPerPage()
}

// GetSortDir returns sort direction with default
func (p *PaginationParams) GetSortDir() string {
	if p.SortDir == "asc" {
		return "ASC"
	}
	return "DESC"
}

// GetSafeSortBy validates SortBy against an allowlist to prevent SQL injection.
// Returns the matching allowed column, or defaultCol if SortBy is empty or not allowed.
func (p *PaginationParams) GetSafeSortBy(allowedCols []string, defaultCol string) string {
	return middleware.SanitizeSortColumn(p.SortBy, allowedCols, defaultCol)
}

// UserFilters holds user-specific filter parameters
type UserFilters struct {
	PaginationParams
	IsActive    *bool  `form:"is_active"`
	IsStaff     *bool  `form:"is_staff"`
	IsSuperuser *bool  `form:"is_superuser"`
	Verified    *bool  `form:"verified"`
}

// CreateUserRequest for creating a new user
type CreateUserRequest struct {
	Username    string `json:"username" validate:"required,min=3,max=150"`
	Email       string `json:"email" validate:"required,email"`
	Password    string `json:"password" validate:"required,min=8"`
	FirstName   string `json:"first_name" validate:"max=150"`
	LastName    string `json:"last_name" validate:"max=150"`
	PhoneNumber string `json:"phone_number" validate:"max=20"`
	IsActive    *bool  `json:"is_active"`
	IsStaff     *bool  `json:"is_staff"`
	IsSuperuser *bool  `json:"is_superuser"`
}

// UpdateUserRequest for updating a user
type UpdateUserRequest struct {
	Username    *string `json:"username" validate:"omitempty,min=3,max=150"`
	Email       *string `json:"email" validate:"omitempty,email"`
	Password    *string `json:"password" validate:"omitempty,min=8"`
	FirstName   *string `json:"first_name" validate:"omitempty,max=150"`
	LastName    *string `json:"last_name" validate:"omitempty,max=150"`
	PhoneNumber *string `json:"phone_number" validate:"omitempty,max=20"`
	IsActive    *bool   `json:"is_active"`
	IsStaff     *bool   `json:"is_staff"`
	IsSuperuser *bool   `json:"is_superuser"`
	Verified    *bool   `json:"verified"`
}

// BulkDeleteRequest for bulk delete operations
type BulkDeleteRequest struct {
	IDs []uint `json:"ids" validate:"required,min=1"`
}

// ResidenceFilters holds residence-specific filter parameters
type ResidenceFilters struct {
	PaginationParams
	IsActive *bool `form:"is_active"`
	OwnerID  *uint `form:"owner_id"`
}

// UpdateResidenceRequest for updating a residence
type UpdateResidenceRequest struct {
	OwnerID        *uint    `json:"owner_id"`
	Name           *string  `json:"name" validate:"omitempty,max=200"`
	PropertyTypeID *uint    `json:"property_type_id"`
	StreetAddress  *string  `json:"street_address" validate:"omitempty,max=255"`
	ApartmentUnit  *string  `json:"apartment_unit" validate:"omitempty,max=50"`
	City           *string  `json:"city" validate:"omitempty,max=100"`
	StateProvince  *string  `json:"state_province" validate:"omitempty,max=100"`
	PostalCode     *string  `json:"postal_code" validate:"omitempty,max=20"`
	Country        *string  `json:"country" validate:"omitempty,max=100"`
	Bedrooms       *int     `json:"bedrooms"`
	Bathrooms      *float64 `json:"bathrooms"`
	SquareFootage  *int     `json:"square_footage"`
	LotSize        *float64 `json:"lot_size"`
	YearBuilt      *int     `json:"year_built"`
	Description    *string  `json:"description"`
	PurchaseDate   *string  `json:"purchase_date"`
	PurchasePrice  *decimal.Decimal `json:"purchase_price"`
	IsActive       *bool            `json:"is_active"`
	IsPrimary      *bool            `json:"is_primary"`
}

// TaskFilters holds task-specific filter parameters
type TaskFilters struct {
	PaginationParams
	ResidenceID *uint `form:"residence_id"`
	CategoryID  *uint `form:"category_id"`
	PriorityID  *uint `form:"priority_id"`
	InProgress  *bool `form:"in_progress"`
	IsCancelled *bool `form:"is_cancelled"`
	IsArchived  *bool `form:"is_archived"`
}

// UpdateTaskRequest for updating a task
type UpdateTaskRequest struct {
	ResidenceID   *uint    `json:"residence_id"`
	CreatedByID   *uint    `json:"created_by_id"`
	AssignedToID  *uint    `json:"assigned_to_id"`
	Title         *string  `json:"title" validate:"omitempty,max=200"`
	Description   *string  `json:"description"`
	CategoryID    *uint    `json:"category_id"`
	PriorityID    *uint    `json:"priority_id"`
	FrequencyID   *uint    `json:"frequency_id"`
	InProgress    *bool    `json:"in_progress"`
	DueDate       *string  `json:"due_date"`
	NextDueDate   *string  `json:"next_due_date"`
	EstimatedCost *decimal.Decimal `json:"estimated_cost"`
	ActualCost    *decimal.Decimal `json:"actual_cost"`
	ContractorID  *uint    `json:"contractor_id"`
	ParentTaskID  *uint    `json:"parent_task_id"`
	IsCancelled   *bool    `json:"is_cancelled"`
	IsArchived    *bool    `json:"is_archived"`
}

// ContractorFilters holds contractor-specific filter parameters
type ContractorFilters struct {
	PaginationParams
	IsActive    *bool `form:"is_active"`
	IsFavorite  *bool `form:"is_favorite"`
	ResidenceID *uint `form:"residence_id"`
}

// UpdateContractorRequest for updating a contractor
type UpdateContractorRequest struct {
	ResidenceID   *uint    `json:"residence_id"`
	CreatedByID   *uint    `json:"created_by_id"`
	Name          *string  `json:"name" validate:"omitempty,max=200"`
	Company       *string  `json:"company" validate:"omitempty,max=200"`
	Phone         *string  `json:"phone" validate:"omitempty,max=20"`
	Email         *string  `json:"email" validate:"omitempty,email"`
	Website       *string  `json:"website" validate:"omitempty,max=200"`
	Notes         *string  `json:"notes"`
	StreetAddress *string  `json:"street_address" validate:"omitempty,max=255"`
	City          *string  `json:"city" validate:"omitempty,max=100"`
	StateProvince *string  `json:"state_province" validate:"omitempty,max=100"`
	PostalCode    *string  `json:"postal_code" validate:"omitempty,max=20"`
	Rating        *float64 `json:"rating"`
	IsFavorite    *bool    `json:"is_favorite"`
	IsActive      *bool    `json:"is_active"`
	SpecialtyIDs  []uint   `json:"specialty_ids"`
}

// DocumentFilters holds document-specific filter parameters
type DocumentFilters struct {
	PaginationParams
	IsActive     *bool   `form:"is_active"`
	ResidenceID  *uint   `form:"residence_id"`
	DocumentType *string `form:"document_type"`
}

// UpdateDocumentRequest for updating a document
type UpdateDocumentRequest struct {
	ResidenceID     *uint    `json:"residence_id"`
	CreatedByID     *uint    `json:"created_by_id"`
	Title           *string  `json:"title" validate:"omitempty,max=200"`
	Description     *string  `json:"description"`
	DocumentType    *string  `json:"document_type"`
	FileURL         *string  `json:"file_url" validate:"omitempty,max=500"`
	FileName        *string  `json:"file_name" validate:"omitempty,max=255"`
	FileSize        *int64   `json:"file_size"`
	MimeType        *string  `json:"mime_type" validate:"omitempty,max=100"`
	PurchaseDate    *string  `json:"purchase_date"`
	ExpiryDate      *string  `json:"expiry_date"`
	PurchasePrice   *decimal.Decimal `json:"purchase_price"`
	Vendor          *string          `json:"vendor" validate:"omitempty,max=200"`
	SerialNumber    *string  `json:"serial_number" validate:"omitempty,max=100"`
	ModelNumber     *string  `json:"model_number" validate:"omitempty,max=100"`
	Provider        *string  `json:"provider" validate:"omitempty,max=200"`
	ProviderContact *string  `json:"provider_contact" validate:"omitempty,max=200"`
	ClaimPhone      *string  `json:"claim_phone" validate:"omitempty,max=50"`
	ClaimEmail      *string  `json:"claim_email" validate:"omitempty,email"`
	ClaimWebsite    *string  `json:"claim_website" validate:"omitempty,max=500"`
	Notes           *string  `json:"notes"`
	TaskID          *uint    `json:"task_id"`
	IsActive        *bool    `json:"is_active"`
}

// NotificationFilters holds notification-specific filter parameters
type NotificationFilters struct {
	PaginationParams
	UserID           *uint   `form:"user_id"`
	NotificationType *string `form:"notification_type"`
	Sent             *bool   `form:"sent"`
	Read             *bool   `form:"read"`
}

// UpdateNotificationRequest for updating a notification
type UpdateNotificationRequest struct {
	Title *string `json:"title" validate:"omitempty,max=200"`
	Body  *string `json:"body" validate:"omitempty,max=1000"`
	Read  *bool   `json:"read"`
}

// SubscriptionFilters holds subscription-specific filter parameters
type SubscriptionFilters struct {
	PaginationParams
	UserID      *uint   `form:"user_id"`
	Tier        *string `form:"tier"`
	Platform    *string `form:"platform"`
	AutoRenew   *bool   `form:"auto_renew"`
	Active      *bool   `form:"active"`
	HasStripe   *bool   `form:"has_stripe"`
	TrialActive *bool   `form:"trial_active"`
}

// UpdateSubscriptionRequest for updating a subscription
type UpdateSubscriptionRequest struct {
	Tier         *string `json:"tier" validate:"omitempty,oneof=free premium pro"`
	AutoRenew    *bool   `json:"auto_renew"`
	IsFree       *bool   `json:"is_free"`
	Platform     *string `json:"platform" validate:"omitempty,max=20"`
	SubscribedAt *string `json:"subscribed_at"`
	ExpiresAt    *string `json:"expires_at"`
	CancelledAt  *string `json:"cancelled_at"`
	// Stripe fields
	StripeCustomerID     *string `json:"stripe_customer_id"`
	StripeSubscriptionID *string `json:"stripe_subscription_id"`
	StripePriceID        *string `json:"stripe_price_id"`
	// Trial fields
	TrialStart *string `json:"trial_start"`
	TrialEnd   *string `json:"trial_end"`
	TrialUsed  *bool   `json:"trial_used"`
}

// CreateResidenceRequest for creating a new residence
type CreateResidenceRequest struct {
	OwnerID        uint    `json:"owner_id" validate:"required"`
	Name           string  `json:"name" validate:"required,max=200"`
	PropertyTypeID *uint   `json:"property_type_id"`
	StreetAddress  string  `json:"street_address" validate:"max=255"`
	ApartmentUnit  string  `json:"apartment_unit" validate:"max=50"`
	City           string  `json:"city" validate:"max=100"`
	StateProvince  string  `json:"state_province" validate:"max=100"`
	PostalCode     string  `json:"postal_code" validate:"max=20"`
	Country        string  `json:"country" validate:"max=100"`
	Bedrooms       *int    `json:"bedrooms"`
	Bathrooms      *float64 `json:"bathrooms"`
	SquareFootage  *int    `json:"square_footage"`
	YearBuilt      *int    `json:"year_built"`
	Description    string  `json:"description"`
	IsPrimary      bool    `json:"is_primary"`
}

// CreateTaskRequest for creating a new task
type CreateTaskRequest struct {
	ResidenceID   uint     `json:"residence_id" validate:"required"`
	CreatedByID   uint     `json:"created_by_id" validate:"required"`
	Title         string   `json:"title" validate:"required,max=200"`
	Description   string   `json:"description"`
	CategoryID    *uint    `json:"category_id"`
	PriorityID    *uint    `json:"priority_id"`
	FrequencyID   *uint    `json:"frequency_id"`
	InProgress    bool     `json:"in_progress"`
	AssignedToID  *uint    `json:"assigned_to_id"`
	DueDate       *string          `json:"due_date"`
	EstimatedCost *decimal.Decimal `json:"estimated_cost"`
	ContractorID  *uint            `json:"contractor_id"`
}

// CreateContractorRequest for creating a new contractor
type CreateContractorRequest struct {
	ResidenceID   *uint   `json:"residence_id"`
	CreatedByID   uint    `json:"created_by_id" validate:"required"`
	Name          string  `json:"name" validate:"required,max=200"`
	Company       string  `json:"company" validate:"max=200"`
	Phone         string  `json:"phone" validate:"max=20"`
	Email         string  `json:"email" validate:"omitempty,email"`
	Website       string  `json:"website" validate:"max=200"`
	Notes         string  `json:"notes"`
	StreetAddress string  `json:"street_address" validate:"max=255"`
	City          string  `json:"city" validate:"max=100"`
	StateProvince string  `json:"state_province" validate:"max=100"`
	PostalCode    string  `json:"postal_code" validate:"max=20"`
	IsFavorite    bool    `json:"is_favorite"`
	SpecialtyIDs  []uint  `json:"specialty_ids"`
}

// CreateDocumentRequest for creating a new document
type CreateDocumentRequest struct {
	ResidenceID   uint    `json:"residence_id" validate:"required"`
	CreatedByID   uint    `json:"created_by_id" validate:"required"`
	Title         string  `json:"title" validate:"required,max=200"`
	Description   string  `json:"description"`
	DocumentType  string  `json:"document_type" validate:"omitempty,oneof=general warranty receipt contract insurance manual"`
	FileURL       string  `json:"file_url" validate:"max=500"`
	FileName      string  `json:"file_name" validate:"max=255"`
	FileSize      *int64  `json:"file_size"`
	MimeType      string  `json:"mime_type" validate:"max=100"`
	PurchaseDate  *string `json:"purchase_date"`
	ExpiryDate    *string `json:"expiry_date"`
	PurchasePrice *decimal.Decimal `json:"purchase_price"`
	Vendor        string           `json:"vendor" validate:"max=200"`
	SerialNumber  string  `json:"serial_number" validate:"max=100"`
	ModelNumber   string  `json:"model_number" validate:"max=100"`
	TaskID        *uint   `json:"task_id"`
}

// SendTestNotificationRequest for sending a test push notification
type SendTestNotificationRequest struct {
	UserID uint   `json:"user_id" validate:"required"`
	Title  string `json:"title" validate:"required,max=200"`
	Body   string `json:"body" validate:"required,max=500"`
}

// SendTestEmailRequest for sending a test email
type SendTestEmailRequest struct {
	UserID  uint   `json:"user_id" validate:"required"`
	Subject string `json:"subject" validate:"required,max=200"`
	Body    string `json:"body" validate:"required"`
}
