package ledger

import (
	"context"
	"strings"

	"github.com/tech/sendico/ledger/storage"
	"github.com/tech/sendico/pkg/api/routers/gsresponse"
	"github.com/tech/sendico/pkg/merrors"
	"github.com/tech/sendico/pkg/mutil/mzap"
	ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.uber.org/zap"
)

func (s *Service) listAccountsResponder(_ context.Context, req *ledgerv1.ListAccountsRequest) gsresponse.Responder[ledgerv1.ListAccountsResponse] {
	return func(ctx context.Context) (*ledgerv1.ListAccountsResponse, error) {
		if s.storage == nil {
			return nil, errStorageNotInitialized
		}
		if req == nil {
			return nil, merrors.InvalidArgument("request is required")
		}

		orgRefStr := strings.TrimSpace(req.GetOrganizationRef())
		if orgRefStr == "" {
			return nil, merrors.InvalidArgument("organization_ref is required")
		}
		orgRef, err := parseObjectID(orgRefStr)
		if err != nil {
			return nil, err
		}

		// Build filter from request.
		var filter *storage.AccountsFilter
		if req.GetOwnerRefFilter() != nil {
			ownerRefStr := strings.TrimSpace(req.GetOwnerRefFilter().GetValue())
			var ownerRef bson.ObjectID
			if ownerRefStr != "" {
				ownerRef, err = parseObjectID(ownerRefStr)
				if err != nil {
					return nil, merrors.InvalidArgument("owner_ref_filter: " + err.Error())
				}
			}
			filter = &storage.AccountsFilter{OwnerRefFilter: &ownerRef}
		}

		// No pagination requested; return all accounts for the organization.
		accounts, err := s.storage.Accounts().ListByOrganization(ctx, orgRef, filter, 0, 0)
		if err != nil {
			s.logger.Warn("Failed to list ledger accounts", zap.Error(err), mzap.ObjRef("organization_ref", orgRef))
			return nil, err
		}

		resp := &ledgerv1.ListAccountsResponse{
			Accounts: make([]*ledgerv1.LedgerAccount, 0, len(accounts)),
		}
		for _, acc := range accounts {
			resp.Accounts = append(resp.Accounts, toProtoAccount(acc))
		}

		return resp, nil
	}
}
