package handlers

import (
	"net/http"
	"os"
	"path/filepath"

	"github.com/Fimeg/RedFlag/aggregator-server/internal/database/queries"
	"github.com/Fimeg/RedFlag/aggregator-server/internal/services"
	"github.com/gin-gonic/gin"
)

// AgentBuildHandler handles agent build operations
type AgentBuildHandler struct {
	agentQueries *queries.AgentQueries
}

// NewAgentBuildHandler creates a new agent build handler
func NewAgentBuildHandler(agentQueries *queries.AgentQueries) *AgentBuildHandler {
	return &AgentBuildHandler{
		agentQueries: agentQueries,
	}
}

// BuildAgent handles the agent build endpoint
// Deprecated: Use AgentHandler.Rebuild instead
func (h *AgentBuildHandler) BuildAgent(c *gin.Context) {
	var req services.AgentSetupRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Create config builder with database access
	configBuilder := services.NewConfigBuilder(req.ServerURL, h.agentQueries.DB)

	// Build agent configuration
	config, err := configBuilder.BuildAgentConfig(req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Create agent builder
	agentBuilder := services.NewAgentBuilder()

	// Generate build artifacts
	buildResult, err := agentBuilder.BuildAgentWithConfig(config)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Create response with native binary instructions
	response := gin.H{
		"agent_id":       config.AgentID,
		"config_file":    buildResult.ConfigFile,
		"platform":       buildResult.Platform,
		"config_version": config.ConfigVersion,
		"agent_version":  config.AgentVersion,
		"build_time":     buildResult.BuildTime,
		"next_steps": []string{
			"1. Download native binary from server",
			"2. Place binary in /usr/local/bin/redflag-agent",
			"3. Set permissions: chmod 755 /usr/local/bin/redflag-agent",
			"4. Create config directory: mkdir -p /etc/redflag",
			"5. Save config to /etc/redflag/config.json",
			"6. Set config permissions: chmod 600 /etc/redflag/config.json",
			"7. Start service: systemctl enable --now redflag-agent",
		},
		"configuration": config.PublicConfig,
	}

	c.JSON(http.StatusOK, response)
}

// GetBuildInstructions returns build instructions for manual setup
func (h *AgentBuildHandler) GetBuildInstructions(c *gin.Context) {
	agentID := c.Param("agentID")
	if agentID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "agent ID is required"})
		return
	}

	instructions := gin.H{
		"title":    "RedFlag Agent Build Instructions",
		"agent_id": agentID,
		"steps": []gin.H{
			{
				"step": 1,
				"title": "Prepare Build Environment",
				"commands": []string{
					"mkdir -p redflag-build",
					"cd redflag-build",
				},
			},
			{
				"step": 2,
				"title": "Copy Agent Source Code",
				"commands": []string{
					"cp -r ../aggregator-agent/* .",
					"ls -la",
				},
			},
			{
				"step": 3,
				"title": "Build Docker Image",
				"commands": []string{
					"docker build -t redflag-agent:" + agentID[:8] + " .",
				},
			},
			{
				"step": 4,
				"title": "Create Docker Network",
				"commands": []string{
					"docker network create redflag 2>/dev/null || true",
				},
			},
			{
				"step": 5,
				"title": "Deploy Agent",
				"commands": []string{
					"docker compose up -d",
				},
			},
			{
				"step": 6,
				"title": "Verify Deployment",
				"commands": []string{
					"docker compose logs -f",
					"docker ps",
				},
			},
		},
		"troubleshooting": []gin.H{
			{
				"issue": "Build fails with 'go mod download' errors",
				"solution": "Ensure go.mod and go.sum are copied correctly and internet connectivity is available",
			},
			{
				"issue": "Container fails to start",
				"solution": "Check docker-compose.yml and ensure Docker secrets are created with 'echo \"secret-value\" | docker secret create secret-name -'",
			},
			{
				"issue": "Agent cannot connect to server",
				"solution": "Verify server URL is accessible from container and firewall rules allow traffic",
			},
		},
	}

	c.JSON(http.StatusOK, instructions)
}

// DownloadBuildArtifacts provides download links for generated files
func (h *AgentBuildHandler) DownloadBuildArtifacts(c *gin.Context) {
	agentID := c.Param("agentID")
	fileType := c.Param("fileType")
	buildDir := c.Query("buildDir")

	// Validate agent ID parameter
	if agentID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "agent ID is required"})
		return
	}

	if buildDir == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "build directory is required"})
		return
	}

	// Security check: ensure the buildDir is within expected path
	absBuildDir, err := filepath.Abs(buildDir)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid build directory"})
		return
	}

	// Construct file path based on type
	var filePath string
	switch fileType {
	case "compose":
		filePath = filepath.Join(absBuildDir, "docker-compose.yml")
	case "dockerfile":
		filePath = filepath.Join(absBuildDir, "Dockerfile")
	case "config":
		filePath = filepath.Join(absBuildDir, "pkg", "embedded", "config.go")
	default:
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file type"})
		return
	}

	// Check if file exists
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
		return
	}

	// Serve file for download
	c.FileAttachment(filePath, filepath.Base(filePath))
}
