<?php

namespace App\Http\Controllers\Users;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;

use GuzzleHttp\Client;
use Illuminate\Support\Facades\Storage;
use Log;
use DB;
use Exception;
use Carbon\Carbon;

use App\Models\User;
use App\Helpers\GaClient;

class UsersController extends Controller
{

    const DEFAULT_PER_PAGE = 10;

    public function __construct()
    {
        
    }

    private function buildSearch($data, Request $request)
    {
        $data = $data->where('name', 'like', '%'.$request->search.'%')
                ->orWhere('email', 'like', '%'.$request->search.'%');

        return $data;
    }
    
    public function index(Request $request)
    {
        try {
            validation($request, [
                'page' => 'required|numeric',
                'perPage' => 'required|numeric',
                'search' => regexValidString()
            ]);
        } catch (ValidationException $e) {
            Log::error('UsersController - index - validasi : '. json_encode($e->validator->errors()));
            return response()->json([
                'status' => false,
                'message' => 'Failed validation',
                'errors' => $e->validator->errors()
            ], 422);
        }

        try {

            $perPage = self::DEFAULT_PER_PAGE;
            
            $user = User::whereNull('deleted_at');
            
            if ($request->has('perPage')) {
                $perPage = $request->perPage;
            }
            if ($request->has('search')) {
                $user = $this->buildSearch($user, $request);
            }

            $user = $user->paginate($perPage);
            
            return response()->json([
                'status' => true,
                'message' => 'Berhasil mengambil data',
                'data' => $user
            ], 200);

        } catch (Exception $e) {
            Log::error('UsersController - index : '. $e->getMessage());
            return response()->json([
                'status' => false,
                'message' => 'Gagal menghubungkan ke server'
            ], 500);
        }
    }

    public function detail(Request $request, $id)
    {
        try {
            $request->merge([
                'id' => $id
            ]);

            validation($request, [
                'id' => 'required|numeric|exists:users,id'
            ]);
        } catch (ValidationException $e) {
            Log::error('UsersController - detail - validasi : '. json_encode($e->validator->errors()));
            return response()->json([
                'status' => false,
                'message' => 'Failed validation',
                'errors' => $e->validator->errors()
            ], 422);
        }

        try {

            $user = User::whereNull('deleted_at')->find($id);

            if (empty($user)) {
                return response()->json([
                    'status' => false,
                    'message' => 'Data tidak ditemukan',
                    'data' => []
                ], 400);    
            }
            
            return response()->json([
                'status' => true,
                'message' => 'Berhasil mengambil data',
                'data' => $user
            ], 200);

        } catch (Exception $e) {
            Log::error('UsersController - index : '. $e->getMessage());
            return response()->json([
                'status' => false,
                'message' => 'Gagal menghubungkan ke server'
            ], 500);
        }
    }

    public function store(Request $request, GaClient $GaClient)
    {
        try {
            validation($request, [
                'name' => 'required|'.regexValidString(),
                'email' => 'required|email',
                'is_active' => 'required|numeric|in:0,1'
            ]);
        } catch (ValidationException $e) {
            Log::error('UsersController - store - validasi : '. json_encode($e->validator->errors()));
            return response()->json([
                'status' => false,
                'message' => 'Failed validation',
                'errors' => $e->validator->errors()
            ], 422);
        }

        DB::beginTransaction();
        try {

            $user = User::where('email', $request->email)->first();
            
            if (!empty($user)) {
                return response()->json([
                    'status' => false,
                    'message' => 'Email sudah terdaftar',
                    'data' => []
                ], 400);    
            }
            
            $password = Str::random(10);
            $hashedPassword = Hash::make($password);

            $newUser = User::create([
                'name' => $request->name,
                'email' => $request->email,
                'password' => $hashedPassword,
                'role' => 'admin',
                'is_active' => $request->is_active
            ]);

            // SEND EMAIL
            $to = $request->email;
            $subject = 'Konfirmasi Akun PGN Register Backoffice';
            $body = '';

            $year = date("Y");

            $data = [
                'pgn_register_backoffice_url' => env('PGN_REGISTER_BACKOFFICE_URL', ''),
                'email' => $request->email,
                'password' => $password
            ];
            $html = view('mail.create_user_email', [
                'data' => $data,
                'year' => $year,
            ])->render();

            $body = $html;

            $response_ga = $GaClient->sendEmail($to, $subject, $body, []);

            if ($response_ga) {

                DB::commit();
                return response()->json([
                    'status' => true,
                    'message' => 'Berhasil membuat data user',
                    'data' => []
                ], 200);    
            }
            // END SEND EMAIL

            DB::rollBack();
            return response()->json([
                'status' => true,
                'message' => 'Gagal membuat data user, silakan coba beberapa saat lagi',
                'data' => []
            ], 400);

        } catch (Exception $e) {
            DB::rollBack();

            Log::error('UsersController - store : '. $e->getMessage());
            return response()->json([
                'status' => false,
                'message' => 'Gagal menghubungkan ke server'
            ], 500);
        }
    }

