package main

import (
	"context"
	"log"
	"os"

	"director/api/db"
	"director/api/handlers"
	"director/api/pubsub"
	"director/api/ws"

	"github.com/gin-gonic/gin"
)

func main() {
	dsn := os.Getenv("DATABASE_URL")
	if dsn == "" {
		dsn = "postgres://director:director_local_2026@127.0.0.1:5432/director?sslmode=disable"
	}

	redisAddr := os.Getenv("REDIS_URL")
	if redisAddr == "" {
		redisAddr = "127.0.0.1:6379"
	}

	database, err := db.Connect(dsn)
	if err != nil {
		log.Fatalf("database connection failed: %v", err)
	}
	defer database.Close()

	hub := ws.NewHub()
	go hub.Run()

	// Redis pub/sub — bridges external events (OpenClaw agents) to WebSocket clients
	ps := pubsub.New(redisAddr, hub)
	if err := ps.Ping(context.Background()); err != nil {
		log.Fatalf("redis connection failed: %v", err)
	}
	defer ps.Close()
	go ps.Subscribe(context.Background())

	r := gin.Default()

	// CORS for local dev
	r.Use(func(c *gin.Context) {
		c.Header("Access-Control-Allow-Origin", "*")
		c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
		c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
			return
		}
		c.Next()
	})

	api := r.Group("/api")
	{
		h := handlers.New(database, ps)

		// Plans
		api.GET("/plans", h.ListPlans)
		api.POST("/plans", h.CreatePlan)
		api.GET("/plans/:id", h.GetPlan)
		api.PATCH("/plans/:id", h.UpdatePlan)

		// Tasks
		api.GET("/plans/:id/tasks", h.ListTasks)
		api.POST("/plans/:id/tasks", h.CreateTask)
		api.PATCH("/tasks/:id", h.UpdateTask)

		// Agents
		api.GET("/agents", h.ListAgents)
		api.PATCH("/agents/:id", h.UpdateAgent)

		// Director Queue
		api.GET("/queue", h.ListQueue)
		api.PATCH("/queue/:id", h.UpdateQueueItem)

		// Pending Questions
		api.GET("/questions", h.ListQuestions)
		api.POST("/questions", h.CreateQuestion)
		api.PATCH("/questions/:id", h.AnswerQuestion)

		// Messages
		api.GET("/plans/:id/messages", h.ListMessages)
		api.POST("/plans/:id/messages", h.CreateMessage)
		api.PATCH("/messages/:id", h.UpdateMessage)

		// System / Settings
		api.GET("/system/claude-mode", h.GetClaudeMode)
		api.POST("/system/claude-mode", h.SetClaudeMode)
	}

	// WebSocket
	r.GET("/ws", func(c *gin.Context) {
		ws.HandleWebSocket(hub, c.Writer, c.Request)
	})

	// Health
	r.GET("/health", func(c *gin.Context) {
		if err := ps.Ping(c.Request.Context()); err != nil {
			c.JSON(500, gin.H{"status": "error", "redis": err.Error()})
			return
		}
		c.JSON(200, gin.H{"status": "ok"})
	})

	port := os.Getenv("PORT")
	if port == "" {
		port = "8090"
	}

	log.Printf("Director API starting on :%s", port)
	if err := r.Run(":" + port); err != nil {
		log.Fatalf("server failed: %v", err)
	}
}
