<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreClientRequest;
use App\Http\Requests\StoreContractRequest;
use App\Http\Requests\StoreUserRequest;
use App\Http\Requests\UpdateClientRequest;
use App\Http\Requests\UpdateContractRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Mail\IPRSRegisterUser;
use App\Models\Client;
use App\Models\Contract;
use App\Models\IprsNewServiceGroup;
use App\Models\Onboarding;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Illuminate\Contracts\Auth\PasswordBroker;

class OnboardingController extends Controller
{
    protected PasswordBroker $passwordBroker;
    public function __construct(PasswordBroker $passwordBroker)
    {
        $this->passwordBroker = $passwordBroker;
    }

    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        $onboarding = Onboarding::all();
        return view('multistep.onboarding-list', ['onboarded' => $onboarding]);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        $contractPermissions = Permission::where("permission_type", "Contract")->get();
        $users = User::with('contract.client')->get();
        $roles = Role::all();
        session(['onboarding-id' => null]);
        //$onboard = Onboarding::find($obid);

        return view('multistep.onboarding', [
            'contractPermissions' => $contractPermissions,
            'users' => $users,
            'roles' => $roles,
            'onboard' => null,
        ]);
    }

    /**
     * Store a newly created resource in storage.
     * @throws \Exception
     */
    public function store(Request $request)
    {
        // check form step i.e. client, contract or user
        switch ($request->step) {
            case "client" :
                // store the step in session: 1-client, 2-contract, 3-user
                // save and retain the same page
                $step = 1; // if saved only
                // submit and move step to contract
                if ($request->has('submit')) {
                    $step = 2;
                }

                // include this column not passed from ui
                $validated['CREATED_BY'] = auth()->user()->name;
                $validated['MODIFIED_BY'] = auth()->user()->name;

                // Store the client data
                if ($request->filled('record')) {
                    // validate the form
                    $contractRequest = new UpdateClientRequest();
                    $validated = $request->validate($contractRequest->rules());
                    $client = Client::query()->find($request->record);
                    $client->update([
                        'NAME_SH' => $validated['NAME_SH'],
                        'NAME_FL' => $validated['NAME_FL'],
                        'ADDRESS' => $validated['ADDRESS'],
                        //'BANK_ACC' => $validated['BANK_ACC'],
                        'BOSS_SURN' => $validated['BOSS_SURN'],
                        'BOSS_NAME' => $validated['BOSS_NAME'],
                        'BOSS_OTHNAME' => $validated['BOSS_OTHNAME'],
                        'BOSS_POST' => $validated['BOSS_POST'],
                        'BOSS_PHONE' => $validated['BOSS_PHONE'],
                        'BOSS_CELL' => $validated['BOSS_CELL'],
                        'BOSS_EMAIL' => $validated['BOSS_EMAIL'],
                        'ACC_SURN' => $validated['ACC_SURN'],
                        'ACC_NAME' => $validated['ACC_NAME'],
                        'ACC_OTHNAME' => $validated['ACC_OTHNAME'],
                        'ACC_POST' => $validated['ACC_POST'],
                        'ACC_PHONE' => $validated['ACC_PHONE'],
                        'ACC_CELL' => $validated['ACC_CELL'],
                        'ACC_EMAIL' => $validated['ACC_EMAIL'],
                        'STATUS_CL' => $validated['STATUS_CL'],
                        //'MODIFIED_BY' => $validated['MODIFIED_BY']
                    ]);
                }else{
                    // validate the form
                    $contractRequest = new StoreClientRequest();
                    $validated = $request->validate($contractRequest->rules());
                    $client = Client::create($validated);
                }

                // get the client id and create the record to onboarding table
                $ob = Onboarding::firstOrNew(['id' => request('obid')]);
                $ob->CLIENT_RID = $client->RID ?? $client->rid;
                $ob->STEP = $step;
                $ob->save();

                // store the onboarding id on session to be used by the next cases
                session(['onboarding-id' => $ob->id]);
                return redirect()->route('onboarding.edit', $ob->id)->with("success", "Client saved successfully!");
            case "contract" :
                // store the step in session: 0-client, 1-contract, 2-user
                // save and retain the same page
                $step = 2;
                // submit and move steps to user
                if ($request->has('submit')) {
                    $step = 3;
                }

                // store contract data
                if ($request->filled('record')) {
                    // validate the form
                    $contractRequest = new UpdateContractRequest();
                    $validated = $request->validate($contractRequest->rules());
                    $contract = Contract::query()->find($request->record);
                    $payment_type = match ($validated['payment_type'] ?? '') {
                        "Post-paid" => 1,
                        "Pre-paid" => 2,
                        "Free" => 3,
                        default => 0
                    };
                    $contract->update([
                        'CLIENT_RID' => $validated['client_id'],
                        'D_DOC' => $validated['issue_date'],
                        'D_BGN' => $validated['begin_date'],
                        'D_END' => $validated['expire_date'],
                        'MANAGER_SURN' => $validated['surname'],
                        'MANAGER_NAME' => $validated['name'],
                        'MANAGER_OTHNAM' => $validated['other_name'],
                        'MANAGER_POST' => $validated['post'],
                        'MANAGER_PHONE' => $validated['phone'],
                        'MANAGER_CELL' => $validated['cell'],
                        'MANAGER_EMAIL' => $validated['email'],
                        'IN_USE' => $validated['in_use'],
                        'PAYMENT_TYPE' => $payment_type,
                        'POSTED_BY_INTERNET' => ($request->filled("internet") && $validated['internet'] == "on") ? 1 : 0,
                        //'POSTED_BY_EMAIL' => $validated[''],
                        //'POSTED_BY_SMS' => $validated[''],
                        'POSTED_BY_SERVICE' => ($request->filled("api") && $validated['api'] == "on") ? 1 : 0,
                    ]);
                    $cid = $contract->rid ?? $contract['RID'];
                    //get RID
                    $contract_role='CID-'.$cid;
                    $servicePerm=$request['permissions'];
                    //create role
                    $role = Role::firstOrCreate(['name' => $contract_role],['for_contract' => true]);
                    //assign permissions
                    $role->syncPermissions($servicePerm);
                }else{
                    // validate the form
                    $contractRequest = new StoreContractRequest();
                    $validated = $request->validate($contractRequest->rules());
                    $payment_type = match ($validated['payment_type'] ?? '') {
                        "Post-paid" => 1,
                        "Pre-paid" => 2,
                        "Free" => 3,
                        default => 0
                    };
                    $contract = Contract::create([
                        'CLIENT_RID' => $validated['client_id'],
                        'D_DOC' => $validated['issue_date'],
                        'D_BGN' => $validated['begin_date'],
                        'D_END' => $validated['expire_date'],
                        'MANAGER_SURN' => $validated['surname'],
                        'MANAGER_NAME' => $validated['name'],
                        'MANAGER_OTHNAM' => $validated['other_name'],
                        'MANAGER_POST' => $validated['post'],
                        'MANAGER_PHONE' => $validated['phone'],
                        'MANAGER_CELL' => $validated['cell'],
                        'MANAGER_EMAIL' => $validated['email'],
                        'IN_USE' => $validated['in_use'],
                        'PAYMENT_TYPE' => $payment_type,
                        'POSTED_BY_INTERNET' => ($request->filled("internet") && $validated['internet'] == "on") ? 1 : 0,
                        //'POSTED_BY_EMAIL' => $validated[''],
                        //'POSTED_BY_SMS' => $validated[''],
                        'POSTED_BY_SERVICE' => ($request->filled("api") && $validated['api'] == "on") ? 1 : 0,
                    ]);
                    //get RID
                    $contract_role='CID-'.$contract['RID'];
                    $servicePerm=$request['permissions'];
                    //create role
                    $role = Role::create(['name' => $contract_role, 'for_contract' => true]);
                    //assign permissions
                    $role->syncPermissions($servicePerm);
                }

                // get the contract id and create the record to onboarding table
                $ob = Onboarding::firstOrNew(['id' => request('obid')]);
                $ob->CONTRACT_RID = $contract->RID ?? $contract->rid;
                $ob->STEP = $step;
                $ob->save();

                // store the onboarding id on session to be used by the next cases
                session(['onboarding-id' => $ob->id]);
                return redirect()->route('onboarding.edit', $ob->id)->with("success", "Contract saved successfully!");
            case "user" :
                // store the user data
                $plainPassword = $validated['password'] ?? Str::random(8);
                if ($request->filled('record')) {
                    $userRequest = new UpdateUserRequest();
                    $validated = $request->validate($userRequest->rules());
                    $user = User::query()->find($request->record);
                    $user->update([
                        'contract_rid' => $validated['contract_id'],
                        'name' => $validated['name'],
                        'email' => $validated['email'],
                        'password' => bcrypt($plainPassword),
                        'status_l' => $validated['status']
                    ]);
                }else{
                    $userRequest = new StoreUserRequest();
                    $validated = $request->validate($userRequest->rules());
                    $plainPassword = $validated['password'] ?? Str::random(8);
                    $user = User::create([
                        'contract_rid' => $validated['contract_id'],
                        'name' => $validated['name'],
                        'email' => $validated['email'],
                        'password' => bcrypt($plainPassword),
                        'status_l' => $validated['status']
                    ]);
                }

                $step = 3;
                // submit and move steps to client
                if ($request->has('submit')) {
                    $step = 4;
                }

                // add client role to user by default

                $validated['role'][] = 'client';

                $user->syncRoles($validated['role']);

                // get the contract id and create the record to onboarding table
                $ob = Onboarding::firstOrNew(['id' => request('obid')]);
                $ob->user_id = $user->id ?? $user->ID;
                $ob->STEP = $step;
                $ob->save();

                //get a token
                $resetToken= $this->passwordBroker->createToken($user);
                //generate link
                //$resetUrl = url('/password/reset/'.$resetToken.'?email='.$user['email']);
                $resetUrl='';
                //mail with custom template
                Mail::to($user['email'])->send(new IPRSRegisterUser($user,$plainPassword,$resetUrl));
                // save and retain the same page
                return redirect()->route('onboarding.edit',$ob->id)->with("success", "User saved successfully!");
            case "review":
                // store the onboarding id on session to be used by the next cases
                session(['onboarding-id' => '']);

                // get the contract id and create the record to onboarding table
                $ob = Onboarding::firstOrNew(['id' => request('obid')]);
                $ob->STEP = 1;
                $ob->save();

                // submit and move steps
                if ($request->has('submit')) {
                    return redirect()->route('onboarding.index')->with("success", "On-boarded successfully!");
                }

                break;
            default:
                throw new \Exception('Unexpected On-boarding Step');
        }
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id)
    {
        $onboarded = Onboarding::find($id);
        $contracts = Contract::query()->where('CLIENT_RID', $onboarded->client_rid)->get();
        return view('multistep.onboarding-show', [
            'onboard' => $onboarded,
            'client' => $onboarded->client ?? null,
            'contracts' => $contracts ?? [],
        ]);
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(string $id)
    {
        $contractPermissions = Permission::where("permission_type", "Contract")->get();
        $users = User::with('contract.client')->get();;
        $roles = Role::where('for_iprs_admins', false)->get();
        session(['onboarding-id' => $id]);
        $onboard = Onboarding::find($id);

        return view('multistep.onboarding-edit', [
            'contractPermissions' => $contractPermissions,
            'users' => $users,
            'roles' => $roles,
            'onboard' => $onboard ?? null,
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        //
    }
}
