package caasmmodel

import (
	"net"
	"strings"
	"time"

	coremodel "security-center-backend/internal/model"
)

type PortObservationSource string

const (
	PortObservationSourceUnknown         PortObservationSource = "unknown"
	PortObservationSourceSecurityGroup   PortObservationSource = "security_group"
	PortObservationSourceListener        PortObservationSource = "listener"
	PortObservationSourceServiceEndpoint PortObservationSource = "service_endpoint"
	PortObservationSourceTaskMapping     PortObservationSource = "task_mapping"
	PortObservationSourceInferredWeb     PortObservationSource = "inferred_web"
)

type IPPortIndex struct {
	coremodel.Base
	AssetID           uint64 `gorm:"uniqueIndex:idx_ip_port_asset_endpoint,priority:1;index:idx_ip_port_asset" json:"asset_id"`
	Asset             Asset
	Endpoint          string                `gorm:"size:255;uniqueIndex:idx_ip_port_asset_endpoint,priority:2;index:idx_ip_port_endpoint" json:"endpoint,omitempty"`
	IPAddress         string                `gorm:"size:255;index:idx_ip_port_index_ip_address" json:"ip_address,omitempty"`
	Port              uint32                `gorm:"uniqueIndex:idx_ip_port_asset_endpoint,priority:3;index:idx_exposure_port,priority:2" json:"port"`
	Protocol          string                `gorm:"size:8;uniqueIndex:idx_ip_port_asset_endpoint,priority:4" json:"protocol"`
	ObservationSource PortObservationSource `gorm:"size:64;default:unknown;uniqueIndex:idx_ip_port_asset_endpoint,priority:5;index:idx_port_observation_source" json:"observation_source,omitempty"`
	ServiceName       string                `gorm:"size:120" json:"service_name"`
	AssetService      string                `gorm:"column:asset_service;->" json:"asset_service,omitempty"`
	Product           string                `gorm:"size:255" json:"product"`
	Version           string                `gorm:"size:120" json:"version"`
	Exposure          string                `gorm:"size:32;index:idx_exposure_port,priority:1" json:"exposure"`
	Status            string                `gorm:"size:16" json:"status"`
	Evidence          coremodel.JSONB       `gorm:"type:json" json:"evidence,omitempty"`
	Confidence        coremodel.JSONB       `gorm:"type:json" json:"confidence,omitempty"`
	LastSeenAt        time.Time             `json:"last_seen_at"`
}

// TableName overrides the default GORM table name
func (IPPortIndex) TableName() string {
	return "ip_port_index"
}

func (p *IPPortIndex) NormalizeEndpointFields() {
	if p == nil {
		return
	}
	p.Endpoint = strings.TrimSpace(p.Endpoint)
	p.IPAddress = strings.TrimSpace(p.IPAddress)
	if p.Endpoint == "" {
		p.Endpoint = p.IPAddress
	}
	if p.Endpoint != "" && p.IPAddress == "" && net.ParseIP(p.Endpoint) != nil {
		p.IPAddress = p.Endpoint
	}
	if p.IPAddress != "" && net.ParseIP(p.IPAddress) == nil && strings.EqualFold(p.IPAddress, p.Endpoint) {
		p.IPAddress = ""
	}
}

func (p IPPortIndex) EndpointValue() string {
	if endpoint := strings.TrimSpace(p.Endpoint); endpoint != "" {
		return endpoint
	}
	return strings.TrimSpace(p.IPAddress)
}

func (p IPPortIndex) EndpointType() string {
	endpoint := p.EndpointValue()
	if endpoint == "" {
		return ""
	}
	if net.ParseIP(endpoint) != nil {
		return "ip"
	}
	return "hostname"
}

type AssetRelationship struct {
	coremodel.Base
	SourceAssetID    uint64          `gorm:"index:idx_rel_type_source,priority:2" json:"source_asset_id"`
	TargetAssetID    uint64          `json:"target_asset_id"`
	RelationshipType string          `gorm:"size:120;index:idx_rel_type_source,priority:1" json:"relationship_type"`
	Metadata         coremodel.JSONB `gorm:"type:json" json:"metadata"`
	LastSeenAt       time.Time       `json:"last_seen_at"`
}

type SyncJobStatus string

const (
	SyncJobQueued  SyncJobStatus = "queued"
	SyncJobPending SyncJobStatus = "pending"
	SyncJobRunning SyncJobStatus = "running"
	SyncJobSuccess SyncJobStatus = "success"
	SyncJobPartial SyncJobStatus = "partial_success"
	SyncJobFailed  SyncJobStatus = "failed"
)

type SyncJob struct {
	coremodel.Base
	JobType        string          `gorm:"size:100" json:"job_type"`
	Status         SyncJobStatus   `gorm:"size:32" json:"status"`
	CloudAccountID *uint64         `json:"cloud_account_id"`
	TriggeredBy    *uint64         `json:"triggered_by"`
	StartedAt      *time.Time      `json:"started_at"`
	FinishedAt     *time.Time      `json:"finished_at"`
	ErrorMessage   string          `gorm:"type:text" json:"error_message"`
	Metadata       coremodel.JSONB `gorm:"type:json" json:"metadata"`
}
