package auth

import (
	"encoding/json"
	"net/http"
	"strings"
	"time"
)

// IssueAPIKeyHandler issues an API key after signature verification.
// Similar to VerifyHandler but only returns the API key without JWT tokens.
// For non-default namespaces, may trigger cluster provisioning and return 202 Accepted.
//
// POST /v1/auth/api-key
// Request body: APIKeyRequest
// Response: { "api_key", "namespace", "plan", "wallet" }
// Or 202 Accepted: { "status": "provisioning", "cluster_id", "poll_url" }
func (h *Handlers) IssueAPIKeyHandler(w http.ResponseWriter, r *http.Request) {
	if h.authService == nil {
		writeError(w, http.StatusServiceUnavailable, "auth service not initialized")
		return
	}
	if r.Method != http.MethodPost {
		writeError(w, http.StatusMethodNotAllowed, "method not allowed")
		return
	}

	var req APIKeyRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		writeError(w, http.StatusBadRequest, "invalid json body")
		return
	}
	if strings.TrimSpace(req.Wallet) == "" || strings.TrimSpace(req.Nonce) == "" || strings.TrimSpace(req.Signature) == "" {
		writeError(w, http.StatusBadRequest, "wallet, nonce and signature are required")
		return
	}

	ctx := r.Context()
	verified, err := h.authService.VerifySignature(ctx, req.Wallet, req.Nonce, req.Signature, req.ChainType)
	if err != nil || !verified {
		writeError(w, http.StatusUnauthorized, "signature verification failed")
		return
	}

	// Mark nonce used
	nsID, _ := h.resolveNamespace(ctx, req.Namespace)
	h.markNonceUsed(ctx, nsID, strings.ToLower(req.Wallet), req.Nonce)

	// Check if namespace cluster provisioning is needed (for non-default namespaces)
	namespace := strings.TrimSpace(req.Namespace)
	if namespace == "" {
		namespace = "default"
	}

	if h.clusterProvisioner != nil && namespace != "default" {
		clusterID, status, needsProvisioning, err := h.clusterProvisioner.CheckNamespaceCluster(ctx, namespace)
		if err != nil {
			// Log but don't fail - cluster provisioning is optional (error may just mean no cluster yet)
			_ = err
		} else if needsProvisioning {
			// Trigger provisioning for new namespace
			nsIDInt := 0
			if id, ok := nsID.(int); ok {
				nsIDInt = id
			} else if id, ok := nsID.(int64); ok {
				nsIDInt = int(id)
			} else if id, ok := nsID.(float64); ok {
				nsIDInt = int(id)
			}

			newClusterID, pollURL, provErr := h.clusterProvisioner.ProvisionNamespaceCluster(ctx, nsIDInt, namespace, req.Wallet)
			if provErr != nil {
				writeError(w, http.StatusInternalServerError, "failed to start cluster provisioning")
				return
			}

			writeJSON(w, http.StatusAccepted, map[string]any{
				"status":                 "provisioning",
				"cluster_id":             newClusterID,
				"poll_url":               pollURL,
				"estimated_time_seconds": 60,
				"message":                "Namespace cluster is being provisioned. Poll the status URL for updates.",
			})
			return
		} else if status == "provisioning" {
			// Already provisioning, return poll URL
			writeJSON(w, http.StatusAccepted, map[string]any{
				"status":                 "provisioning",
				"cluster_id":             clusterID,
				"poll_url":               "/v1/namespace/status?id=" + clusterID,
				"estimated_time_seconds": 60,
				"message":                "Namespace cluster is being provisioned. Poll the status URL for updates.",
			})
			return
		}
		// If status is "ready" or "default", proceed with API key generation
	}

	apiKey, err := h.authService.GetOrCreateAPIKey(ctx, req.Wallet, req.Namespace)
	if err != nil {
		writeError(w, http.StatusInternalServerError, err.Error())
		return
	}

	writeJSON(w, http.StatusOK, map[string]any{
		"api_key":   apiKey,
		"namespace": req.Namespace,
		"plan": func() string {
			if strings.TrimSpace(req.Plan) == "" {
				return "free"
			}
			return req.Plan
		}(),
		"wallet": strings.ToLower(strings.TrimPrefix(strings.TrimPrefix(req.Wallet, "0x"), "0X")),
	})
}

// SimpleAPIKeyHandler generates an API key without signature verification.
// This is a simplified flow for development/testing purposes.
//
// POST /v1/auth/simple-key
// Request body: SimpleAPIKeyRequest
// Response: { "api_key", "namespace", "wallet", "created" }
func (h *Handlers) SimpleAPIKeyHandler(w http.ResponseWriter, r *http.Request) {
	if h.authService == nil {
		writeError(w, http.StatusServiceUnavailable, "auth service not initialized")
		return
	}
	if r.Method != http.MethodPost {
		writeError(w, http.StatusMethodNotAllowed, "method not allowed")
		return
	}

	var req SimpleAPIKeyRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		writeError(w, http.StatusBadRequest, "invalid json body")
		return
	}
	if strings.TrimSpace(req.Wallet) == "" {
		writeError(w, http.StatusBadRequest, "wallet is required")
		return
	}

	// Check if namespace cluster provisioning is needed (for non-default namespaces)
	namespace := strings.TrimSpace(req.Namespace)
	if namespace == "" {
		namespace = "default"
	}

	ctx := r.Context()
	if h.clusterProvisioner != nil && namespace != "default" {
		clusterID, status, needsProvisioning, err := h.clusterProvisioner.CheckNamespaceCluster(ctx, namespace)
		if err != nil {
			// Log but don't fail - cluster provisioning is optional
			_ = err
		} else if needsProvisioning {
			// Trigger provisioning for new namespace
			nsID, _ := h.resolveNamespace(ctx, namespace)
			nsIDInt := 0
			if id, ok := nsID.(int); ok {
				nsIDInt = id
			} else if id, ok := nsID.(int64); ok {
				nsIDInt = int(id)
			} else if id, ok := nsID.(float64); ok {
				nsIDInt = int(id)
			}

			newClusterID, pollURL, provErr := h.clusterProvisioner.ProvisionNamespaceCluster(ctx, nsIDInt, namespace, req.Wallet)
			if provErr != nil {
				writeError(w, http.StatusInternalServerError, "failed to start cluster provisioning")
				return
			}

			writeJSON(w, http.StatusAccepted, map[string]any{
				"status":                 "provisioning",
				"cluster_id":             newClusterID,
				"poll_url":               pollURL,
				"estimated_time_seconds": 60,
				"message":                "Namespace cluster is being provisioned. Poll the status URL for updates.",
			})
			return
		} else if status == "provisioning" {
			// Already provisioning, return poll URL
			writeJSON(w, http.StatusAccepted, map[string]any{
				"status":                 "provisioning",
				"cluster_id":             clusterID,
				"poll_url":               "/v1/namespace/status?id=" + clusterID,
				"estimated_time_seconds": 60,
				"message":                "Namespace cluster is being provisioned. Poll the status URL for updates.",
			})
			return
		}
		// If status is "ready" or "default", proceed with API key generation
	}

	apiKey, err := h.authService.GetOrCreateAPIKey(ctx, req.Wallet, req.Namespace)
	if err != nil {
		writeError(w, http.StatusInternalServerError, err.Error())
		return
	}

	writeJSON(w, http.StatusOK, map[string]any{
		"api_key":   apiKey,
		"namespace": req.Namespace,
		"wallet":    strings.ToLower(strings.TrimPrefix(strings.TrimPrefix(req.Wallet, "0x"), "0X")),
		"created":   time.Now().Format(time.RFC3339),
	})
}