    public function update(Request $request)
    {
        try {
            validation($request, [
                'id' => [
                    'required',
                    'numeric',
                    Rule::exists('users')->where(function ($query) {
                        $query->where('deleted_at', null);
                    }),
                ],
                'name' => 'required|'.regexValidString(),
                'email' => 'required|email',
                'name_old' => 'required|'.regexValidString(),
                'email_old' => 'required|email',
                'is_active' => 'required|numeric|in:0,1'
            ]);
        } catch (ValidationException $e) {
            Log::error('UsersController - update - validasi : '. json_encode($e->validator->errors()));
            return response()->json([
                'status' => false,
                'message' => 'Failed validation',
                'errors' => $e->validator->errors()
            ], 422);
        }

        DB::beginTransaction();
        try {

            $user = User::find($request->id);

            if (($user->email != $request->email_old) && ($user->name != $request->name_old)) {
                return response()->json([
                    'status' => false,
                    'message' => 'Data tidak ditemukan',
                    'data' => []
                ], 400);
            }
            
            $user->update([
                'name' => $request->name,
                'email' => $request->email,
                'is_active' => $request->is_active
            ]);

            DB::commit();

            return response()->json([
                'status' => true,
                'message' => 'Berhasil mengubah data user',
                'data' => []
            ], 200);

        } catch (Exception $e) {
            DB::rollBack();

            Log::error('UsersController - update : '. $e->getMessage());
            return response()->json([
                'status' => false,
                'message' => 'Gagal menghubungkan ke server'
            ], 500);
        }
    }

    public function destroy(Request $request)
    {
        try {
            validation($request, [
                'id' => [
                    'required',
                    'numeric',
                    Rule::exists('users')->where(function ($query) {
                        $query->where('deleted_at', null);
                    }),
                ],
                'name' => 'required|'.regexValidString(),
                'email' => 'required|email'
            ]);
        } catch (ValidationException $e) {
            Log::error('UsersController - destroy - validasi : '. json_encode($e->validator->errors()));
            return response()->json([
                'status' => false,
                'message' => 'Failed validation',
                'errors' => $e->validator->errors()
            ], 422);
        }

        DB::beginTransaction();
        try {

            $user = User::where([
                'id' => $request->id,
                'name' => $request->name,
                'email' => $request->email
            ])
            ->first();

            if (empty($user)) {
                return response()->json([
                    'status' => false,
                    'message' => 'Data tidak ditemukan',
                    'data' => []
                ], 400);
            }
            
            $user->delete();

            DB::commit();

            return response()->json([
                'status' => true,
                'message' => 'Berhasil menghapus data user',
                'data' => []
            ], 200);

        } catch (Exception $e) {
            DB::rollBack();

            Log::error('UsersController - destroy : '. $e->getMessage());
            return response()->json([
                'status' => false,
                'message' => 'Gagal menghubungkan ke server'
            ], 500);
        }
    }

    public function changePassword(Request $request)
    {
        try {
            validation($request, [
                'old_password' => 'required|'.regexValidBase64(),
                'new_password' => 'required|'.regexValidBase64(),
                'confirm_password' => 'required|'.regexValidBase64()
            ]);
        } catch (ValidationException $e) {
            Log::error('UsersController - changePassword - validasi : '. json_encode($e->validator->errors()));
            return response()->json([
                'status' => false,
                'message' => 'Failed validation',
                'errors' => $e->validator->errors()
            ], 422);
        }

        DB::beginTransaction();
        try {

            if (base64_encode(base64_decode($request->old_password, true)) !== $request->old_password) {
                return response()->json([
                    'status' => false,
                    'message' => 'Isian Old Password tidak valid'
                ], 422);
            }
            if (base64_encode(base64_decode($request->new_password, true)) !== $request->new_password) {
                return response()->json([
                    'status' => false,
                    'message' => 'Isian New Password tidak valid'
                ], 422);
            }
            if (base64_encode(base64_decode($request->confirm_password, true)) !== $request->confirm_password) {
                return response()->json([
                    'status' => false,
                    'message' => 'Isian Confirm Password tidak valid'
                ], 422);
            }

            $User = Auth::user();

            if (!Hash::check($request->old_password, $User->password)) {
                return response()->json([
                    'status' => false,
                    'message' => 'Old Password tidak sesuai',
                    'data' => []
                ], 400);
            }

            if ($request->new_password != $request->confirm_password) {
                return response()->json([
                    'status' => false,
                    'message' => 'New Password dan Confirm Password tidak sesuai',
                    'data' => []
                ], 400);
            }

            $user = User::find($User->id);
            
            if (empty($user)) {
                return response()->json([
                    'status' => false,
                    'message' => 'Data tidak ditemukan',
                    'data' => []
                ], 400);
            }

            $user->update([
                'password' => Hash::make($request->new_password)
            ]);

            DB::commit();

            return response()->json([
                'status' => true,
                'message' => 'Berhasil mengubah password',
                'data' => []
            ], 200);

        } catch (Exception $e) {
            DB::rollBack();
            
            Log::error('UsersController - changePassword : '. $e->getMessage());
            return response()->json([
                'status' => false,
                'message' => 'Gagal menghubungkan ke server'
            ], 500);
        }
    }
}
