package org

import (
	"context"
	"errors"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/store/identity"
	"github.com/tidbcloud/AgentTeam/internal/store/organization"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/require"
)

type tokenTestOrganizationProvider struct {
	OrganizationProvider
	createTokenResult organization.OrganizationProviderTokenView
	createTokenErr    error
	deleteTokenErr    error
	createCalls       int
	deleteCalls       int
}

func (provider *tokenTestOrganizationProvider) CreateOrganizationProviderTokenForUser(ctx context.Context, userID string, organizationID string, providerID string, params organization.CreateOrganizationProviderTokenParams) (organization.OrganizationProviderTokenView, error) {
	provider.createCalls++
	if provider.createTokenErr != nil {
		return organization.OrganizationProviderTokenView{}, provider.createTokenErr
	}
	return provider.createTokenResult, nil
}

func (provider *tokenTestOrganizationProvider) DeleteOrganizationProviderTokenForUser(ctx context.Context, userID string, organizationID string, providerID string, tokenID string) error {
	provider.deleteCalls++
	return provider.deleteTokenErr
}

type tokenTestRefresher struct {
	err   error
	calls int
}

func (refresher *tokenTestRefresher) Refresh(context.Context) error {
	refresher.calls++
	return refresher.err
}

func TestProviderHandlerTokenCreateRefreshesLLMRegistry(t *testing.T) {
	t.Parallel()

	orgs := &tokenTestOrganizationProvider{
		createTokenResult: organization.OrganizationProviderTokenView{
			ID:                     "optk_1",
			OrganizationID:         "org_1",
			OrganizationProviderID: "opvd_1",
			Label:                  "primary",
			TokenHint:              "Y1xU",
			Status:                 "active",
		},
	}
	refresher := &tokenTestRefresher{}
	handler := &ProviderHandler{organizationHandlerBase: organizationHandlerBase{
		organizations: orgs,
		llmRegistry:   refresher,
	}}

	router := gin.New()
	router.POST("/api/v1/orgs/:orgId/providers/:providerId/tokens", func(ctx *gin.Context) {
		api.SetAuthenticatedUser(ctx, identity.AuthenticatedUser{User: identity.User{ID: "usr_1"}})
		handler.TokenCreate(ctx)
	})

	recorder := httptest.NewRecorder()
	request := httptest.NewRequest(http.MethodPost, "/api/v1/orgs/org_1/providers/opvd_1/tokens", strings.NewReader(`{"label":"primary","token":"sk-test"}`))
	request.Header.Set("Content-Type", "application/json")
	router.ServeHTTP(recorder, request)

	require.Equal(t, http.StatusOK, recorder.Code)
	require.Equal(t, 1, orgs.createCalls)
	require.Equal(t, 1, refresher.calls)
}

func TestProviderHandlerTokenDeleteRefreshesLLMRegistry(t *testing.T) {
	t.Parallel()

	orgs := &tokenTestOrganizationProvider{}
	refresher := &tokenTestRefresher{}
	handler := &ProviderHandler{organizationHandlerBase: organizationHandlerBase{
		organizations: orgs,
		llmRegistry:   refresher,
	}}

	router := gin.New()
	router.DELETE("/api/v1/orgs/:orgId/providers/:providerId/tokens/:tokenId", func(ctx *gin.Context) {
		api.SetAuthenticatedUser(ctx, identity.AuthenticatedUser{User: identity.User{ID: "usr_1"}})
		handler.TokenDelete(ctx)
	})

	recorder := httptest.NewRecorder()
	request := httptest.NewRequest(http.MethodDelete, "/api/v1/orgs/org_1/providers/opvd_1/tokens/optk_1", nil)
	router.ServeHTTP(recorder, request)

	require.Equal(t, http.StatusOK, recorder.Code)
	require.Equal(t, 1, orgs.deleteCalls)
	require.Equal(t, 1, refresher.calls)
}

func TestProviderHandlerTokenCreateReturnsServerErrorWhenRefreshFails(t *testing.T) {
	t.Parallel()

	orgs := &tokenTestOrganizationProvider{
		createTokenResult: organization.OrganizationProviderTokenView{
			ID:                     "optk_1",
			OrganizationID:         "org_1",
			OrganizationProviderID: "opvd_1",
			Label:                  "primary",
			TokenHint:              "Y1xU",
			Status:                 "active",
		},
	}
	refresher := &tokenTestRefresher{err: errors.New("refresh failed")}
	handler := &ProviderHandler{organizationHandlerBase: organizationHandlerBase{
		organizations: orgs,
		llmRegistry:   refresher,
	}}

	router := gin.New()
	router.POST("/api/v1/orgs/:orgId/providers/:providerId/tokens", func(ctx *gin.Context) {
		api.SetAuthenticatedUser(ctx, identity.AuthenticatedUser{User: identity.User{ID: "usr_1"}})
		handler.TokenCreate(ctx)
	})

	recorder := httptest.NewRecorder()
	request := httptest.NewRequest(http.MethodPost, "/api/v1/orgs/org_1/providers/opvd_1/tokens", strings.NewReader(`{"label":"primary","token":"sk-test"}`))
	request.Header.Set("Content-Type", "application/json")
	router.ServeHTTP(recorder, request)

	require.Equal(t, http.StatusInternalServerError, recorder.Code)
	require.Equal(t, 1, refresher.calls)
}
