<?php

namespace App\Repositories;

use App\Models\AccountDetail;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Mail\Mailer;

class AccountDetailRepository
{
    public function __construct(AccountDetail $accountDetail, Filesystem $filesystem, Mailer $mailer)
    {
        $this->model = $accountDetail;
        $this->file = $filesystem;
        $this->mailer = $mailer;
    }

    public function getByUserId($userId)
    {
        return $this->model->where('user_id', '=', (int) $userId)->first();
    }

    public function getOrCreateByUserId($userId)
    {
        $userId = (int) $userId;
        $account = $this->getByUserId($userId);
        if ($account) {
            return $account;
        }

        $account = $this->model->newInstance();
        $account->user_id = $userId;
        $account->total_credited = 0;
        $account->total_debited = 0;
        $account->current_balance = 0;
        $account->save();

        return $account;
    }

    /**
     * Fetch the account row with a FOR UPDATE lock.
     * NOTE: Must be called inside a DB transaction.
     */
    public function getOrCreateByUserIdForUpdate($userId)
    {
        $userId = (int) $userId;

        $account = $this->model->where('user_id', '=', $userId)->lockForUpdate()->first();
        if ($account) {
            return $account;
        }

        $account = $this->model->newInstance();
        $account->user_id = $userId;
        $account->total_credited = 0;
        $account->total_debited = 0;
        $account->current_balance = 0;
        $account->save();

        return $account;
    }

    public function applyCredit($userId, $amount)
    {
        $amount = round((float) $amount, 2);
        $account = $this->getOrCreateByUserId($userId);

        $account->total_credited = round(((float) $account->total_credited) + $amount, 2);
        $account->current_balance = round(((float) $account->current_balance) + $amount, 2);
        $account->save();

        return $account;
    }

    public function applyDebit($userId, $amount)
    {
        $amount = round((float) $amount, 2);
        $account = $this->getOrCreateByUserId($userId);

        $account->total_debited = round(((float) $account->total_debited) + $amount, 2);
        $account->current_balance = round(((float) $account->current_balance) - $amount, 2);
        if ($account->current_balance < 0) {
            $account->current_balance = 0;
        }
        $account->save();

        return $account;
    }
}
