<?php /** @noinspection ALL */

/** @noinspection PhpUndefinedClassInspection */

namespace App\Http\Controllers\Client;

use App\AdminAccessRight;
use App\Company;
use App\CompanyDirector;
use App\CompanyStatus;
use App\Models\WhitelistedIps;
use App\Role;
use App\TmpRegistration;
use App\Tools\SmsTools;
use App\User;
use App\UserSenderId;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;

class CompanyController extends Controller
{

    public function create(Request $request,$tmpcode = null)
    {
        $tmp_user = null;

        if(!empty($tmpcode))
        {
            $route = route('register.company.tmp',$tmpcode);
            $tmp_user = TmpRegistration::query()
                ->where('tmp_url',$route)->first();

            if(empty($tmp_user))
                return  abort(401);
        }

        if($request->isMethod('Post')):


            $this->validate($request,[

                'name' =>'required|unique:companies',
                //'date_of_incorporation' =>'required',
                'legal_status' =>'required',
                'mobile_money_number' =>'required|digits_between:10,12',
                'company_phone_number' =>'required|digits_between:10,12',
                'business_document' =>'nullable',
                'nature_of_business' =>'required',
                'sender_id_document' =>'nullable',
                'contact_person' =>'required',
                'contact_person_id' =>'required',
                'contact_person_designation' =>'required',
                'contact_person_phone' => 'required|unique:companies|digits_between:10,12',
                'contact_person_email' => 'required|email|unique:companies',
                'contact_person_email' => 'required|email|unique:users,email',
                'contact_person_email' =>'required|email',

            ]);



            $records = $request->all();
            $sendor_ids   = json_decode($records['sender_ids'] ?? '', true);
            $directors   =  json_decode($records['items'] ?? '' , true);

//             if($sendor_ids == null)
// //            if($sendor_ids == null  || $directors == null)
//                 redirect()->back()->withErrors('All Fields Are Required');

            /** Validation on minimum of two company directors **/
            /** Comment Out company directors **/
//            if(count($directors) < 1)
//                return redirect()->back()->withInput(Input::all())->withErrors('Company directors field should have a Minimum of one director');


            $records['nature_of_business'] = empty($request->input('nature_of_business')) ? 'N/A' : $request->input('nature_of_business');
            $records['location_in_other_countries'] = empty($request->input('location_in_other_countries')) ? 'N/A' : $request->input('location_in_other_countries');
            $records['physical_address'] = empty($request->input('physical_address')) ? 'N/A' : $request->input('physical_address');
            $records['postal_address'] = empty($request->input('postal_address')) ? 'N/A' : $request->input('postal_address');


            $result = $this->generateUserInfo($request);
            $result['created_by'] = 'messenger';
            $result['must_change_password'] = true;


            DB::beginTransaction();


                $user = User::query()->create($result);

                if ($user):

                    $records['user_id'] = $user->id;

                    $user->credit()->create([
                        'username' => $user->username,
                        'price' => '0.03',
                        'email_price' => '0.00332',
                        'credit_alloted' => '3.00',
                        'old_bal' => '0',
                        'new_bal' => '3.00',
                        'credit_used' => '0',
                        'credited' => '0'
                    ]);

                    $output = $this->saveFiles($request);

                    $company = Company::query()->create($records);

                    $company->putToTrialMode($records); //put to trial mode

                    $company->update($output);


                    if ($company):
                        //update user table with company table
                        $user->update(['company_id' => $company->id]);
                        //then we save the sender Id here
                        $this->saveSenderId($sendor_ids, $user);
                        // we save the company's director here
                        $this->saveDirectors($directors ?? [], $company);

                        $status = $this->setStatus($company);
                        $company->update($status);

                        $data['email'] = $user->email;

                        $data['name'] = $user->full_name;

                        $data['code'] = $status['code'];


                        try {
                            /** @noinspection PhpUndefinedClassInspection */
                            Mail::send('emails.admin_login', $data, function ($m) use ($data) {
                                $m->from('mtn@messenger.com', 'MESSENGER');
                                $m->to($data['email'], $data['name']);
                                $m->subject('Company Registration');
                            });
                        } catch (\Exception $e) {
                        }


                        $adminEmail = AdminAccessRight::query()->where('value', 2)->get();

                        $emails = array();

                        foreach ($adminEmail as $mail):
                            $search = User::query()->find($mail->user_id);
                            if ($search):
                                array_push($emails, $search->email);
                            endif;
                        endforeach;


                        if (!empty($emails)):
                            try {
                                Mail::send('emails.admin_login', $emails, function ($m) use (&$emails) {
                                    $m->from('mtn@messenger.com', 'MESSENGER');
                                    $m->to($emails);
                                    $m->cc('dorothy.sarpong@mtn.com');
                                    $m->cc('Benedict.bentil@mtn.com');
                                    $m->cc('Peter.anani@mtn.com');
                                    $m->cc('support@npontu.com');
                                    $m->cc('Josephine.asante@mtn.com');
                                    $m->cc('Maame.simpson@mtn.com');
                                    $m->subject('New Company Registration');
                                });
                            } catch (\Exception $ex) {
                            }

                        endif;


                        $msg = "Hello {$company->name},
Thank you for registering for the MTN Business Messenger. 
Your account will be verified and created within 2 working days.
Request ID is {$status['code']}. 
Thank you.";
                        $this->sendSms($msg, $company->users->phone_number);
                        $tmp_user ? $tmp_user->isRegistered() : null;


                    endif;
                endif;


                DB::commit();

            $flash = "Hello {$company->name}, thank you for registering for the MTN Business Messenger. Your account will be verified and created within 2 working days. Request ID is {$status['code']}. Thank you.";
            return redirect()->route($result['url'])->with('success',$flash);


        endif;


        return view('layouts.register',compact('tmp_user'));

    }


