package mcp

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/mark3labs/mcp-go/mcp"
)

// registerResourceTemplates registers all MCP resource templates
func (s *ServerV2) registerResourceTemplates() error {
	// Register worktree detail template
	worktreeDetailTemplate := mcp.NewResourceTemplate(
		"amux://worktree/{id}",
		"Worktree Details",
		mcp.WithTemplateDescription("Get details of a specific worktree by branch name"),
		mcp.WithTemplateMIMEType("application/json"),
	)
	s.mcpServer.AddResourceTemplate(worktreeDetailTemplate, s.handleWorktreeDetailResource)

	// Register worktree files template
	worktreeFilesTemplate := mcp.NewResourceTemplate(
		"amux://worktree/{id}/files{/path*}",
		"Worktree Files",
		mcp.WithTemplateDescription("Browse files in a worktree"),
		mcp.WithTemplateMIMEType("application/json"),
	)
	s.mcpServer.AddResourceTemplate(worktreeFilesTemplate, s.handleWorktreeFilesResource)

	return nil
}

// workspacePaths contains the actual filesystem paths for a worktree
type workspacePaths struct {
	Worktree string `json:"worktree"`
}

// workspaceResources contains the MCP resource URIs for a worktree
type workspaceResources struct {
	Files string `json:"files"`
}

// workspaceDetail is the common structure for detailed worktree information
type workspaceDetail struct {
	ID          string             `json:"id"`
	Index       string             `json:"index"`
	Name        string             `json:"name"`
	Branch      string             `json:"branch"`
	BaseBranch  string             `json:"baseBranch"`
	Path        string             `json:"path"`
	Description string             `json:"description,omitempty"`
	CreatedAt   string             `json:"createdAt"`
	UpdatedAt   string             `json:"updatedAt"`
	Paths       workspacePaths     `json:"paths"`
	Resources   workspaceResources `json:"resources"`
}

// parseWorktreeURI extracts the worktree ID from a URI like amux://worktree/{id}
func parseWorktreeURI(uri string) (string, string, error) {
	// Remove the scheme
	path := strings.TrimPrefix(uri, "amux://")

	// Check if it starts with worktree/
	if !strings.HasPrefix(path, "worktree/") {
		return "", "", fmt.Errorf("invalid worktree URI: %s", uri)
	}

	// Remove the worktree/ prefix
	path = strings.TrimPrefix(path, "worktree/")

	// Find the end of the worktree ID (branch name)
	// Branch names contain "/" so we need to handle special paths like /files, /context
	var workspaceID string
	var remainingPath string

	// Check for known resource paths
	if idx := strings.Index(path, "/files"); idx != -1 {
		workspaceID = path[:idx]
		remainingPath = path[idx+1:]
	} else {
		// No special path, entire thing is the worktree ID
		workspaceID = path
		remainingPath = ""
	}

	if workspaceID == "" {
		return "", "", fmt.Errorf("invalid worktree URI: missing worktree ID")
	}

	return workspaceID, remainingPath, nil
}

// handleWorktreeDetailResource returns details for a specific worktree
func (s *ServerV2) handleWorktreeDetailResource(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
	workspaceID, _, err := parseWorktreeURI(request.Params.URI)
	if err != nil {
		return nil, err
	}

	detail, err := s.getWorktreeDetail(ctx, workspaceID)
	if err != nil {
		return nil, err
	}

	jsonData, err := json.MarshalIndent(detail, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("failed to marshal workspace detail: %w", err)
	}

	return []mcp.ResourceContents{
		&mcp.TextResourceContents{
			URI:      request.Params.URI,
			MIMEType: "application/json",
			Text:     string(jsonData),
		},
	}, nil
}

// handleWorktreeFilesResource lists files in a worktree directory
func (s *ServerV2) handleWorktreeFilesResource(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
	workspaceID, subPath, err := parseWorktreeURI(request.Params.URI)
	if err != nil {
		return nil, err
	}

	// Remove "files" prefix if present
	if subPath == "files" {
		subPath = ""
	} else {
		subPath = strings.TrimPrefix(subPath, "files/")
	}

	ws, err := s.worktreeManager.Get(ctx, workspaceID)
	if err != nil {
		return nil, fmt.Errorf("failed to get workspace: %w", err)
	}

	// Construct the full path
	fullPath := ws.Path
	if subPath != "" {
		fullPath = filepath.Join(ws.Path, subPath)
	}

	// Security check: ensure path is within workspace
	if !strings.HasPrefix(fullPath, ws.Path) {
		return nil, fmt.Errorf("access denied: path outside workspace")
	}

	// Check if path exists and is a directory
	info, err := os.Stat(fullPath)
	if err != nil {
		return nil, fmt.Errorf("failed to stat path: %w", err)
	}

	if !info.IsDir() {
		// If it's a file, return its contents
		content, err := os.ReadFile(fullPath)
		if err != nil {
			return nil, fmt.Errorf("failed to read file: %w", err)
		}

		// Determine MIME type (simplified)
		mimeType := "text/plain"
		if strings.HasSuffix(fullPath, ".json") {
			mimeType = "application/json"
		} else if strings.HasSuffix(fullPath, ".md") {
			mimeType = "text/markdown"
		} else if strings.HasSuffix(fullPath, ".go") {
			mimeType = "text/x-go"
		}

		return []mcp.ResourceContents{
			&mcp.TextResourceContents{
				URI:      request.Params.URI,
				MIMEType: mimeType,
				Text:     string(content),
			},
		}, nil
	}

	// List directory contents
	entries, err := os.ReadDir(fullPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read directory: %w", err)
	}

	type fileInfo struct {
		Name string `json:"name"`
		Type string `json:"type"`
		Size int64  `json:"size"`
	}

	files := make([]fileInfo, 0, len(entries))
	for _, entry := range entries {
		// Skip hidden files
		if strings.HasPrefix(entry.Name(), ".") {
			continue
		}

		info, err := entry.Info()
		if err != nil {
			continue
		}

		fileType := "file"
		if entry.IsDir() {
			fileType = "directory"
		}

		files = append(files, fileInfo{
			Name: entry.Name(),
			Type: fileType,
			Size: info.Size(),
		})
	}

	jsonData, err := json.MarshalIndent(files, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("failed to marshal file list: %w", err)
	}

	return []mcp.ResourceContents{
		&mcp.TextResourceContents{
			URI:      request.Params.URI,
			MIMEType: "application/json",
			Text:     string(jsonData),
		},
	}, nil
}
