<?php

namespace App\Services;

use App\Models\User;
use App\Models\SMTPMails;
use Illuminate\Support\Str;
use App\Repositories\UserRepository;
use Illuminate\Support\Facades\Hash;
use App\Exceptions\SystemErrorException;

class UserService
{
    public $userRepository;

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function getAllUsers()
    {
        return User::orderBy('is_owner', 'desc')->orderBy('created_at', 'desc')->get();
    }

    public function activate($user, $data, $isAdmin)
    {

        if (is_null(SMTPMails::defaultSmtpMail()->first())) {
            throw SystemErrorException::withMessages([
                'email' => ["SMTP server not found in the database. Please provide an SMTP server to enable email sending"]
            ]);

        }

        $this->checkStatus($user, "active");
        $this->checkIsOwner($user);

        if (!$isAdmin) {
            $user->group_ID = $data->input('user-group');
        }

        $user->status = "active";
        $user->save();

        $user->sendActivateUserMail();
    }

    public function block($user, $data)
    {
        $this->checkStatus($user, "blocked");
        $this->checkIsOwner($user);

        $user->status = "blocked";
        $user->save();
    }

    public function unblock($user, $data)
    {
        $this->checkStatus($user, "active");
        $this->checkIsOwner($user);

        $user->status = "active";
        $user->save();
    }

    public function destroy($user, $data)
    {

        if ($user->trashed()) {
            abort(400, "This user's status does not permit this action.");
        }

        $this->checkIsOwner($user);

        $user->delete();
    }

    private function checkStatus($user, $status)
    {

        if (strtolower($user->status) === strtolower($status)) {
            abort(400, "This user's status does not permit this action.");
        }

    }

    private function checkIsOwner($user)
    {

        if ($user->is_owner) {
            abort(400, "This action is prevented for this user.");
        }

    }

    private function checkIsNotAdmin($user)
    {

        if (!$user->is_admin) {
            abort(400, "This action is prevented for this user.");
        }

    }

    public function store($data)
    {

        if (is_null(SMTPMails::defaultSmtpMail()->first())) {
            throw SystemErrorException::withMessages([
                'email' => ["SMTP server not found in the database. Please provide an SMTP server to enable email sending"]
            ]);

        }

        $temp_password = $this->generateRandomPassword(12);

        $data['added_by'] = auth()->user()->user_ID;

        $data['Password'] = Hash::make($temp_password);

        $user = $this->userRepository->createUser($data);

        $this->sendInvitationEmail($user, $data, $temp_password);

        $this->sendVerificationEmail($user, $data);
    }

    public function update($user, $data)
    {
        $this->checkEmailChanged($user, $data);
        $this->checkPendedToActiveChange($user, $data);

        $this->checkResetPassword($user, $data);

        $this->userRepository->updateUser($user, $data);

        $this->sendVerificationEmail($user, $data);
    }

    private function generateRandomPassword($length)
    {
        return Str::password($length);
    }

    private function sendInvitationEmail($user, $data, $temp_password)
    {

        if (isset($user) && isset($data['send_invitaion'])) {
            $user->sendEmailInvitationNotification($temp_password);
        }

    }

    private function sendVerificationEmail($user, $data)
    {

        if (isset($user) && isset($data['send_activation'])) {
            $user->sendEmailVerificationNotification();
        }

    }

    private function checkResetPassword($user, $data)
    {

        if (isset($user) && isset($data['reset_password'])) {

            $temp_password = $this->generateRandomPassword(12);
            $user->update(['Password' => Hash::make($temp_password)]);

            $user->sendResetPasswordManuallyMail($temp_password);
        }

    }

    private function checkEmailChanged($user, $data)
    {
        $old_email = $user->Email;

        if (isset($old_email) && $old_email !== $data["Email"]) {
            $user->sendEmailChangedConfirmationMail($data["Email"]);
        }

    }

    private function checkPendedToActiveChange($user, $data)
    {
        $old_status = strtolower($user->status);

        if (isset($old_status) && $old_status === "pended" && strtolower($data["status"]) === "active") {
            $user->sendActivateUserMail();
        }

    }

}