    public function  edit(Request $request,$id)
    {
        $company = Company::query()->find($id);
        $sends = json_encode(UserSenderId::query()->where('user_id',$company->users->id)->select('id','sender_id as name')->get()->toArray());
        $dirs = json_encode($company->directors()->select('id','name','designation')->get()->toArray());

        if($request->isMethod('Post')):

            $this->validate($request,[
                'name' =>'required|unique:companies,name,'.$id,
                //'date_of_incorporation' =>'required',
                'legal_status' =>'required',
                'mobile_money_number' =>'required|digits_between:10,20',
                'company_phone_number' =>'required|digits_between:10,20',
                'contact_person' =>'required',
                'contact_person_designation' =>'required',
                'contact_person_phone' =>'required|digits_between:10,20',
                'contact_person_email' =>'required',
            ]);


            $contains = Str::contains($request->input('contact_person_email'), ['@']);

            if(!$contains)
                return redirect()->back()->withInput(Input::all())->withErrors('This is not a valid email');

            $verify = User::query()->where('email',$request->input('contact_person_email'))->first();

            if($verify && $company->users->email != $verify->email)
                return redirect()->back()->withInput(Input::all())->withErrors('the email '.$request->input('contact_person_email') .' has already been taken');

            $records = $request->all();



            $sender_ids   = json_decode($records['sender_ids'], true);
            $directors   = json_decode($records['items'] ?? '', true);
//            if($sender_ids == null  || $directors == null)
            if($sender_ids == null)
                redirect()->back()->withErrors('All Fields Are Required');

            /** Validation check on company directors **/
            /** Comment Out company directors validation **/
//            if(count($directors) < 1)
//                return redirect()->back()->withInput(Input::all())->withErrors('Company directors field should have a Minimum of one director');


            $records['nature_of_business'] = empty($request->input('nature_of_business')) ? 'N/A' : $request->input('nature_of_business');
            $records['location_in_other_countries'] = empty($request->input('location_in_other_countries')) ? 'N/A' : $request->input('location_in_other_countries');
            $records['physical_address'] = empty($request->input('physical_address')) ? 'N/A' : $request->input('physical_address');
            $records['postal_address'] = empty($request->input('postal_address')) ? 'N/A' : $request->input('postal_address');

            $result = $this->editUserInfo($request);


            DB::beginTransaction();

            if (!empty($company->users))
                $user   = $company->users->update($result);

            $company->update($records);

            //update uploaded files
            $output = $this->editSavedFiles($request,$company);
            if(!empty($output))
                $company->update($output);
            //then we edit the sender Id here
            if (!empty($user))
                $this->editSavedSenderId($sender_ids);
            // we edit the company's director here
            $this->editSavedDirectors($directors ?? []);

            DB::commit();

            return redirect()->route('admin.root.company')->with('success','Company Successfully Updated');

        endif;

        return view('admin.root.edit',compact('company','sends','dirs'));

    }

