package mailapi

import (
	"net/http"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/extension/providers/mail"
	"github.com/tidbcloud/AgentTeam/internal/store/storeerr"
)

type InstallResponse struct {
	InstallationID string   `json:"installationId"`
	ConnectionID   string   `json:"connectionId"`
	ExtensionName  string   `json:"extensionName"`
	DisplayName    string   `json:"displayName"`
	SenderAddress  string   `json:"senderAddress"`
	Capabilities   []string `json:"capabilities"`
}

type ReconnectResponse struct {
	ConnectionID  string   `json:"connectionId"`
	SenderAddress string   `json:"senderAddress"`
	Capabilities  []string `json:"capabilities"`
}

type Handler struct {
	service  ConnectionService
	realtime WorkspaceAppsRealtime
}

func (handler *Handler) Install(
	request api.WorkspaceScopedJSON[mail.InstallRequest],
) (api.Response, error) {
	if err := mail.ValidateInstallRequest(request.Body); err != nil {
		return api.Response{}, storeerr.BadRequest(err.Error())
	}
	result, err := handler.service.Install(
		request.Context(),
		request.UserID(),
		request.WorkspaceID(),
		request.Body,
	)
	if err != nil {
		return api.Response{}, err
	}
	handler.emitUpdated(request.WorkspaceID())
	return noStore(api.Created(InstallResponse{
		InstallationID: result.InstallationID,
		ConnectionID:   result.ConnectionID,
		ExtensionName:  result.ExtensionName,
		DisplayName:    result.DisplayName,
		SenderAddress:  result.SenderAddress,
		Capabilities:   append([]string(nil), result.Capabilities...),
	})), nil
}

func (handler *Handler) Reconnect(
	request api.WorkspaceScopedJSON[mail.ReconnectRequest],
) (api.Response, error) {
	if err := mail.ValidateReconnectRequest(request.Body); err != nil {
		return api.Response{}, storeerr.BadRequest(err.Error())
	}
	result, err := handler.service.Reconnect(
		request.Context(),
		request.UserID(),
		request.WorkspaceID(),
		strings.TrimSpace(request.Gin.Param("installationId")),
		request.Body,
	)
	if err != nil {
		return api.Response{}, err
	}
	handler.emitUpdated(request.WorkspaceID())
	return noStore(api.OK(ReconnectResponse{
		ConnectionID:  result.ConnectionID,
		SenderAddress: result.SenderAddress,
		Capabilities:  append([]string(nil), result.Capabilities...),
	})), nil
}

func (handler *Handler) Disconnect(
	request api.WorkspaceScopedRequest,
) (api.Response, error) {
	if err := handler.service.Disconnect(
		request.Context(),
		request.UserID(),
		request.WorkspaceID(),
		strings.TrimSpace(request.Gin.Param("installationId")),
		strings.TrimSpace(request.Gin.Param("connectionId")),
	); err != nil {
		return api.Response{}, err
	}
	handler.emitUpdated(request.WorkspaceID())
	return noStore(api.NoContent()), nil
}

func noStore(response api.Response) api.Response {
	if response.Headers == nil {
		response.Headers = make(http.Header)
	}
	response.Headers.Set("Cache-Control", "no-store")
	response.Headers.Set("Pragma", "no-cache")
	return response
}

func (handler *Handler) emitUpdated(workspaceID string) {
	if handler != nil && handler.realtime != nil {
		handler.realtime.EmitWorkspaceAppsUpdated(workspaceID)
	}
}
