<?php

namespace App\Modules\Admin\Libraries;

use App\Models\Role;
use App\Models\AccessRole;
use App\Http\Resources\Admin\Roles as RolesResource;
use App\Traits\SearchTraits;
use App\Traits\SortingTraits;
use App\Traits\ValidatorTraits;
use Illuminate\Support\Facades\DB;

class RoleModule
{
    use SortingTraits, SearchTraits, ValidatorTraits;

    public function getData($payload)
    {
        //! Sorting
        $sortField = $payload['sortField'] ?? 'name';
        $sortOrder = $payload['sortOrder'] ?? 'asc';

        //! Searching
        $nameSearch   = $payload['name'] ?? null;
        $accessSearch = $payload['access'] ?? null;

        return RolesResource::collection(
            Role::select(
                'roles.id',
                'roles.name')
                ->when(
                    !empty($nameSearch), function ($query) use ($nameSearch) 
                    {
                        return $query->where(function ($query) use ($nameSearch) 
                            {
                                $query->where('roles.name', 'LIKE', $nameSearch . '%');
                            }
                        );
                    }
                )
                ->with('access')
                ->whereHas(
                    'access', function ($query) use ($accessSearch) 
                    {
                        $query->when(!empty($accessSearch), function ($query) use ($accessSearch) 
                            {
                                return $query->join('access', 'access.id', "=", 'access_roles.access_id')
                                    ->whereIn('access.id', $accessSearch);
                            }
                        );
                    }
                )
                ->orderBy($sortField, $sortOrder)
                ->paginate(20)
        )
        ->response()
        ->setStatusCode(200);
    }

    public function getDetails($id)
    {
        return RolesResource::collection(
            Role::select(
            'roles.id',
            'roles.name')
            ->with('access:role_id,access_id,page')
            ->where('roles.id', $id)
            ->limit(1)
            ->get()
        )
        ->response()
        ->setStatusCode(200);
    }

    public function updateData($payload, $id)
    {
        DB::beginTransaction();

        $name   = $payload['name'];

        $role = 
        [
            'name' => $name,
        ];

        $roleNameTransaction = $this->saveRole($id, $role);

        $this->deleteAccessRole($id);

        foreach ($payload['access'] as $access) 
        {
            $accessRole = 
            [
                'role_id' => $id,
                'access_id' => $access,
            ];

            
            $accessRoleTransaction = $this->saveAccessRole($accessRole);

            if (!$accessRoleTransaction) 
            {
                DB::rollBack();
            
                return response()->json(['error' => 'Server error.'])->setStatusCode(500);
            }
        }

        if (!$roleNameTransaction) 
        {
            DB::rollBack();
        
            return response()->json(['error' => 'Server error.'])->setStatusCode(500);    
        } 
        else 
        {
            DB::commit();
        
            return response()->json(['success' => 'Data updated successfully.'])->setStatusCode(200);
        }
    }

    public function saveRole($id, $role)
    {
        return Role::where('id', $id)->update($role);
    }

    public function deleteAccessRole($id)
    {
        return AccessRole::where('role_id', $id)->delete();
    }

    public function saveAccessRole($accessRole)
    {
        return AccessRole::create($accessRole);
    }
}
