package provider

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

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

// ConfigGet handles GET /api/v1/workspaces/:workspaceId/providers/gitea/config.
// Returns the Gitea App configuration for the current workspace.
func (handler *GiteaHandler) ConfigGet(r api.WorkspaceScopedRequest) (api.Response, error) {
	authenticated := r.User
	workspaceID := r.WorkspaceID()

	config, err := handler.store.GetGiteaAppConfigForUser(r.Context(), authenticated.User.ID, workspaceID)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToGiteaAppConfigResponse(config)), nil
}

// ConfigUpdate handles PUT /api/v1/workspaces/:workspaceId/providers/gitea/config.
// The store performs the authoritative workspace-admin check. For an admin's
// first Gitea configuration, it atomically installs the builtin App and saves
// its credentials. Ordinary member proposals remain independently pending and
// are revalidated only if approved; they are not a global direct-write lock.
func (handler *GiteaHandler) ConfigUpdate(r api.WorkspaceScopedJSON[dto.GiteaConfigUpdateRequest]) (api.Response, error) {
	if handler.adminStore == nil {
		return api.Response{}, fmt.Errorf("Gitea admin store is not configured")
	}
	if !r.Body.Valid() {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "Gitea instance URL and display name are required")
	}
	config, err := handler.adminStore.SaveGiteaAppConfigForWorkspaceAdmin(r.Context(), r.UserID(), r.WorkspaceID(), provider.UpsertGiteaAppConfigParams{
		InstanceURL:   r.Body.InstanceURL,
		APIToken:      r.Body.APIToken,
		WebhookSecret: r.Body.WebhookSecret,
		DisplayName:   r.Body.DisplayName,
	})
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToGiteaAppConfigResponse(config)), nil
}

// ConnectionCreate handles POST /api/v1/workspaces/:workspaceId/providers/gitea/connections.
// It is the workspace-admin direct path; member connection changes continue to
// use App installation requests.
func (handler *GiteaHandler) ConnectionCreate(r api.WorkspaceScopedJSON[dto.GiteaConnectionCreateRequest]) (api.Response, error) {
	if handler.adminStore == nil {
		return api.Response{}, fmt.Errorf("Gitea admin store is not configured")
	}
	target := strings.TrimSpace(r.Body.Target)
	if target == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "target is required")
	}
	installation, err := handler.adminStore.CreateGiteaConnectionForWorkspaceAdmin(r.Context(), r.UserID(), r.WorkspaceID(), target)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToProviderAppInstallationResponse(installation)), nil
}

// ConnectionsList handles GET /api/v1/workspaces/:workspaceId/providers/gitea/connections.
// Returns the list of Gitea connections for the current workspace.
func (handler *GiteaHandler) ConnectionsList(r api.WorkspaceScopedRequest) (api.Response, error) {
	authenticated := r.User
	workspaceID := r.WorkspaceID()

	connections, err := handler.store.ListGiteaConnectionsForUser(r.Context(), authenticated.User.ID, workspaceID)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToProviderAppConnectionResponses(connections)), nil
}

// Disconnect handles DELETE /api/v1/workspaces/:workspaceId/providers/gitea/connections/:connectionId.
// Only a current workspace admin may use this direct path.
func (handler *GiteaHandler) Disconnect(r api.WorkspaceScopedRequest) (api.Response, error) {
	if handler.adminStore == nil {
		return api.Response{}, fmt.Errorf("Gitea admin store is not configured")
	}
	connectionID := strings.TrimSpace(r.Gin.Param("connectionId"))
	if connectionID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "connectionId is required")
	}
	if err := handler.adminStore.DisconnectGiteaConnectionForWorkspaceAdmin(r.Context(), r.UserID(), r.WorkspaceID(), connectionID); err != nil {
		return api.Response{}, err
	}
	return api.NoContent(), nil
}