    private function verifyUsername($string)
    {
        $length = 2;
        $query = User::query()->where('username',$string)->first();
        //if query returns true that means we ought to regenerate the user the name.

        //while $query remains true
        while($query):
            $random = substr(str_shuffle(str_repeat($x='0123456789',ceil($length/strlen($x)))),1,$length);
            $string = $string.$random;
            break;
        endwhile;

        return $string;
    }

    private function generateUserInfo(Request $request)
    {
        $inputs['phone_number'] = SmsTools::format_gh_number($request->input('company_phone_number'));
        $inputs['full_name'] = $request->input('name');
        $words = explode(" ", trim($request->input('name')));
        $acronym = "";
        foreach ($words as $w) {
            if($w && isset($w[0]) && !empty($w[0]))
                $acronym .= $w[0];
        }

        $demo = strtolower($acronym.$words[0]);
        $password = substr(hash('sha512',rand()),0,6);
        $username =  $this->verifyUsername($demo);

        $inputs['username'] = $username;
        $inputs['organisation'] = $request->input('name');;
        $inputs['email'] = $request->input('contact_person_email');
        $inputs['role_id'] = Role::where('name', $request->input('register_as'))->first()->id;
        $inputs['password'] = bcrypt($password);
        $inputs['website_url'] = !empty($request->input('website_url')) ? $request->input('website_url') : null;
        $inputs['status'] = 'active';
        $inputs['location'] = empty($request->input('physical_address')) ? 'N/A' : $request->input('physical_address');
        $inputs['pass'] = $password;

        if( $inputs['role_id'] == 2)
        {
            $inputs['url']  = 'login';

        }
        else if( $inputs['role_id'] == 3){
            $inputs['url']  = 'reseller.login';
        }

        return $inputs;
    }

    private function saveFiles(Request $request)
    {
        if($request->hasFile('business_document')){
            $bc = $request->file('business_document');
            $records['business_document'] = date('Y-m-d h:i:s').'_'.$bc->getClientOriginalName();
            $bc->storePubliclyAs('public/business_doc', $records['business_document']);
        }
        else{
            $records['business_document'] = null;
        }

        if($request->hasFile('sender_id_document')){
            $sendID = $request->file('sender_id_document');
            $records['sender_id_document'] = date('Y-m-d h:i:s').'_'.$sendID->getClientOriginalName();
            $sendID->storePubliclyAs('public/sender_docs', $records['sender_id_document']);
        }else{
            $records['sender_id_document'] = null;
        }

        $contactID = $request->file('contact_person_id');
        $records['contact_person_id'] = date('Y-m-d h:i:s').'_'.$contactID->getClientOriginalName();
        $contactID->storePubliclyAs('public/contact_person', $records['contact_person_id']);

        return $records;
    }

    private function saveSenderId(array  $senderIds, $user)
    {
        foreach ($senderIds as $sendor_id):

            $today = date('Y-m-d h:i:s');
            $registerIds = new UserSenderId;
            $registerIds->user_id = $user->id;
            $registerIds->sender_id = $sendor_id['Name'];
            $registerIds->created_at = Carbon::parse($today);
            $registerIds->updated_at = Carbon::parse($today);
            $registerIds->save();

        endforeach;
    }
    private function saveDirectors(array $directors, $company)
    {
        foreach ($directors as $director):
            $array['company_id'] = $company->id;
            $array['name'] = $director['Name'];
                $array['designation'] = $director['Designation'];
            CompanyDirector::query()->create($array);

        endforeach;
    }

