package discovery

import (
	"context"
	"fmt"

	"github.com/pkg/errors"
	"github.com/sankofa/crossplane-provider-proxmox/pkg/cloudflare"
)

// CloudflareDiscoveryAgent discovers Cloudflare resources
type CloudflareDiscoveryAgent struct {
	client *cloudflare.Client
	site   string
	region string
}

// NewCloudflareDiscoveryAgent creates a new Cloudflare discovery agent
func NewCloudflareDiscoveryAgent(client *cloudflare.Client, site, region string) *CloudflareDiscoveryAgent {
	return &CloudflareDiscoveryAgent{
		client: client,
		site:   site,
		region: region,
	}
}

// DiscoverTunnels discovers all Cloudflare Tunnels
func (a *CloudflareDiscoveryAgent) DiscoverTunnels(ctx context.Context) ([]DiscoveredResource, error) {
	tunnels, err := a.client.ListTunnels(ctx)
	if err != nil {
		return nil, errors.Wrap(err, "failed to list tunnels")
	}

	var resources []DiscoveredResource
	for _, tunnel := range tunnels {
		resources = append(resources, DiscoveredResource{
			ResourceType: "TUNNEL",
			Provider:     "CLOUDFLARE",
			ProviderID:   fmt.Sprintf("tunnel:%s", tunnel.ID),
			Name:         tunnel.Name,
			Region:       a.region,
			SiteID:       a.site,
			Metadata: map[string]interface{}{
				"id":          tunnel.ID,
				"status":      tunnel.Status,
				"connections": tunnel.Connections,
				"createdAt":   tunnel.CreatedAt,
			},
			Tags: []string{"cloudflare", "tunnel"},
		})
	}

	return resources, nil
}

// DiscoverDNSRecords discovers all DNS records
func (a *CloudflareDiscoveryAgent) DiscoverDNSRecords(ctx context.Context) ([]DiscoveredResource, error) {
	zones, err := a.client.ListZones(ctx)
	if err != nil {
		return nil, errors.Wrap(err, "failed to list zones")
	}

	var resources []DiscoveredResource
	for _, zoneID := range zones {
		records, err := a.client.ListDNSRecords(ctx, zoneID)
		if err != nil {
			continue // Skip zones we can't access
		}

		for _, record := range records {
			resources = append(resources, DiscoveredResource{
				ResourceType: "DNS_RECORD",
				Provider:     "CLOUDFLARE",
				ProviderID:   fmt.Sprintf("dns:%s:%s", zoneID, record.ID),
				Name:         record.Name,
				Region:       a.region,
				SiteID:       a.site,
				Metadata: map[string]interface{}{
					"id":        record.ID,
					"type":      record.Type,
					"content":   record.Content,
					"ttl":       record.TTL,
					"zoneID":    record.ZoneID,
					"zoneName":  record.ZoneName,
				},
				Tags: []string{"cloudflare", "dns"},
			})
		}
	}

	return resources, nil
}

// DiscoverZeroTrustPolicies discovers Zero Trust access policies
func (a *CloudflareDiscoveryAgent) DiscoverZeroTrustPolicies(ctx context.Context) ([]DiscoveredResource, error) {
	policies, err := a.client.ListZeroTrustPolicies(ctx)
	if err != nil {
		return nil, errors.Wrap(err, "failed to list Zero Trust policies")
	}

	var resources []DiscoveredResource
	for _, policy := range policies {
		resources = append(resources, DiscoveredResource{
			ResourceType: "ZERO_TRUST_POLICY",
			Provider:     "CLOUDFLARE",
			ProviderID:   fmt.Sprintf("zerotrust:%s", policy.ID),
			Name:         policy.Name,
			Region:       a.region,
			SiteID:       a.site,
			Metadata: map[string]interface{}{
				"id":       policy.ID,
				"decision": policy.Decision,
				"include":  policy.Include,
				"exclude":  policy.Exclude,
				"require":  policy.Require,
			},
			Tags: []string{"cloudflare", "zerotrust", "security"},
		})
	}

	return resources, nil
}

// DiscoverAll discovers all Cloudflare resources
func (a *CloudflareDiscoveryAgent) DiscoverAll(ctx context.Context) ([]DiscoveredResource, error) {
	var allResources []DiscoveredResource

	// Discover tunnels
	tunnels, err := a.DiscoverTunnels(ctx)
	if err != nil {
		return nil, errors.Wrap(err, "failed to discover tunnels")
	}
	allResources = append(allResources, tunnels...)

	// Discover DNS records
	dnsRecords, err := a.DiscoverDNSRecords(ctx)
	if err != nil {
		return nil, errors.Wrap(err, "failed to discover DNS records")
	}
	allResources = append(allResources, dnsRecords...)

	// Discover Zero Trust policies
	policies, err := a.DiscoverZeroTrustPolicies(ctx)
	if err != nil {
		return nil, errors.Wrap(err, "failed to discover Zero Trust policies")
	}
	allResources = append(allResources, policies...)

	return allResources, nil
}

