package cloudflare

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"

	"agent-wdd/log"
)

// Zone represents a Cloudflare zone (domain)
type Zone struct {
	ID                  string      `json:"id"`
	Name                string      `json:"name"`
	Status              string      `json:"status"`
	Paused              bool        `json:"paused"`
	Type                string      `json:"type"`
	DevelopmentMode     int         `json:"development_mode"`
	NameServers         []string    `json:"name_servers"`
	OriginalNameServers []string    `json:"original_name_servers"`
	OriginalRegistrar   interface{} `json:"original_registrar"`
	OriginalDNSHost     interface{} `json:"original_dnshost"`
	ModifiedOn          string      `json:"modified_on"`
	CreatedOn           string      `json:"created_on"`
	ActivatedOn         string      `json:"activated_on"`
	Meta                ZoneMeta    `json:"meta"`
	Owner               Owner       `json:"owner"`
	Account             Account     `json:"account"`
	Tenant              Tenant      `json:"tenant"`
	TenantUnit          TenantUnit  `json:"tenant_unit"`
	Permissions         []string    `json:"permissions"`
	Plan                Plan        `json:"plan"`
}

// ZoneMeta contains zone metadata
type ZoneMeta struct {
	Step                   int  `json:"step"`
	CustomCertificateQuota int  `json:"custom_certificate_quota"`
	PageRuleQuota          int  `json:"page_rule_quota"`
	PhishingDetected       bool `json:"phishing_detected"`
}

// Owner represents the owner of a zone
type Owner struct {
	ID    interface{} `json:"id"`
	Type  string      `json:"type"`
	Email interface{} `json:"email"`
}

// Account represents a Cloudflare account
type Account struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

// Tenant represents a tenant
type Tenant struct {
	ID   interface{} `json:"id"`
	Name interface{} `json:"name"`
}

// TenantUnit represents a tenant unit
type TenantUnit struct {
	ID interface{} `json:"id"`
}

// Plan represents a zone plan
type Plan struct {
	ID                string `json:"id"`
	Name              string `json:"name"`
	Price             int    `json:"price"`
	Currency          string `json:"currency"`
	Frequency         string `json:"frequency"`
	IsSubscribed      bool   `json:"is_subscribed"`
	CanSubscribe      bool   `json:"can_subscribe"`
	LegacyID          string `json:"legacy_id"`
	LegacyDiscount    bool   `json:"legacy_discount"`
	ExternallyManaged bool   `json:"externally_managed"`
}

// ZoneFilter represents filters for listing zones
type ZoneFilter struct {
	Name      string
	Status    string
	Page      int
	PerPage   int
	Direction string
	Match     string
}

// ListZones retrieves a list of zones from Cloudflare based on the provided filters
//
// Parameters:
//   - filter: Optional filter to apply to the zone list
//
// Returns:
//   - []Zone: List of zones
//   - error: Any errors that occurred during the request
func (c *CloudflareClient) ListZones(filter *ZoneFilter) ([]Zone, error) {
	log.Debug("Listing zones with filter: %+v", filter)

	// Build URL and query parameters
	endpoint := fmt.Sprintf("%s/zones", c.baseURL)
	u, err := url.Parse(endpoint)
	if err != nil {
		log.Error("Failed to parse URL: %v", err)
		return nil, fmt.Errorf("failed to parse URL: %w", err)
	}

	q := u.Query()
	if filter != nil {
		if filter.Name != "" {
			q.Add("name", filter.Name)
		}
		if filter.Status != "" {
			q.Add("status", filter.Status)
		}
		if filter.Page > 0 {
			q.Add("page", fmt.Sprintf("%d", filter.Page))
		}
		if filter.PerPage > 0 {
			q.Add("per_page", fmt.Sprintf("%d", filter.PerPage))
		}
		if filter.Direction != "" {
			q.Add("direction", filter.Direction)
		}
		if filter.Match != "" {
			q.Add("match", filter.Match)
		}
	}
	u.RawQuery = q.Encode()

	// Make request
	resp, err := c.doRequest(http.MethodGet, u.String(), nil)
	if err != nil {
		log.Error("Failed to list zones: %v", err)
		return nil, fmt.Errorf("failed to list zones: %w", err)
	}

	// Parse response
	var zones []Zone
	result, err := json.Marshal(resp.Result)
	if err != nil {
		log.Error("Failed to marshal result: %v", err)
		return nil, fmt.Errorf("failed to marshal result: %w", err)
	}

	if err := json.Unmarshal(result, &zones); err != nil {
		log.Error("Failed to unmarshal zones: %v", err)
		return nil, fmt.Errorf("failed to unmarshal zones: %w", err)
	}

	log.Info("Successfully retrieved %d zones", len(zones))
	return zones, nil
}

// GetZone retrieves details of a specific zone by ID or name
//
// Parameters:
//   - identifier: The zone ID or domain name
//
// Returns:
//   - *Zone: The zone details
//   - error: Any errors that occurred during the request
func (c *CloudflareClient) GetZone(identifier string) (*Zone, error) {
	log.Debug("Getting zone details for identifier: %s", identifier)

	// Determine if identifier is an ID or a domain name
	isID := true
	for _, char := range identifier {
		if (char < '0' || char > '9') && (char < 'a' || char > 'f') && (char < 'A' || char > 'F') {
			isID = false
			break
		}
	}

	var endpoint string
	if isID {
		endpoint = fmt.Sprintf("%s/zones/%s", c.baseURL, identifier)
	} else {

		// tc.hk.107421.xyz  ipv6.t2.107421.xyz 转换为 107421.xyz
		// 寻找.的个数 如果大于 从后往前找到 第二个 . 的位置
		dotCount := strings.Count(identifier, ".")
		if dotCount > 1 {
			// 从后往前找到 第二个 . 的位置
			lastDotIndex := strings.LastIndex(identifier, ".")
			secondLastDotIndex := strings.LastIndex(identifier[:lastDotIndex], ".")
			identifier = identifier[secondLastDotIndex+1:]
		} else if dotCount == 0 {
			// 没有. 报错
			log.Error("未找到域名 %s 的ZoneID", identifier)
			return nil, fmt.Errorf("no zone found with name: %s", identifier)
		}

		log.Debug("转换后的域名: %s", identifier)

		// List zones with name filter
		zones, err := c.ListZones(&ZoneFilter{Name: identifier})
		if err != nil {
			return nil, err
		}

		if len(zones) == 0 {
			log.Error("No zone found with name: %s", identifier)
			return nil, fmt.Errorf("no zone found with name: %s", identifier)
		}

		endpoint = fmt.Sprintf("%s/zones/%s", c.baseURL, zones[0].ID)
	}

	// Make request
	resp, err := c.doRequest(http.MethodGet, endpoint, nil)
	if err != nil {
		log.Error("Failed to get zone: %v", err)
		return nil, fmt.Errorf("failed to get zone: %w", err)
	}

	// Parse response
	var zone Zone
	result, err := json.Marshal(resp.Result)
	if err != nil {
		log.Error("Failed to marshal result: %v", err)
		return nil, fmt.Errorf("failed to marshal result: %w", err)
	}

	if err := json.Unmarshal(result, &zone); err != nil {
		log.Error("Failed to unmarshal zone: %v", err)
		return nil, fmt.Errorf("failed to unmarshal zone: %w", err)
	}

	log.Info("Successfully retrieved zone: %s (%s)", zone.Name, zone.ID)
	return &zone, nil
}