    private function setStatus($company)
    {

        $status['company_id'] = $company->id;
        $status['r_code'] = $this->returnCode(4);
        $status['status'] = 3;
        $save = CompanyStatus::query()->create($status);
        //create a new array and send results
        $expose['company_status_id'] = $save->id;
        $expose['code'] = $status['r_code'];

        return $expose;

    }

    private function returnCode($length)
    {
        $t = Carbon::parse(date('Y-m-d h:i:s'))->format('s');
        $random = substr(str_shuffle(str_repeat($x='0123456789',ceil($length/strlen($x)))),1,$length);
        return 'DY'.$random.$t;
    }

    private function editUserInfo(Request $request)
    {
        $inputs['phone_number'] = SmsTools::format_gh_number($request->input('company_phone_number'));
        $inputs['full_name'] = $request->input('name');

        $inputs['organisation'] = $request->input('name');;
        $inputs['email']        = $request->input('contact_person_email');
        $inputs['website_url']  = !empty($request->input('website_url')) ? $request->input('website_url') : null;
        $inputs['role_id']      = Role::where('name', $request->input('register_as'))->first()->id;
        $inputs['location']     = empty($request->input('physical_address')) ? 'N/A' : $request->input('physical_address');;

        return $inputs;
    }

    private function editSavedFiles(Request $request,$company)
    {
        $records = array();

        if($request->hasFile('business_document')):

            $bc = $request->file('business_document');
            $records['business_document'] = date('Y-m-d h:i:s').'_'.$bc->getClientOriginalName();
            $bc->storePubliclyAs('public/business_doc', $records['business_document']);
            Storage::delete('public/business_doc/'.$company->business_document);

        endif;



        if($request->hasFile('sender_id_document')):

            $sendID = $request->file('sender_id_document');
            $records['sender_id_document'] = date('Y-m-d h:i:s').'_'.$sendID->getClientOriginalName();
            $sendID->storePubliclyAs('public/sender_docs', $records['sender_id_document']);
            Storage::delete('public/business_doc/'.$company->sender_id_document);

        endif;

        if($request->hasFile('contact_person_id')):

            $contactID = $request->file('contact_person_id');
            $records['contact_person_id'] = date('Y-m-d h:i:s').'_'.$contactID->getClientOriginalName();
            $contactID->storePubliclyAs('public/contact_person', $records['contact_person_id']);
            Storage::delete('public/business_doc/'.$company->contact_person_id);

        endif;

        return $records;
    }

    private function editSavedSenderId(array  $senderIds)
    {
        foreach ($senderIds as $sendor_id):
            $find = UserSenderId::query()->find($sendor_id['id']);

            $edit['sender_id']  = $sendor_id['name'];

            $find->update($edit);

        endforeach;
    }

    private function editSavedDirectors(array $directors)
    {
        foreach ($directors as $director):

            $find = CompanyDirector::query()->find($director['id']);

            $edit['name']  = $director['name'];
            $edit['designation']  = $director['designation'];

            $find->update($edit);


        endforeach;
    }

    private  function sendSms($text,$phone)
    {
        $message = urlencode($text);
        $num = urlencode($phone);

        $url = "https://deywuro.com/api/sms?username=sammy&password=cse@2021_npontu&source=Messenger&destination=" . $num . "&message=" . $message;

        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_exec($curl);
        curl_close($curl);
    }

    public function lookUp($request)
    {
        $data = $request->all();
        $requestIP = request()->ip();
        $app_user = $data['app_user'];
        $app_user_token = $data['app_user_token'];

        $authorizer = WhitelistedIPs::query()->where('ip',$requestIP)
            ->where('app_user',$app_user)
            ->first();

        if (!empty($authorizer)){
            $token =  $encrypted = hash_hmac('sha256', $authorizer->client_key, $authorizer->client_secrete);
            if($app_user_token !== $token)
                return  false;
        }else
        {
            return  false;
        }

        return true;

    }


    public function successResponse($message)
    {
        return response()->json(['code' => 200, 'status' => 'success', 'msg' => $message]);
    }

    public function failureResponse($message)
    {
        return response()->json(['code' => 401, 'status' => 'failed', 'msg' => $message]);
    }
}