package org

import (
	"context"
	"log/slog"
	"net/http"
	"strings"
	"time"

	"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/observability/logging"
)

const feishuDirectorySyncTimeout = 15 * time.Minute

// GetEnterprise handles GET /api/v1/orgs/:orgId/enterprise/feishu.
// It retrieves the Feishu enterprise integration settings for the organization.
func (handler *FeishuHandler) GetEnterprise(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")
	}

	view, err := orgs.GetOrganizationEnterpriseFeishuForUser(r.Context(), r.UserID(), organizationID)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToOrgEnterpriseFeishuView(view)), nil
}

// SetCredentials handles PUT /api/v1/orgs/:orgId/enterprise/feishu/credentials.
// It updates the Feishu app credentials for the organization's enterprise integration.
func (handler *FeishuHandler) SetCredentials(r api.AuthenticatedJSON[dto.OrganizationFeishuCredentialsRequest]) (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

	view, err := orgs.UpdateOrganizationEnterpriseFeishuCredentialsForUser(
		r.Context(),
		r.UserID(),
		organizationID,
		request.AppID,
		request.AppSecret,
	)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToOrgEnterpriseFeishuView(view)), nil
}

// DeleteCredentials handles DELETE /api/v1/orgs/:orgId/enterprise/feishu/credentials.
// It removes the Feishu app credentials from the organization's enterprise integration.
func (handler *FeishuHandler) DeleteCredentials(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")
	}

	view, err := orgs.DeleteOrganizationEnterpriseFeishuCredentialsForUser(r.Context(), r.UserID(), organizationID)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToOrgEnterpriseFeishuView(view)), nil
}

// Sync handles POST /api/v1/orgs/:orgId/feishu/sync.
// It triggers a Feishu directory sync for the organization.
func (handler *FeishuHandler) Sync(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")
	}

	summary, created, err := orgs.StartOrganizationFeishuDirectorySyncForUser(r.Context(), r.UserID(), organizationID)
	if err != nil {
		return api.Response{}, err
	}
	if created {
		handler.runFeishuDirectorySyncInBackground(orgs, r.UserID(), organizationID, summary.SyncRunID)
	}
	return api.OK(converter.ToOrgDirectorySyncRunSummaryView(&summary)), nil
}

func (handler *FeishuHandler) runFeishuDirectorySyncInBackground(orgs OrganizationProvider, userID string, organizationID string, syncRunID string) {
	logger := handler.logger
	if logger == nil {
		logger = slog.Default()
	}
	logging.Go(nil, func() {
		ctx, cancel := context.WithTimeout(context.Background(), feishuDirectorySyncTimeout)
		defer cancel()
		if _, err := orgs.RunOrganizationFeishuDirectorySyncForUser(ctx, userID, organizationID, syncRunID); err != nil {
			logger.Error(
				"organization feishu directory sync failed",
				slog.String("organization_id", organizationID),
				slog.String("sync_run_id", syncRunID),
				slog.String("error", err.Error()),
			)
			return
		}
		logger.Info(
			"organization feishu directory sync completed",
			slog.String("organization_id", organizationID),
			slog.String("sync_run_id", syncRunID),
		)
	})
}
