package org

import (
	"net/http"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/api/dto/converter"
)

// List handles GET /api/v1/orgs/:orgId/workspaces.
// It returns all workspaces owned by the specified organization.
func (handler *WorkspaceAccessHandler) List(r api.AuthenticatedRequest) (api.Response, error) {
	orgs, ok := handler.organizationProvider()
	if !ok {
		return api.Response{}, api.NewHTTPError(http.StatusNotFound, "Organization provider not installed")
	}

	organizationID := strings.TrimSpace(r.Gin.Param("orgId"))
	if organizationID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "orgId is required")
	}

	workspaces, err := orgs.ListOrganizationWorkspacesForUser(r.Context(), r.UserID(), organizationID)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToOrgWorkspaceViews(workspaces)), nil
}

// Create handles POST /api/v1/orgs/:orgId/workspaces.
// It creates a workspace owned by the specified organization.
func (handler *WorkspaceAccessHandler) Create(r api.AuthenticatedJSON[dto.OrganizationWorkspaceCreateRequest]) (api.Response, error) {
	orgs, ok := handler.organizationProvider()
	if !ok {
		return api.Response{}, api.NewHTTPError(http.StatusNotFound, "Organization provider not installed")
	}

	organizationID := strings.TrimSpace(r.Gin.Param("orgId"))
	if organizationID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "orgId is required")
	}

	request := r.Body
	name := strings.TrimSpace(request.Name)
	if name == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "name is required")
	}

	workspace, err := orgs.CreateOrganizationWorkspaceForUser(r.Context(), r.UserID(), organizationID, name, strings.TrimSpace(request.Slug))
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToOrgWorkspaceView(workspace)), nil
}

// MemberGrantsList handles GET /api/v1/orgs/:orgId/workspaces/:workspaceId/members.
// It returns the member-level access grants for the specified organization workspace.
func (handler *WorkspaceAccessHandler) MemberGrantsList(r api.AuthenticatedRequest) (api.Response, error) {
	orgs, ok := handler.organizationProvider()
	if !ok {
		return api.Response{}, api.NewHTTPError(http.StatusNotFound, "Organization provider not installed")
	}

	organizationID := strings.TrimSpace(r.Gin.Param("orgId"))
	workspaceID := strings.TrimSpace(r.Gin.Param("workspaceId"))
	if organizationID == "" || workspaceID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "Invalid request")
	}

	grants, err := orgs.ListOrganizationWorkspaceGrantsForUser(r.Context(), r.UserID(), organizationID, workspaceID)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToOrgWorkspaceGrantViews(grants)), nil
}

// MemberGrant handles POST /api/v1/orgs/:orgId/workspaces/:workspaceId/members/:memberId.
// It grants workspace access to the specified organization member.
func (handler *WorkspaceAccessHandler) MemberGrant(r api.AuthenticatedJSON[dto.OrganizationWorkspaceAccessGrantRequest]) (api.Response, error) {
	orgs, ok := handler.organizationProvider()
	if !ok {
		return api.Response{}, api.NewHTTPError(http.StatusNotFound, "Organization provider not installed")
	}

	organizationID := strings.TrimSpace(r.Gin.Param("orgId"))
	workspaceID := strings.TrimSpace(r.Gin.Param("workspaceId"))
	memberID := strings.TrimSpace(r.Gin.Param("memberId"))
	if organizationID == "" || workspaceID == "" || memberID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "Invalid request")
	}

	request := r.Body

	grant, err := orgs.GrantOrganizationMemberWorkspaceAccessForUser(r.Context(), r.UserID(), organizationID, workspaceID, memberID, request.Role)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToOrgWorkspaceGrantView(grant)), nil
}

