package oauth

import (
	"context"
	"fmt"
	"time"

	"github.com/jackc/pgx/v5/pgxpool"
	"golang.org/x/oauth2"

	mailcredentials "github.com/ultisuite/ulti-backend/internal/mail/credentials"
)

// RefreshAccountCredential refreshes OAuth tokens when needed and persists updated credentials.
func RefreshAccountCredential(
	ctx context.Context,
	db *pgxpool.Pool,
	manager *mailcredentials.Manager,
	oauthSvc *Service,
	accountID string,
	cred mailcredentials.Credential,
) (mailcredentials.Credential, error) {
	if !cred.IsOAuth() || !cred.NeedsRefresh() {
		return cred, nil
	}
	if oauthSvc == nil || cred.RefreshToken == "" {
		return cred, fmt.Errorf("oauth refresh unavailable")
	}
	token, err := oauthSvc.Refresh(ctx, cred.OAuthProvider, cred.RefreshToken)
	if err != nil {
		return cred, fmt.Errorf("refresh token: %w", err)
	}
	updated := applyToken(cred, token)
	blob, err := manager.EncryptCredential(updated)
	if err != nil {
		return cred, err
	}
	_, err = db.Exec(ctx, `UPDATE mail_accounts SET credentials = $1, updated_at = NOW() WHERE id = $2`, blob, accountID)
	if err != nil {
		return cred, err
	}
	return updated, nil
}

func CredentialFromToken(email, provider string, token *oauth2.Token) mailcredentials.Credential {
	return applyToken(mailcredentials.Credential{
		AuthType:      mailcredentials.AuthOAuth2,
		Username:      email,
		OAuthProvider: provider,
	}, token)
}

func applyToken(c mailcredentials.Credential, token *oauth2.Token) mailcredentials.Credential {
	c.AccessToken = token.AccessToken
	if token.RefreshToken != "" {
		c.RefreshToken = token.RefreshToken
	}
	if !token.Expiry.IsZero() {
		c.Expiry = token.Expiry.UTC()
	} else if token.ExpiresIn > 0 {
		c.Expiry = time.Now().Add(time.Duration(token.ExpiresIn) * time.Second)
	}
	return c
}
