<?php

namespace App\Policies;

use App\Models\Loan;
use App\Models\User;
use App\Services\BranchAccessService;
use App\Support\Authorization\PermissionName;

class LoanPolicy
{
    public function __construct(private BranchAccessService $branchAccess)
    {
    }

    public function viewAny(User $user): bool
    {
        return $user->can(PermissionName::LOANS_VIEW->value);
    }

    public function view(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_VIEW->value)
            && $this->canAccess($user, $loan);
    }

    public function create(User $user): bool
    {
        return $user->can(PermissionName::LOANS_CREATE->value);
    }

    public function update(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_UPDATE->value)
            && $this->canAccess($user, $loan);
    }

    public function transition(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_UPDATE->value)
            && $this->canAccess($user, $loan);
    }

    public function generateContract(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_CONTRACT->value)
            && $this->canAccess($user, $loan);
    }

    public function manageDocuments(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_DOCUMENTS->value)
            && $this->canAccess($user, $loan);
    }

    public function downloadDocument(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_VIEW->value)
            && $this->canAccess($user, $loan);
    }

    public function approve(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_APPROVE->value)
            && $this->canAccess($user, $loan);
    }

    public function addCollateral(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_UPDATE->value)
            && $this->canAccess($user, $loan);
    }

    public function disburse(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_DISBURSE->value)
            && $this->canAccess($user, $loan);
    }

    public function receivePayment(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::PAYMENTS_RECEIVE->value)
            && $this->canAccess($user, $loan);
    }

    public function submitRemotePayment(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::PAYMENTS_REMOTE_SUBMIT->value)
            && $this->canAccess($user, $loan);
    }

    public function createTopUp(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_TOP_UP_CREATE->value)
            && $this->canAccess($user, $loan);
    }

    public function executeTopUp(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_TOP_UP_EXECUTE->value)
            && $this->canAccess($user, $loan);
    }

    public function settle(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_SETTLEMENT_EXECUTE->value)
            && $this->canAccess($user, $loan);
    }

    public function restructure(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_RESTRUCTURE_CREATE->value)
            && $this->canAccess($user, $loan);
    }

    public function requestWriteOff(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_WRITEOFF_REQUEST->value)
            && $this->canAccess($user, $loan);
    }

    public function viewArrears(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::ARREARS_VIEW->value)
            && $this->canAccess($user, $loan);
    }

    public function followUpArrears(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::ARREARS_FOLLOW_UP->value)
            && $this->canAccess($user, $loan);
    }

    public function excuseInstallment(User $user, Loan $loan): bool
    {
        return $user->can(PermissionName::LOANS_INSTALLMENTS_EXCUSE->value)
            && $this->canAccess($user, $loan);
    }

    private function canAccess(User $user, Loan $loan): bool
    {
        return $this->branchAccess->canAccessBranch($user, (int) $loan->branch_id);
    }
}