// MemberGrantDelete handles DELETE /api/v1/orgs/:orgId/workspaces/:workspaceId/members/:memberId.
// It revokes workspace access from the specified organization member.
func (handler *WorkspaceAccessHandler) MemberGrantDelete(r api.AuthenticatedRequest) (api.Response, error) {
	orgs, ok := handler.organizationProvider()
	if !ok {
		return api.Response{}, api.NewHTTPError(http.StatusNotFound, "Organization provider not installed")
	}

	organizationID := strings.TrimSpace(r.Gin.Param("orgId"))
	workspaceID := strings.TrimSpace(r.Gin.Param("workspaceId"))
	memberID := strings.TrimSpace(r.Gin.Param("memberId"))
	if organizationID == "" || workspaceID == "" || memberID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "Invalid request")
	}

	if err := orgs.RevokeOrganizationMemberWorkspaceAccessForUser(r.Context(), r.UserID(), organizationID, workspaceID, memberID); err != nil {
		return api.Response{}, err
	}
	return api.OK(dto.EmptyResponse{}), nil
}

// TeamGrantsList handles GET /api/v1/orgs/:orgId/workspaces/:workspaceId/teams.
// It returns the team-level access grants for the specified organization workspace.
func (handler *WorkspaceAccessHandler) TeamGrantsList(r api.AuthenticatedRequest) (api.Response, error) {
	orgs, ok := handler.organizationProvider()
	if !ok {
		return api.Response{}, api.NewHTTPError(http.StatusNotFound, "Organization provider not installed")
	}

	organizationID := strings.TrimSpace(r.Gin.Param("orgId"))
	workspaceID := strings.TrimSpace(r.Gin.Param("workspaceId"))
	if organizationID == "" || workspaceID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "Invalid request")
	}

	grants, err := orgs.ListOrganizationWorkspaceTeamGrantsForUser(r.Context(), r.UserID(), organizationID, workspaceID)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToOrgWorkspaceTeamGrantViews(grants)), nil
}

// TeamGrantCreate handles POST /api/v1/orgs/:orgId/workspaces/:workspaceId/teams/:teamId.
// It grants workspace access to the specified organization team.
func (handler *WorkspaceAccessHandler) TeamGrantCreate(r api.AuthenticatedJSON[dto.OrganizationWorkspaceAccessGrantRequest]) (api.Response, error) {
	orgs, ok := handler.organizationProvider()
	if !ok {
		return api.Response{}, api.NewHTTPError(http.StatusNotFound, "Organization provider not installed")
	}

	organizationID := strings.TrimSpace(r.Gin.Param("orgId"))
	workspaceID := strings.TrimSpace(r.Gin.Param("workspaceId"))
	teamID := strings.TrimSpace(r.Gin.Param("teamId"))
	if organizationID == "" || workspaceID == "" || teamID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "Invalid request")
	}

	request := r.Body

	grant, err := orgs.GrantOrganizationTeamWorkspaceAccessForUser(r.Context(), r.UserID(), organizationID, workspaceID, teamID, request.Role)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToOrgWorkspaceTeamGrantView(grant)), nil
}

// TeamGrantDelete handles DELETE /api/v1/orgs/:orgId/workspaces/:workspaceId/teams/:teamId.
// It revokes workspace access from the specified organization team.
func (handler *WorkspaceAccessHandler) TeamGrantDelete(r api.AuthenticatedRequest) (api.Response, error) {
	orgs, ok := handler.organizationProvider()
	if !ok {
		return api.Response{}, api.NewHTTPError(http.StatusNotFound, "Organization provider not installed")
	}

	organizationID := strings.TrimSpace(r.Gin.Param("orgId"))
	workspaceID := strings.TrimSpace(r.Gin.Param("workspaceId"))
	teamID := strings.TrimSpace(r.Gin.Param("teamId"))
	if organizationID == "" || workspaceID == "" || teamID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "Invalid request")
	}

	if err := orgs.RevokeOrganizationTeamWorkspaceAccessForUser(r.Context(), r.UserID(), organizationID, workspaceID, teamID); err != nil {
		return api.Response{}, err
	}
	return api.OK(dto.EmptyResponse{}), nil
}
