<?php

namespace App\Traits;

use App\Classes\Common;
use App\Classes\Notify;
use App\Classes\Payrolls;
use App\Http\Requests\Api\User\ImportRequest;
use App\Imports\UserImport;
use App\Models\Role;
use Examyou\RestAPI\ApiResponse;
use Examyou\RestAPI\Exceptions\ApiException;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;

trait UserTraits
{
    public $userType = "";
    public $moduleName = "";

    public function modifyIndex($query)
    {
        $request = request();
        $user    = user();

        // User Status Filter
        if ($request->has('status') && $request->status != "all") {
            $userStatus = $request->status;
            $query      = $query->where('users.status', $userStatus);
        }

        $query = $query->where('users.user_type', $this->userType);

        if ($this->moduleName != '') {
            $query = $query->where('users.module_name', $this->moduleName);
        }

        return $query;
    }

    public function storing($user)
    {
        $loggedUser = user();
        $request    = request();

        // Set user_type to trigger the model's mutator
        $user->user_type = $this->userType;

        // Set module_name if applicable
        if ($this->moduleName != '') {
            $user->module_name = $this->moduleName;
        }

        if ($user->user_type != $this->userType) {
            throw new ApiException("Don't have valid permission");
        }

        // allow_login, role_id, and password are only set when user has assign_role permission
        if ($loggedUser->ability('admin', 'assign_role')) {
            $user->allow_login = $request->has('allow_login') ? (bool) $request->allow_login : false;

            if ($user->user_type == 'staff_members') {
                // Only set role_id if allow_login is true, otherwise clear it
                if ($user->allow_login) {
                    $user->role_id = $request->has('role_id') && $request->role_id ? $this->getIdFromHash($request->role_id) : null;
                } else {
                    $user->role_id = null;
                }
            }
        } else {
            // User without assign_role permission cannot set allow_login
            $user->allow_login = false;
            $user->role_id = null;
        }

        return $user;
    }

    public function stored($user)
    {
        $request = request();
        $this->saveAndUpdateRole($user);

        // Notifying to User
        $user->user_password =  $request->has('password') && $request->password ? $request->password : '';
        Notify::send('user_welcome_mail', $user);
    }

    public function updating($user)
    {
        $loggedUser = user();
        $request    = request();

        // Can not change role because only one
        // Admin exists for whole app
        if ($user->user_type == "staff_members") {
            $adminRoleUserCount = Role::join('role_user', 'roles.id', '=', 'role_user.role_id')
                ->where('roles.name', '=', 'admin')
                ->count('role_user.user_id');

            if ($adminRoleUserCount <= 1 && $loggedUser->id == $user->id && $user->isDirty('role_id')) {
                throw new ApiException("Can not change role because you are only admin of app");
            }
        }

        if ($user->user_type != $this->userType) {
            throw new ApiException("Don't have valid permission");
        }

        // Demo mode admin cannot be edit
        // email, password, status, role_id
        if (env('APP_ENV') == 'production' && ($user->isDirty('password') || $user->isDirty('email') || $user->isDirty('status') || $user->isDirty('role_id'))) {
            if ($user->user_type == 'staff_members' && ($user->getOriginal('email') == 'admin@example.com' || $user->getOriginal('email') == 'stockmanager@example.com' || $user->getOriginal('email') == 'salesman@example.com')) {
                throw new ApiException('Not Allowed In Demo Mode');
            }
        }

        // allow_login, role_id are only updated when user has assign_role permission
        if ($loggedUser->ability('admin', 'assign_role')) {
            if ($request->has('allow_login')) {
                $user->allow_login = (bool) $request->allow_login;
            }

            if ($user->user_type == 'staff_members') {
                // Only set role_id if allow_login is true, otherwise clear it
                if ($user->allow_login) {
                    $user->role_id = $request->has('role_id') && $request->role_id ? $this->getIdFromHash($request->role_id) : $user->role_id;
                } else {
                    $user->role_id = null;
                }
            }
        }
        // User without assign_role permission cannot change allow_login or role_id - keep existing values

        return $user;
    }

    public function updated($user)
    {
        $this->saveAndUpdateRole($user);
    }

    public function saveAndUpdateRole($user)
    {
        // Only For Staff Members
        if ($user->user_type == 'staff_members') {
            // Always remove existing role first
            DB::table('role_user')->where('user_id', $user->id)->delete();

            // Only attach role if role_id exists and allow_login is true
            if ($user->role_id && $user->allow_login) {
                $user->attachRole($user->role_id);
            }
        }

        return $user;
    }

    public function destroying($user)
    {
        if ($user->user_type != $this->userType) {
            throw new ApiException("Don't have valid permission");
        }

        $loggedUser        = user();
        $loggedUserCompany = company();

        if ($loggedUserCompany->admin_id == $user->id) {
            throw new ApiException('Can not delete company root admin');
        }

        if (env('APP_ENV') == 'production' && $user->user_type == 'staff_members' && ($user->getOriginal('email') == 'admin@example.com' || $user->getOriginal('email') == 'stockmanager@example.com' || $user->getOriginal('email') == 'salesman@example.com')) {
            throw new ApiException('Not Allowed In Demo Mode');
        }

        // If application have only one admin
        // Then staff member cannot be deleted
        if ($user->user_type == "staff_members") {
            if ($user->role_id) {
                $userRole = Role::find($user->role_id);

                if ($userRole && $userRole->name == 'admin') {
                    $adminRoleUserCount = Role::join('role_user', 'roles.id', '=', 'role_user.role_id')
                        ->where('roles.name', '=', 'admin')
                        ->count('role_user.user_id');

                    if ($adminRoleUserCount <= 1) {
                        throw new ApiException('You are the only admin of app. So not able to delete.');
                    }
                }
            }
        }

        if ($loggedUser->id == $user->id) {
            throw new ApiException('Can not delete yourself.');
        }

        return $user;
    }

    public function destroyed($user)
    {
        // Updating Company Total Users
        Common::calculateTotalUsers($user->company_id, true);
    }

    public function import(ImportRequest $request)
    {
        if ($request->hasFile('file')) {
            Excel::import(new UserImport($this->userType), request()->file('file'));
        }

        return ApiResponse::make('Imported Successfully', []);
    }
}
