<?php

namespace App\Http\Controllers\User;

use App\Helpers\Security;
use App\Http\Controllers\BaseController;
use App\Models\SecurityEvent;
use App\Models\User;
use App\Rules\AdminAnyUserIdentity;
use App\Rules\GroupIdentity;
use App\Rules\OrganisationIdentity;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Throwable;

class AdminController extends BaseController
{
    public function get_user(Request $_r, $_user_id) {
        if($user = User::where('id', '=', $_user_id)->select('name', 'email', 'group_id', 'organisation_id')->first()) {
            return response()->json($user, 200);            
        }

        return response()->json(['detail' => 'Error processing the request'], 500);
    }

    public function get_users(Request $_r) {
        return $this->paged_table($_r, function() {
            return User::select('users.id', DB::raw("(CASE WHEN password = '' THEN 0 ELSE 1 END) as is_setup"), DB::raw("(CASE WHEN totp_confirmed_at IS NULL THEN 0 ELSE 1 END) as mfa"), DB::raw('groups.name as group'), 'email', 'phone', DB::raw('users.name as user_name'), DB::raw('organisations.name as organisation_name'), 'organisations.id as organisation_id')
                ->leftJoin('organisations', 'organisation_id', '=', 'organisations.id')
                ->leftJoin('groups', 'group_id', 'groups.id')
                ->whereNull('organisations.deleted_at');
        }, [ 
            'user_name'         => [ 'db' => 'users.name', 'searchable' => true ],
            'email'             => [ 'db' => 'email', 'searchable' => true ],
            'organisation_name' => [ 'db' => 'organisations.name', 'searchable' => true ],
            'phone'             => [ 'db' => 'phone', 'searchable' => true ],
            'group'             => [ 'db' => 'groups.name', 'searchable' => true ]
        ], 'users.created_at', null);
    }

    public function create_user(Request $_r) {

        try {

            $valid_request = Validator::make($_r->input(), [
                'name'              => ['required', 'string', 'max:255'],
                'email'             => ['required', 'max:255', 'email:rfc,dns', 'unique:users,email'],
                'group_id'          => ['required', new GroupIdentity],
                'organisation_id'   => ['required', new OrganisationIdentity],
            ]);

            if(!$valid_request->fails()) { // Good input

                $user = new User([
                    'name'              => $_r->input('name'),
                    'password'          => '',
                    'email'             => $_r->input('email'),
                    'group_id'          => $_r->input('group_id'),
                    'organisation_id'   => $_r->input('organisation_id')
                ]);

                if($user->save()) {

                    $user->sendSetupEmail();

                    return response()->json(['detail' => 'User created'], 200);
                }

            }
            else { // Bad input
                return response()->json(['detail' => 'Invalid Payload'], 400);
            }

        }
        catch(Throwable $ex) {            
            Log::debug($ex);
        }

        return response()->json(['detail' => 'Server Error'], 500);
    }

    public function update_user(Request $_r, $_user_id) {

        try {

            $valid_request = Validator::make([ ...$_r->input(), 'user_id' => $_user_id ], [
                'user_id'           => ['required', new AdminAnyUserIdentity],
                'name'              => ['required', 'string', 'max:255'],
                'email'             => ['required', 'max:255', 'email', Rule::notIn( User::where('id', '!=', $_user_id)->pluck('email')->toArray() )],
                'group_id'          => ['required', new GroupIdentity],
                'organisation_id'   => ['required', new OrganisationIdentity],
            ]);

            if(!$valid_request->fails()) { // Good input

                $user = User::where('id', '=', $_user_id)->first() ?? false;

                if($user) {
                    $user->name = $_r->input('name');
                    $user->email = $_r->input('email');
                    $user->group_id = $_r->input('group_id');
                    $user->organisation_id = $_r->input('organisation_id');

                    if($user->save()) {
                        return response()->json(['detail' => 'User updated'], 200);
                    }
                }

            }
            else { // Bad input
                return response()->json(['detail' => 'Invalid Payload'], 400);
            }

        }
        catch(Throwable $ex) {
            Log::debug($ex);
        }

        return response()->json(['detail' => 'Server Error'], 500);
    }

    public function delete_user(Request $_r, $_user_id) {
        try {
            $valid_request = !Validator::make([ 'id' => $_user_id ], [
                'id' => ['required', new AdminAnyUserIdentity],
            ])->fails();

            if($valid_request && $_user_id != Auth::user()->id && User::find($_user_id)->delete()) {
                return response()->json(['detail' => 'User deleted'], 200);
            }
        }
        catch(Throwable $ex) {}

        return response()->json(['detail' => 'Error deleting user'], 500);
    }

    public function reset_user_mfa(Request $_r, int $_user_id) {
        try {
            $valid_request = !Validator::make([ 'id' => $_user_id ], [
                'id' => ['required', new AdminAnyUserIdentity],
            ])->fails();

            if($valid_request) {

                $user = User::find($_user_id);

                $user->totp_secret = null;
                $user->totp_confirmed_at = null;
                $user->totp_last_slice = null;
                $user->save();

                SecurityEvent::create([
                    'user_id'       => Auth::user()->id,
                    'ip'            => Security::real_ip(),
                    'user_agent'    => $_r->userAgent(),
                    'route'         => $_r->path(),
                    'payload'       => json_encode([ 'target_user_id' => $user->id ]),
                    'description'   => 'MFA reset for user',
                ]);

                return response()->json(['detail' => 'MFA reset'], 200);
            }

            return response()->json(['detail' => 'Invalid Payload'], 400);
        }
        catch(Throwable $ex) {
            Log::debug($ex);
        }

        return response()->json(['detail' => 'Server Error'], 500);
    }

}


