package workspace

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"chorus.services/bzzz/pkg/config"
)

// HCFSWorkspaceManager manages agent workspaces using HCFS as the backing store
type HCFSWorkspaceManager struct {
	hcfsAPIURL    string
	mountPath     string
	client        *http.Client
	activeSpaces  map[string]*HCFSWorkspace
}

// HCFSWorkspace represents an HCFS-backed workspace for an agent
type HCFSWorkspace struct {
	ID          string `json:"id"`
	AgentID     string `json:"agent_id"`
	TaskID      string `json:"task_id"`
	HCFSPath    string `json:"hcfs_path"`
	LocalMount  string `json:"local_mount"`
	CreatedAt   time.Time `json:"created_at"`
	LastUsed    time.Time `json:"last_used"`
}

// HCFSContextRequest represents a request to create context in HCFS
type HCFSContextRequest struct {
	Path     string                 `json:"path"`
	Content  string                 `json:"content"`
	Summary  string                 `json:"summary"`
	Metadata map[string]interface{} `json:"metadata"`
}

// HCFSContextResponse represents the response from HCFS context creation
type HCFSContextResponse struct {
	ID        string                 `json:"id"`
	Path      string                 `json:"path"`
	CreatedAt string                 `json:"created_at"`
	Metadata  map[string]interface{} `json:"metadata"`
}

// NewHCFSWorkspaceManager creates a new HCFS workspace manager
func NewHCFSWorkspaceManager(hcfsAPIURL string, mountPath string) *HCFSWorkspaceManager {
	return &HCFSWorkspaceManager{
		hcfsAPIURL:   hcfsAPIURL,
		mountPath:    mountPath,
		client:       &http.Client{Timeout: 30 * time.Second},
		activeSpaces: make(map[string]*HCFSWorkspace),
	}
}

// CreateWorkspace creates a new HCFS-backed workspace for an agent
func (m *HCFSWorkspaceManager) CreateWorkspace(ctx context.Context, agentID, taskID string, agentConfig *config.AgentConfig) (*HCFSWorkspace, error) {
	// Generate unique workspace ID
	workspaceID := fmt.Sprintf("bzzz-workspace-%s-%d", agentID, time.Now().Unix())
	
	// Create HCFS path for the workspace
	hcfsPath := fmt.Sprintf("/agents/%s/workspaces/%s", agentID, workspaceID)
	
	// Create workspace context in HCFS
	contextReq := HCFSContextRequest{
		Path:    hcfsPath,
		Content: fmt.Sprintf("Workspace for agent %s, task %s", agentID, taskID),
		Summary: fmt.Sprintf("Agent workspace: %s", workspaceID),
		Metadata: map[string]interface{}{
			"agent_id":     agentID,
			"task_id":      taskID,
			"workspace_id": workspaceID,
			"created_by":   "bzzz_sandbox",
			"workspace_type": "agent_sandbox",
		},
	}
	
	contextID, err := m.createHCFSContext(ctx, contextReq)
	if err != nil {
		return nil, fmt.Errorf("failed to create HCFS context: %w", err)
	}
	
	// Create local mount point using HCFS FUSE
	localMount := filepath.Join(m.mountPath, workspaceID)
	if err := m.createHCFSMount(ctx, hcfsPath, localMount); err != nil {
		return nil, fmt.Errorf("failed to create HCFS mount: %w", err)
	}
	
	workspace := &HCFSWorkspace{
		ID:         contextID,
		AgentID:    agentID,
		TaskID:     taskID,
		HCFSPath:   hcfsPath,
		LocalMount: localMount,
		CreatedAt:  time.Now(),
		LastUsed:   time.Now(),
	}
	
	// Track active workspace
	m.activeSpaces[workspaceID] = workspace
	
	fmt.Printf("✅ HCFS workspace created: %s -> %s\n", hcfsPath, localMount)
	return workspace, nil
}

// DestroyWorkspace cleans up an HCFS workspace
func (m *HCFSWorkspaceManager) DestroyWorkspace(ctx context.Context, workspace *HCFSWorkspace) error {
	if workspace == nil {
		return nil
	}
	
	// Unmount HCFS FUSE mount
	if err := m.unmountHCFS(workspace.LocalMount); err != nil {
		fmt.Printf("⚠️ Warning: failed to unmount HCFS: %v\n", err)
	}
	
	// Update HCFS context with final state
	if err := m.finalizeWorkspaceContext(ctx, workspace); err != nil {
		fmt.Printf("⚠️ Warning: failed to finalize workspace context: %v\n", err)
	}
	
	// Remove from active workspaces
	delete(m.activeSpaces, workspace.ID)
	
	fmt.Printf("✅ HCFS workspace destroyed: %s\n", workspace.HCFSPath)
	return nil
}

// GetWorkspacePath returns the local path for container mounting
func (m *HCFSWorkspaceManager) GetWorkspacePath(workspace *HCFSWorkspace) string {
	if workspace == nil {
		return ""
	}
	return workspace.LocalMount
}

// UpdateWorkspaceUsage updates the last used timestamp
func (m *HCFSWorkspaceManager) UpdateWorkspaceUsage(workspace *HCFSWorkspace) {
	if workspace != nil {
		workspace.LastUsed = time.Now()
	}
}

