package pgdb

import (
	"context"
	"database/sql"
	"errors"
	"fmt"

	dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
	dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
	"github.com/Masterminds/squirrel"
)

func (c *client) GetBalance(
	ctx context.Context,
	request *dbtypes.BalanceGetRequest,
) (*dbtypes.BalanceGetResponse, error) {
	if request == nil {
		return nil, nil
	}

	var (
		psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)

		balancesTable = fmt.Sprintf("%s.%s", c.config.Schema, BalancesTableName)
	)

	getBalance := psql.Select(
		"raw_balance", "clean_balance",
	).From(balancesTable).
		Where(squirrel.Eq{"owner_id": request.OwnerId})

	query, args, err := getBalance.ToSql()
	if err != nil {
		return nil, fmt.Errorf("%w: error building get balance query: %v", dberrors.ErrInternal, err)
	}

	row := c.db.QueryRowContext(ctx, query, args...)

	var (
		balance dbtypes.Balance
	)

	if err := row.Scan(&balance.RawBalance, &balance.CleanBalance); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return nil, dberrors.ErrNotFound
		}

		return nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
	}

	return &dbtypes.BalanceGetResponse{
		Balance: &balance,
	}, nil
}

func (c *client) createBalance(
	ctx context.Context,
	driver Driver,
	request *dbtypes.BalanceCreateRequest,
) error {
	if request == nil {
		return fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
	}

	var (
		psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)

		balancesTable = fmt.Sprintf("%s.%s", c.config.Schema, BalancesTableName)
	)

	createBalance := psql.Insert(balancesTable).
		Columns(
			"id", "owner_id", "raw_balance", "clean_balance",
		).
		Values(
			request.Id, request.OwnerId, request.RawBalance, request.CleanBalance,
		)

	query, args, err := createBalance.ToSql()
	if err != nil {
		return fmt.Errorf("%w: error building 'create balance' query: %v", dberrors.ErrInternal, err)
	}

	res, err := driver.ExecContext(ctx, query, args...)
	if err != nil {
		return fmt.Errorf("%w: error executing 'create balance' query: %v", dberrors.ErrInternal, err)
	}

	rowsAffected, err := res.RowsAffected()
	if err != nil {
		return fmt.Errorf("%w: error getting rows affected for 'create balance' query: %v", dberrors.ErrInternal, err)
	}

	if rowsAffected == 0 {
		return dberrors.ErrInternal
	}

	return nil
}
