package collector

import (
	"context"
	"time"

	model "security-center-backend/internal/modules/caasm/model"
)

// AssetResult holds the raw collected data before it's persisted.
// It allows the collector to return a mix of different asset types.
type AssetResult struct {
	Assets          []model.Asset
	IPAssets        []model.IPAsset
	DomainAssets    []model.DomainAsset
	Ports           []model.IPPortIndex // Port inventory from security groups, listeners, etc.
	PartialFailures []CollectionIssue
	CollectedAt     time.Time
}

type CollectionIssue struct {
	Scope   string `json:"scope"`
	Target  string `json:"target,omitempty"`
	Message string `json:"message"`
}

type ChunkCheckpoint struct {
	GlobalService               string `json:"global_service,omitempty"`
	Region                      string `json:"region,omitempty"`
	Route53ZoneID               string `json:"route53_zone_id,omitempty"`
	Route53Zone                 string `json:"route53_zone,omitempty"`
	Route53ZoneComplete         bool   `json:"route53_zone_complete,omitempty"`
	Route53NextRecordName       string `json:"route53_next_record_name,omitempty"`
	Route53NextRecordType       string `json:"route53_next_record_type,omitempty"`
	Route53NextRecordIdentifier string `json:"route53_next_record_identifier,omitempty"`
	Eligible                    bool   `json:"eligible"`
}

type AssetChunk struct {
	Result     AssetResult
	Scope      string                 `json:"scope"`
	Target     string                 `json:"target,omitempty"`
	Sequence   int                    `json:"sequence"`
	Metadata   map[string]interface{} `json:"metadata,omitempty"`
	Checkpoint ChunkCheckpoint        `json:"checkpoint"`
}

type CollectionSummary struct {
	CollectedAt     time.Time
	PartialFailures []CollectionIssue
	ChunkCount      int
}

type Route53ZoneProgress struct {
	ZoneID               string `json:"zone_id,omitempty"`
	ZoneName             string `json:"zone_name,omitempty"`
	NextRecordName       string `json:"next_record_name,omitempty"`
	NextRecordType       string `json:"next_record_type,omitempty"`
	NextRecordIdentifier string `json:"next_record_identifier,omitempty"`
}

type ResumeCursor struct {
	WindowStartedAt       string                         `json:"window_started_at,omitempty"`
	CompletedGlobal       []string                       `json:"completed_global,omitempty"`
	CompletedRegions      []string                       `json:"completed_regions,omitempty"`
	Route53CompletedZones []string                       `json:"route53_completed_zones,omitempty"`
	Route53ZoneProgress   map[string]Route53ZoneProgress `json:"route53_zone_progress,omitempty"`
}

type ChunkSink interface {
	PersistChunk(ctx context.Context, chunk *AssetChunk) error
}

// Collector defines the interface for cloud resource collectors.
type Collector interface {
	// Collect fetches assets from the cloud provider.
	Collect(ctx context.Context) (*AssetResult, error)
	// Provider returns the cloud provider name (e.g., "aws", "gcp").
	Provider() string
	// SetEventReporter sets the reporter for granular progress updates.
	SetEventReporter(reporter EventReporter)
}

type ChunkCollector interface {
	Collector
	CollectChunks(ctx context.Context, sink ChunkSink) (*CollectionSummary, error)
}

// EventReporter defines the interface for reporting sync job events.
type EventReporter interface {
	Report(eventType string, message string, metadata map[string]interface{})
}

func (r *AssetResult) Merge(other *AssetResult) {
	if r == nil || other == nil {
		return
	}
	r.Assets = append(r.Assets, other.Assets...)
	r.IPAssets = append(r.IPAssets, other.IPAssets...)
	r.DomainAssets = append(r.DomainAssets, other.DomainAssets...)
	r.Ports = append(r.Ports, other.Ports...)
	r.PartialFailures = append(r.PartialFailures, other.PartialFailures...)
	if r.CollectedAt.IsZero() {
		r.CollectedAt = other.CollectedAt
	}
}
