<?php

namespace App\Http\Controllers;

use App\Jobs\PasswordResetJob;
use App\Mail\PasswordReset;
use App\Models\Forecast;
use App\Models\Helpers\General;
use App\Models\Payment;
use App\Models\Subscriber;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;

class AuthController extends Controller
{

    public function __construct()
    {
        return $this->middleware('auth')->except([
            'showLoginPage', 'mainLogin', 'logout',
            'password_reset_page',
            'password_reset',
            'password_change_page',
            'password_change'
        ]);
    }

    public function showLoginPage()
    {
        return view('auth.login');
    }

    public function dashboard()
    {
        $incoming_forecast = Forecast::query()
            ->where('schedule', '>=', now()->toDateString())->count();
        // $incoming_forecast = 20;

        $past_forecast = Forecast::query()
            ->where('schedule', '<', now()->toDateString())->count();

        $success_payments = Payment::query()->where('status', 'success')->count();
        $failed_payments = Payment::query()->where('status', 'failed')->count();
        $picked_payments = Payment::query()->where('status', 'picked')->count();

        $total_users = User::all()->count();
        $total_payments = Payment::query()->where('status', 'success')->sum('amount');

        return view('admin.index', compact(
            'incoming_forecast',
            'past_forecast',
            'success_payments',
            'failed_payments',
            'picked_payments',
            'total_payments',
            'total_users'
        ));
    }

    public function mainLogin(Request $request)
    {
        $request->validate([
            'password'  => 'required',
            'email'     =>  'required|email'
        ]);

        $credential = [
            'email'     => $request->email,
            'password'  => $request->password
        ];

        if (auth()->attempt($credential)) {
            Session::forget('failed_email');
            Session::forget('failed_password');
            return redirect()->route('admin.dashboard');
        } else {
            General::logError('USER LOGIN', 'Invalid user credential', 'mainLogin in AuthController');
            Session::put('failed_email', $request->email);
            Session::put('failed_password', $request->password);
            return back()->with('error', 'Invalid email or password');
        }
    }

    public function logout()
    {
        if (Auth::user()) {
            Auth::logout();
            return redirect()->route('login');
        } else {
            return back()->with('error', 'Logout attempt failed');
        }
    }

    public function password_reset_page()
    {
        return view('auth.password_reset');
    }

    public function password_reset(Request $request)
    {
        General::logError('PASSWORD RESET ATTEMPT', json_encode($request->all()), 'password_reset in AuthController');

        $request->validate([
            'email' => 'required|email'
        ]);

        Session::put('reset_email', $request->email);

        $user = User::query()->where('email', $request->email)->first() ?? null;

        if ($user !== null) {
            //Dispatch password reset job by sending email
            $my_token = Str::random(30);

            try {
                DB::table('password_reset_tokens')->insert([
                    'email' => $request->email,
                    'token' => $my_token,
                    'created_at' => now(),
                ]);

                $url = route('password.change.page', ['token' => $my_token]);

                // PasswordResetJob::dispatch($user, $url);
                Mail::send(new PasswordReset($user, $url));

                return back()->with('success', 'Password reset link has been sent to the email you provided');
            } catch (\Throwable $th) {
                General::logError(
                    'INSERTING PASSWORD TOKEN INTO password_reset_tokens table',
                    $th->getMessage(),
                    'password_reset in AuthController'
                );

                return back()->with('error', 'We encountered an issue which is not your fault.');
            }
        } else {
            return back()->with('error', 'The email you provided is not associated with any user');
        }
    }

    public function password_change_page($token)
    {
        return view('auth.password_change', compact('token'));
    }

    public function password_change(Request $request)
    {
        General::logError('PASSWORD CHANGE', json_encode($request->all()), 'password_change in AuthController');
        Log::info($request->token);
        $request->validate([
            'new_password' => 'required|string',
            'confirmation_password' => 'required|string'
        ]);

        if ($request->new_password === $request->confirmation_password) {
            $user_check = DB::table('password_reset_tokens')
                ->where('token', $request->token)->first() ?? null;
            if ($user_check !== null) {
                $user = User::query()->where('email', $user_check->email)->first() ?? null;
                if ($user !== null) {
                    $user->update([
                        'password' => Hash::make($request->new_password)
                    ]);

                    DB::table('password_reset_tokens')
                        ->where('email', $user_check->email)
                        ->where('token', $request->token)
                        ->delete();

                    return back()->with('success', 'Password for ' . $user->email . ' has been changed successfully');
                } else {
                    return back()->with('error', 'Sorry, your user information cannot be retrieved');
                }
            } else {
                General::logError('AN ATTEMPT TO CHANGE PASSWORD', 'No associated token exists in the password_reset_tokens table', 'password_change in AuthController');
                return back()->with('error', 'Token has expired');
            }
        } else {
            return back()->with('error', 'The two passwords do not match');
        }
    }

    public function admin_password_page()
    {
        return view('admin.change_password');
    }

    public function admin_password_change(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'old_password' => 'required|string',
            'new_password' => 'required|string',
            'password_confirmation' => 'required|string'
        ]);

        if ($validator->fails()) {
            return back()->withErrors($validator->errors()->all());
        } else {
            $old_password = $request->old_password;
            $new_password = $request->new_password;
            $password_confirmation = $request->password_confirmation;

            $current_password = auth()->user()->password;

            if (Hash::check($old_password, $current_password)) {
                if ($new_password == $password_confirmation) {
                    $user = User::find(auth()->user()->id) ?? null;
                    if ($user !== null) {
                        $user->update([
                            'password' => Hash::make($new_password)
                        ]);
                        return back()->with('success', 'Your password has been changed successfully');
                    } else {
                        return back()->with('error', 'Your account cannot be found');
                    }
                } else {
                    return back()->with('error', 'New password and password confirmation do not match');
                }
            } else {
                return back()->with('error', 'Old password is incorrect');
            }
        }
    }
}