// StoreWorkspaceArtifacts stores final workspace artifacts in HCFS
func (m *HCFSWorkspaceManager) StoreWorkspaceArtifacts(ctx context.Context, workspace *HCFSWorkspace, artifacts map[string]string) error {
	if workspace == nil {
		return fmt.Errorf("workspace is nil")
	}
	
	// Store each artifact as a separate context in HCFS
	for artifactName, content := range artifacts {
		artifactPath := fmt.Sprintf("%s/artifacts/%s", workspace.HCFSPath, artifactName)
		
		artifactReq := HCFSContextRequest{
			Path:    artifactPath,
			Content: content,
			Summary: fmt.Sprintf("Artifact from workspace %s: %s", workspace.ID, artifactName),
			Metadata: map[string]interface{}{
				"workspace_id":   workspace.ID,
				"agent_id":       workspace.AgentID,
				"task_id":        workspace.TaskID,
				"artifact_name":  artifactName,
				"artifact_type":  "workspace_output",
				"created_by":     "bzzz_sandbox",
			},
		}
		
		_, err := m.createHCFSContext(ctx, artifactReq)
		if err != nil {
			return fmt.Errorf("failed to store artifact %s: %w", artifactName, err)
		}
	}
	
	return nil
}

// createHCFSContext creates a new context in HCFS
func (m *HCFSWorkspaceManager) createHCFSContext(ctx context.Context, req HCFSContextRequest) (string, error) {
	reqBody, err := json.Marshal(req)
	if err != nil {
		return "", fmt.Errorf("failed to marshal request: %w", err)
	}
	
	httpReq, err := http.NewRequestWithContext(ctx, "POST", m.hcfsAPIURL+"/contexts", strings.NewReader(string(reqBody)))
	if err != nil {
		return "", fmt.Errorf("failed to create request: %w", err)
	}
	
	httpReq.Header.Set("Content-Type", "application/json")
	
	resp, err := m.client.Do(httpReq)
	if err != nil {
		return "", fmt.Errorf("failed to make request: %w", err)
	}
	defer resp.Body.Close()
	
	if resp.StatusCode != http.StatusCreated {
		body, _ := io.ReadAll(resp.Body)
		return "", fmt.Errorf("HCFS API returned status %d: %s", resp.StatusCode, string(body))
	}
	
	var contextResp HCFSContextResponse
	if err := json.NewDecoder(resp.Body).Decode(&contextResp); err != nil {
		return "", fmt.Errorf("failed to decode response: %w", err)
	}
	
	return contextResp.ID, nil
}

// createHCFSMount creates a FUSE mount for the HCFS path
func (m *HCFSWorkspaceManager) createHCFSMount(ctx context.Context, hcfsPath, localPath string) error {
	// Ensure the mount directory exists
	if err := os.MkdirAll(localPath, 0755); err != nil {
		return fmt.Errorf("failed to create mount directory: %w", err)
	}
	
	// TODO: Implement HCFS FUSE mount
	// For now, we'll create a placeholder directory structure
	// In a full implementation, this would mount the HCFS path using FUSE
	fmt.Printf("🔗 Creating HCFS FUSE mount: %s -> %s\n", hcfsPath, localPath)
	
	// Create basic workspace structure
	subdirs := []string{"src", "build", "output", "logs"}
	for _, subdir := range subdirs {
		if err := os.MkdirAll(filepath.Join(localPath, subdir), 0755); err != nil {
			return fmt.Errorf("failed to create workspace subdir %s: %w", subdir, err)
		}
	}
	
	return nil
}

// unmountHCFS unmounts the HCFS FUSE mount
func (m *HCFSWorkspaceManager) unmountHCFS(localPath string) error {
	// TODO: Implement HCFS FUSE unmount
	// For now, we'll just remove the directory
	fmt.Printf("🔌 Unmounting HCFS: %s\n", localPath)
	
	return os.RemoveAll(localPath)
}

// finalizeWorkspaceContext updates the workspace context with final metadata
func (m *HCFSWorkspaceManager) finalizeWorkspaceContext(ctx context.Context, workspace *HCFSWorkspace) error {
	// Update workspace context with completion metadata
	finalReq := HCFSContextRequest{
		Path:    workspace.HCFSPath + "/completion",
		Content: fmt.Sprintf("Workspace %s completed at %s", workspace.ID, time.Now().Format(time.RFC3339)),
		Summary: fmt.Sprintf("Completion record for workspace %s", workspace.ID),
		Metadata: map[string]interface{}{
			"workspace_id":   workspace.ID,
			"agent_id":       workspace.AgentID,
			"task_id":        workspace.TaskID,
			"completed_at":   time.Now().Format(time.RFC3339),
			"total_duration": time.Since(workspace.CreatedAt).Seconds(),
			"record_type":    "workspace_completion",
		},
	}
	
	_, err := m.createHCFSContext(ctx, finalReq)
	return err
}

// GetActiveWorkspaces returns all currently active workspaces
func (m *HCFSWorkspaceManager) GetActiveWorkspaces() map[string]*HCFSWorkspace {
	return m.activeSpaces
}

// CleanupIdleWorkspaces removes workspaces that haven't been used recently
func (m *HCFSWorkspaceManager) CleanupIdleWorkspaces(ctx context.Context, maxIdleTime time.Duration) error {
	now := time.Now()
	var toCleanup []*HCFSWorkspace
	
	for _, workspace := range m.activeSpaces {
		if now.Sub(workspace.LastUsed) > maxIdleTime {
			toCleanup = append(toCleanup, workspace)
		}
	}
	
	for _, workspace := range toCleanup {
		if err := m.DestroyWorkspace(ctx, workspace); err != nil {
			fmt.Printf("⚠️ Failed to cleanup idle workspace %s: %v\n", workspace.ID, err)
		}
	}
	
	return nil
}