package gitcred

import (
	"context"
	"fmt"
	"strings"
	"time"
)

// TokenLease is the short-lived AGS repository token returned by MeshX
// access:batch endpoints for Desktop-managed Git sync.
type TokenLease struct {
	Token     string
	ExpiresAt time.Time
}

// LeaseRefresher refreshes a TokenLease before go-git sends a request.
type LeaseRefresher func(context.Context) (TokenLease, error)

// ParseTokenLease validates the wire fields returned by MeshX access:batch.
func ParseTokenLease(token, expires string) (TokenLease, error) {
	token = strings.TrimSpace(token)
	if token == "" {
		return TokenLease{}, fmt.Errorf("missing syncToken")
	}
	expires = strings.TrimSpace(expires)
	if expires == "" {
		return TokenLease{}, fmt.Errorf("missing syncTokenExpires")
	}
	parsed, err := time.Parse(time.RFC3339Nano, expires)
	if err != nil {
		return TokenLease{}, fmt.Errorf("parse syncTokenExpires: %w", err)
	}
	return TokenLease{Token: token, ExpiresAt: parsed}, nil
}

// NewRefreshableLeaseAuth adapts a TokenLease refresher to go-git's HTTP auth
// interface. The resulting auth method sends Authorization: Bearer <token>.
func NewRefreshableLeaseAuth(initial TokenLease, refresh LeaseRefresher) *RefreshableTokenAuth {
	var tokenRefresh TokenRefresher
	if refresh != nil {
		tokenRefresh = func(ctx context.Context) (string, time.Time, error) {
			lease, err := refresh(ctx)
			if err != nil {
				return "", time.Time{}, err
			}
			return lease.Token, lease.ExpiresAt, nil
		}
	}
	return NewRefreshableTokenAuth(initial.Token, initial.ExpiresAt, tokenRefresh)
}
