package api

import (
	"fmt"
	"log"
	"net/http"
	"strings"

	"go.temporal.io/sdk/client"

	"github.com/rockliang/poimen/workflows/pkg/db"
)

// Server handles HTTP routing for workflow APIs
type Server struct {
	api    *WorkflowAPI
	logger *log.Logger
}

// NewServer creates new HTTP server with database connection
func NewServer(database *db.DB, temporalClient client.Client, logger *log.Logger) *Server {
	return &Server{
		api:    NewWorkflowAPI(database, temporalClient, logger),
		logger: logger,
	}
}

// ServeHTTP dispatches HTTP requests to appropriate handler
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Enable CORS
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")

	if r.Method == http.MethodOptions {
		w.WriteHeader(http.StatusOK)
		return
	}

	path := r.URL.Path
	method := r.Method

	s.logger.Printf("%s %s", method, path)

	// Route requests
	switch {
	// Workflow endpoints
	case path == "/workflows" && method == http.MethodPost:
		s.api.CreateWorkflow(w, r)
	case path == "/workflows" && method == http.MethodGet:
		s.api.ListWorkflows(w, r)
	case strings.HasPrefix(path, "/workflows/") && method == http.MethodGet:
		id := strings.TrimPrefix(path, "/workflows/")
		// Exclude special paths
		if !strings.Contains(id, "/") {
			s.api.GetWorkflow(w, r, id)
		} else if strings.HasSuffix(id, "/executions") {
			// GET /workflows/{id}/executions
			workflowID := strings.TrimSuffix(id, "/executions")
			s.api.ListExecutions(w, r, workflowID)
		}
	case strings.HasPrefix(path, "/workflows/") && method == http.MethodPut:
		id := extractID(path, "/workflows/")
		s.api.UpdateWorkflow(w, r, id)
	case strings.HasPrefix(path, "/workflows/") && method == http.MethodDelete:
		id := extractID(path, "/workflows/")
		s.api.DeleteWorkflow(w, r, id)

	// Execute workflow
	case strings.HasSuffix(path, "/execute") && method == http.MethodPost:
		// POST /workflows/{id}/execute
		parts := strings.Split(path, "/")
		if len(parts) >= 4 && parts[1] == "workflows" && parts[3] == "execute" {
			s.api.ExecuteWorkflow(w, r, parts[2])
		}

	// GraphRAG query endpoint
	case strings.HasSuffix(path, "/query") && method == http.MethodPost:
		// POST /workflows/{id}/query
		parts := strings.Split(path, "/")
		if len(parts) >= 4 && parts[1] == "workflows" && parts[3] == "query" {
			s.api.QueryWorkflowGraph(w, r, parts[2])
		}

	// Relation versions endpoint
	case strings.Contains(path, "/relations/") && strings.Contains(path, "/versions") && method == http.MethodGet:
		// GET /workflows/{id}/relations/{edge_id}/versions
		parts := strings.Split(path, "/")
		if len(parts) >= 6 && parts[1] == "workflows" && parts[3] == "relations" && parts[5] == "versions" {
			s.api.GetWorkflowRelationVersions(w, r, parts[2], parts[4])
		}

	// Execution endpoints
	case strings.HasPrefix(path, "/executions/") && method == http.MethodGet:
		id := extractID(path, "/executions/")
		s.api.GetExecution(w, r, id)

	default:
		http.Error(w, "Not found", http.StatusNotFound)
	}
}

// extractID extracts resource ID from path
func extractID(path, prefix string) string {
	id := strings.TrimPrefix(path, prefix)
	if idx := strings.Index(id, "/"); idx != -1 {
		return id[:idx]
	}
	return id
}

// Start starts the HTTP server
func (s *Server) Start(port int) error {
	addr := fmt.Sprintf(":%d", port)
	s.logger.Printf("Starting API server on %s", addr)
	return http.ListenAndServe(addr, s)
}
