package rest

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/nexuscrm/backend/internal/application/services"
	appErrors "github.com/nexuscrm/backend/pkg/errors"
	"github.com/nexuscrm/shared/pkg/models"
)

type ActionHandler struct {
	svc *services.ServiceManager
}

func NewActionHandler(svc *services.ServiceManager) *ActionHandler {
	return &ActionHandler{svc: svc}
}

// CreateAction handles POST /services/data/v63.0/tooling/sobjects/QuickActionDefinition
// Supports both internal format and Salesforce Tooling API format:
//
//	Salesforce Tooling API format:
//	{
//	  "DeveloperName": "MyQuickAction",
//	  "MasterLabel": "My Quick Action",
//	  "SobjectType": "Global" or "Account",
//	  "TargetSobjectType": "Task",
//	  "Type": "Create",
//	  "Description": "..."
//	}
func (h *ActionHandler) CreateAction(c *gin.Context) {
	MustGetUser(c)

	// Try to parse as Salesforce Tooling API format first
	var toolingReq struct {
		DeveloperName     string `json:"DeveloperName"`
		MasterLabel       string `json:"MasterLabel"`
		SobjectType       string `json:"SobjectType"`
		TargetSobjectType string `json:"TargetSobjectType"`
		Type              string `json:"Type"`
		Description       string `json:"Description"`
	}

	// Read raw JSON to determine format
	var rawJSON map[string]interface{}
	if !BindJSON(c, &rawJSON) {
		return
	}

	// Check if it's Salesforce Tooling API format
	var action models.ActionMetadata
	if _, hasDeveloperName := rawJSON["DeveloperName"]; hasDeveloperName {
		// Salesforce Tooling API format
		toolingReq.DeveloperName, _ = rawJSON["DeveloperName"].(string)
		toolingReq.MasterLabel, _ = rawJSON["MasterLabel"].(string)
		toolingReq.SobjectType, _ = rawJSON["SobjectType"].(string)
		toolingReq.TargetSobjectType, _ = rawJSON["TargetSobjectType"].(string)
		toolingReq.Type, _ = rawJSON["Type"].(string)
		toolingReq.Description, _ = rawJSON["Description"].(string)

		// Validate required fields
		if toolingReq.DeveloperName == "" {
			RespondAppError(c, appErrors.NewValidationError("DeveloperName", "DeveloperName is required"))
			return
		}
		if toolingReq.MasterLabel == "" {
			RespondAppError(c, appErrors.NewValidationError("MasterLabel", "MasterLabel is required"))
			return
		}
		if toolingReq.Type == "" {
			RespondAppError(c, appErrors.NewValidationError("Type", "Type is required"))
			return
		}

		// Map Salesforce Tooling API format to internal ActionMetadata
		action = models.ActionMetadata{
			Name:         toolingReq.DeveloperName,
			Label:        toolingReq.MasterLabel,
			Type:         toolingReq.Type,
			TargetObject: &toolingReq.TargetSobjectType,
		}

		// Set ObjectAPIName based on SobjectType
		if toolingReq.SobjectType != "" && toolingReq.SobjectType != "Global" {
			action.ObjectAPIName = toolingReq.SobjectType
		}
	} else {
		// Internal format
		// Convert map back to JSON and bind to ActionMetadata
		action = models.ActionMetadata{
			ID:            getStringField(rawJSON, "id"),
			ObjectAPIName: getStringField(rawJSON, "objectApiName"),
			Name:          getStringField(rawJSON, "name"),
			Label:         getStringField(rawJSON, "label"),
			Type:          getStringField(rawJSON, "type"),
			Icon:          getStringField(rawJSON, "icon"),
		}

		if targetObj, ok := rawJSON["targetObject"].(string); ok {
			action.TargetObject = &targetObj
		}
		if config, ok := rawJSON["config"].(map[string]interface{}); ok {
			action.Config = config
		}
	}

	if err := h.svc.Metadata.CreateAction(c.Request.Context(), &action); err != nil {
		RespondAppError(c, err)
		return
	}

	// Salesforce Tooling API response format for created records
	c.JSON(http.StatusCreated, gin.H{
		"id":      action.ID,
		"success": true,
		"errors":  []interface{}{},
	})
}

// getStringField extracts a string field from a map, returning empty string if not found or not a string
func getStringField(m map[string]interface{}, key string) string {
	if v, ok := m[key].(string); ok {
		return v
	}
	return ""
}
