package handlers

import (
	"database/sql"
	"net/http"

	"github.com/gin-gonic/gin"

	"switchboard-core/models"
)

// ── Team-Scoped Workflow Wrappers (v0.31.2) ────────────────
//
// Thin wrappers that enforce team ownership before delegating
// to the existing WorkflowHandler methods.  Follows the same
// pattern as CreateTeamTask / ListTeamTasks.

// requireTeamWorkflow loads the workflow by :id and verifies
// its team_id matches :teamId.  Returns false (and writes an
// HTTP error) if the check fails; true if the caller may proceed.
func (h *WorkflowHandler) requireTeamWorkflow(c *gin.Context) bool {
	teamID := c.Param("teamId")
	wfID := c.Param("id")
	w, err := h.stores.Workflows.GetByID(c.Request.Context(), wfID)
	if err != nil {
		if err == sql.ErrNoRows {
			c.JSON(http.StatusNotFound, gin.H{"error": "workflow not found"})
		} else {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load workflow"})
		}
		return false
	}
	if w.TeamID == nil || *w.TeamID != teamID {
		c.JSON(http.StatusForbidden, gin.H{"error": "workflow does not belong to this team"})
		return false
	}
	return true
}

// ── Adopt Global Workflow ────────────────────

// AdoptTeamWorkflow claims a global (team_id=NULL) workflow for this team.
// POST /api/v1/teams/:teamId/workflows/:id/adopt
func (h *WorkflowHandler) AdoptTeamWorkflow(c *gin.Context) {
	teamID := c.Param("teamId")
	wfID := c.Param("id")

	w, err := h.stores.Workflows.GetByID(c.Request.Context(), wfID)
	if err != nil {
		if err == sql.ErrNoRows {
			c.JSON(http.StatusNotFound, gin.H{"error": "workflow not found"})
		} else {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load workflow"})
		}
		return
	}
	if w.TeamID != nil {
		c.JSON(http.StatusConflict, gin.H{"error": "workflow already belongs to a team"})
		return
	}

	patch := models.WorkflowPatch{TeamID: &teamID}
	if err := h.stores.Workflows.Update(c.Request.Context(), wfID, patch); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to adopt workflow"})
		return
	}

	// Return the updated workflow
	c.Set("id", wfID)
	h.Get(c)
}

// ListGlobalWorkflows returns unowned workflows available for adoption.
// GET /api/v1/teams/:teamId/workflows/available
func (h *WorkflowHandler) ListGlobalWorkflows(c *gin.Context) {
	result, err := h.stores.Workflows.ListGlobal(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list workflows"})
		return
	}
	if result == nil {
		result = []models.Workflow{}
	}
	c.JSON(http.StatusOK, gin.H{"data": result})
}

// ── Workflow CRUD ───────────────────────────

// ListTeamWorkflows returns workflows owned by the team.
// GET /api/v1/teams/:teamId/workflows
func (h *WorkflowHandler) ListTeamWorkflows(c *gin.Context) {
	teamID := c.Param("teamId")
	result, err := h.stores.Workflows.ListForTeam(c.Request.Context(), teamID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list workflows"})
		return
	}
	if result == nil {
		result = []models.Workflow{}
	}
	c.JSON(http.StatusOK, gin.H{"data": result})
}

// CreateTeamWorkflow creates a workflow scoped to the team.
// POST /api/v1/teams/:teamId/workflows
func (h *WorkflowHandler) CreateTeamWorkflow(c *gin.Context) {
	teamID := c.Param("teamId")
	c.Set("force_team_id", teamID)
	h.Create(c)
}

// GetTeamWorkflow returns a team workflow with stages.
// GET /api/v1/teams/:teamId/workflows/:id
func (h *WorkflowHandler) GetTeamWorkflow(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.Get(c)
}

// UpdateTeamWorkflow patches a team workflow.
// PATCH /api/v1/teams/:teamId/workflows/:id
func (h *WorkflowHandler) UpdateTeamWorkflow(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.Update(c)
}

// DeleteTeamWorkflow deletes a team workflow.
// DELETE /api/v1/teams/:teamId/workflows/:id
func (h *WorkflowHandler) DeleteTeamWorkflow(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.Delete(c)
}

// ── Stage CRUD ──────────────────────────────

// ListTeamWorkflowStages returns stages for a team workflow.
// GET /api/v1/teams/:teamId/workflows/:id/stages
func (h *WorkflowHandler) ListTeamWorkflowStages(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.ListStages(c)
}

// CreateTeamWorkflowStage adds a stage to a team workflow.
// POST /api/v1/teams/:teamId/workflows/:id/stages
func (h *WorkflowHandler) CreateTeamWorkflowStage(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.CreateStage(c)
}

// UpdateTeamWorkflowStage updates a stage on a team workflow.
// PUT /api/v1/teams/:teamId/workflows/:id/stages/:sid
func (h *WorkflowHandler) UpdateTeamWorkflowStage(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.UpdateStage(c)
}

// DeleteTeamWorkflowStage removes a stage from a team workflow.
// DELETE /api/v1/teams/:teamId/workflows/:id/stages/:sid
func (h *WorkflowHandler) DeleteTeamWorkflowStage(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.DeleteStage(c)
}

// ReorderTeamWorkflowStages reorders stages on a team workflow.
// PATCH /api/v1/teams/:teamId/workflows/:id/stages/reorder
func (h *WorkflowHandler) ReorderTeamWorkflowStages(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.ReorderStages(c)
}

// ── Publish / Version ───────────────────────

// PublishTeamWorkflow publishes a team workflow version.
// POST /api/v1/teams/:teamId/workflows/:id/publish
func (h *WorkflowHandler) PublishTeamWorkflow(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.Publish(c)
}

// GetTeamWorkflowVersion returns a version snapshot for a team workflow.
// GET /api/v1/teams/:teamId/workflows/:id/versions/:version
func (h *WorkflowHandler) GetTeamWorkflowVersion(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	h.GetVersion(c)
}

// CloneTeamWorkflow deep-copies a team workflow.
// POST /api/v1/teams/:teamId/workflows/:id/clone
func (h *WorkflowHandler) CloneTeamWorkflow(c *gin.Context) {
	if !h.requireTeamWorkflow(c) {
		return
	}
	c.Set("force_team_id", c.Param("teamId"))
	h.Clone(c)
}
