package models

import (
	"encoding/json"
	"time"

	"gorm.io/gorm"
)

type Template struct {
	ID          string `json:"id" gorm:"primaryKey"`
	Name        string `json:"name" gorm:"not null"`
	Description string `json:"description"`
	Version     string `json:"version" gorm:"index"`

	// Configuration as JSON string in DB
	ConfigJSON string `json:"-" gorm:"column:config;type:text"`

	// Virtual field for ORM serialization/deserialization
	Config TemplateConfig `json:"config" gorm:"-"`

	CreatedAt time.Time      `json:"createdAt" gorm:"autoCreateTime"`
	UpdatedAt time.Time      `json:"updatedAt" gorm:"autoUpdateTime"`
	CreatedBy string         `json:"createdBy" gorm:"index"` // User ID who created the template
	DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`         // Soft delete support

	// Relationships
	Deployments []Deployment `json:"deployments" gorm:"foreignKey:TemplateID"` // Deployments using this template
}

type TemplateConfig struct {
	Apps            []AppConfig       `json:"apps"`                   // Apps included in this template
	NetworkPolicies []NetworkPolicy   `json:"networkPolicies"`        // Network policies to apply
	EnvVariables    map[string]string `json:"envVariables,omitempty"` // Environment variables
	Secrets         []SecretConfig    `json:"secrets,omitempty"`      // Secret configurations
}

type AppConfig struct {
	ID           string            `json:"id"`                     // Reference to the app
	Name         string            `json:"name"`                   // Name of the app in this template
	ExposedPorts []int             `json:"exposedPorts,omitempty"` // Ports to expose
	PublicAccess bool              `json:"publicAccess"`           // Whether the app is publicly accessible
	Resources    ResourceConfig    `json:"resources"`              // Resource allocation
	Autoscaling  AutoscalingConfig `json:"autoscaling,omitempty"`  // Autoscaling configuration
	EnvOverrides map[string]string `json:"envOverrides,omitempty"` // Environment variable overrides
	ServiceMesh  bool              `json:"serviceMesh"`            // Whether to include in service mesh
}

type ResourceConfig struct {
	CPU     string `json:"cpu"`     // e.g., "0.5"
	Memory  string `json:"memory"`  // e.g., "512Mi"
	Storage string `json:"storage"` // e.g., "1Gi"
}

type AutoscalingConfig struct {
	Enabled      bool   `json:"enabled"`      // Whether autoscaling is enabled
	MinReplicas  int    `json:"minReplicas"`  // Minimum number of replicas
	MaxReplicas  int    `json:"maxReplicas"`  // Maximum number of replicas
	CPUThreshold int    `json:"cpuThreshold"` // CPU threshold for scaling (percentage)
	Metric       string `json:"metric"`       // Metric to base scaling on (e.g., "cpu", "memory")
}

type NetworkPolicy struct {
	Name        string   `json:"name"`            // Policy name
	FromApps    []string `json:"fromApps"`        // Source apps
	ToApps      []string `json:"toApps"`          // Destination apps
	Ports       []int    `json:"ports,omitempty"` // Allowed ports
	AllowEgress bool     `json:"allowEgress"`     // Whether to allow egress traffic
}

type SecretConfig struct {
	Name        string `json:"name"`        // Secret name
	Description string `json:"description"` // Secret description
	Required    bool   `json:"required"`    // Whether the secret is required
}

// BeforeSave serializes the embedded JSON fields
func (t *Template) BeforeSave(tx *gorm.DB) error {
	// Marshal Config to JSON
	configJSON, err := json.Marshal(t.Config)
	if err != nil {
		return err
	}
	t.ConfigJSON = string(configJSON)

	return nil
}

// AfterFind deserializes the JSON fields
func (t *Template) AfterFind(tx *gorm.DB) error {
	// Unmarshal Config from JSON
	if t.ConfigJSON != "" {
		if err := json.Unmarshal([]byte(t.ConfigJSON), &t.Config); err != nil {
			return err
		}
	}

	return nil
}
