package organization

import (
	"context"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
)

func (txs TxStore) SyncOrganizationFeishuDirectoryForUser(ctx context.Context, userID string, organizationID string) (OrganizationFeishuDirectoryImportResult, error) {
	return txs.syncOrganizationFeishuDirectoryRunForUser(ctx, userID, organizationID, "")
}

func (txs TxStore) SyncOrganizationFeishuDirectoryRunForUser(ctx context.Context, userID string, organizationID string, syncRunID string) (OrganizationFeishuDirectoryImportResult, error) {
	return txs.syncOrganizationFeishuDirectoryRunForUser(ctx, userID, organizationID, strings.TrimSpace(syncRunID))
}

func (txs TxStore) syncOrganizationFeishuDirectoryRunForUser(ctx context.Context, userID string, organizationID string, syncRunID string) (OrganizationFeishuDirectoryImportResult, error) {
	if _, err := txs.requireActiveOrganizationAdmin(ctx, txs.db, userID, organizationID); err != nil {
		return OrganizationFeishuDirectoryImportResult{}, err
	}
	if _, ok := loadPreparedFeishuDirectoryImport(ctx, organizationID); ok {
		return txs.importOrganizationFeishuDirectoryWithNamespaceAndRun(ctx, organizationID, "", nil, syncRunID)
	}

	settings, err := txs.loadOrganizationSettingsRecord(ctx, txs.db, organizationID)
	if err != nil {
		return OrganizationFeishuDirectoryImportResult{}, err
	}
	if settings.DirectoryProvider != organizationProviderFeishu {
		return OrganizationFeishuDirectoryImportResult{}, badRequest("organization directory provider is not feishu")
	}

	credentials, err := txs.resolveOrganizationFeishuCredentials(ctx, txs.db, organizationID)
	if err != nil {
		return OrganizationFeishuDirectoryImportResult{}, err
	}
	client, err := txs.newFeishuDirectoryClient(credentials)
	if err != nil {
		return OrganizationFeishuDirectoryImportResult{}, err
	}
	return txs.importOrganizationFeishuDirectoryWithNamespaceAndRun(ctx, organizationID, credentials.AppID, client, syncRunID)
}

func (txs TxStore) StartOrganizationFeishuDirectorySyncForUser(ctx context.Context, userID string, organizationID string) (OrganizationDirectorySyncRunSummaryView, bool, error) {
	type startResult struct {
		summary OrganizationDirectorySyncRunSummaryView
		created bool
	}
	result, err := withTxValue(ctx, txs.db, func(tx coredb.Tx) (startResult, error) {
		if _, err := txs.requireActiveOrganizationAdmin(ctx, tx, userID, organizationID); err != nil {
			return startResult{}, err
		}
		settings, err := txs.loadOrganizationSettingsRecord(ctx, tx, organizationID)
		if err != nil {
			return startResult{}, err
		}
		if settings.DirectoryProvider != organizationProviderFeishu {
			return startResult{}, badRequest("organization directory provider is not feishu")
		}
		if _, err := txs.resolveOrganizationFeishuCredentials(ctx, tx, organizationID); err != nil {
			return startResult{}, err
		}
		state, err := txs.requireOrganizationExternalDirectory(ctx, tx, organizationID)
		if err != nil {
			return startResult{}, err
		}
		existing, found, err := txs.loadLatestRunningOrganizationDirectorySyncRun(ctx, tx, organizationID, organizationProviderFeishu, organizationSyncSourceDefault)
		if err != nil {
			return startResult{}, err
		}
		if found {
			return startResult{summary: existing.summaryView()}, nil
		}

		startedAt := time.Now().UTC()
		run, err := txs.createOrganizationDirectorySyncRun(ctx, tx, organizationID, state.revision, organizationProviderFeishu, organizationSyncSourceDefault, startedAt)
		if err != nil {
			return startResult{}, err
		}
		return startResult{summary: run.summaryView(), created: true}, nil
	})
	if err != nil {
		return OrganizationDirectorySyncRunSummaryView{}, false, err
	}
	return result.summary, result.created, nil
}

func (record organizationDirectorySyncRunRecord) summaryView() OrganizationDirectorySyncRunSummaryView {
	return OrganizationDirectorySyncRunSummaryView{
		SyncRunID:         record.ID,
		ExternalProvider:  record.ExternalProvider,
		SyncSource:        record.SyncSource,
		Status:            record.Status,
		DirectoryRevision: record.DirectoryRevision,
		StartedAt:         record.StartedAt,
		CompletedAt:       record.CompletedAt,
	}
}

func (txs TxStore) newFeishuDirectoryClient(credentials effectiveFeishuCredentials) (FeishuDirectoryClient, error) {
	return NewFeishuDirectoryHTTPClient(FeishuDirectoryHTTPClientOptions{
		BaseURL:    txs.feishuBaseURL,
		AppID:      credentials.AppID,
		AppSecret:  credentials.AppSecret,
		HTTPClient: txs.feishuHTTPClient,
	})
}

func resolveFeishuDirectoryIdentityNamespace(appID string, settings OrganizationSettingsView) string {
	if strings.TrimSpace(appID) != "" {
		return strings.TrimSpace(appID)
	}
	return strings.TrimSpace(settings.Feishu.TenantKey)
}
