<?php /** @noinspection PhpUnhandledExceptionInspection */
/** @noinspection PhpUndefinedMethodInspection */

/** @noinspection PhpUndefinedClassInspection */

namespace App\Http\Controllers\Admin;

use App\AdminAccessRight;
use App\Company;
use App\CompanyDirector;
use App\CompanyStatus;
use App\DataTables\Admin\CompanyDataTable;
use App\DataTables\SingleUserDataTable;
use App\Opt\CompanyTrait;
use App\Role;
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\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class AdminCompanyController extends Controller
{

    public function index(CompanyDataTable $company)
    {
        return $company->render('admin.company.index');
    }

    public function create(Request $request)
    {

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

            $this->validate($request, [
                'name' => 'required|unique:companies',
                //'date_of_incorporation' =>'required',
                'legal_status' => 'required',
                //               'postal_address' =>'required',
                'company_phone_number' => 'required|digits_between:10,20',
                'business_document' => 'required',
                'sender_id_document' => 'required',
                'contact_person' => 'required',
                'contact_person_id' => '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)
                return redirect()->back()->withInput(Input::all())->withErrors('the email ' . $request->input('contact_person_email') . ' has already been taken');

            $records = $request->all();

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

            /** Check for null values on the sender IDs and the Directors */
            //           if($sendor_ids == null  || $directors == null)
            if ($sendor_ids == null)
                redirect()->back()->withErrors('All Fields Are Required');


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

            /** IF OPTIONAL FIELDS ARE EMPTY INSERT N/A **/
            $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);




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

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

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

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

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

                $company->update($output);

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

                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('MTN MESSENGER');
                        });

                        $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('MTN MESSENGER');
                                });

                            } 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);
                    } catch (\Exception $ex) {
                    }

                endif;
            endif;

            DB::commit();

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

        endif;

        return view('admin.company.create');

    }

    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['website_url'] = !empty($request->input('website_url')) ? $request->input('website_url') : null;
        $inputs['password'] = bcrypt($password);
        $inputs['status'] = 'active';
        $inputs['location'] = empty($request->input('physical_address')) ? 'N/A' : $request->input('physical_address');
        $inputs['pass'] = $password;

        return $inputs;
    }

    private function saveFiles(Request $request)
    {
        $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']);


        $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']);

        $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);
        $save = CompanyStatus::query()->create($status);
        //create a Farray 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;
    }

    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',
                'nature_of_business' => 'required',
                '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  || empty($directors))
            if ($sender_ids == null)
                redirect()->back()->withErrors('All Fields Are Required');

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

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


            DB::beginTransaction();

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

            $company->update($records);

            $status = $this->editSetStatus($company);

            //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, $user);
            // we edit the company's director here
            $this->editSavedDirectors($directors ?? [], $company);

            DB::commit();

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

        endif;





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

    }

    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['website_url'] = !empty($request->input('website_url')) ? $request->input('website_url') : null;
        $inputs['email'] = $request->input('contact_person_email');
        $inputs['role_id'] = Role::where('name', $request->input('register_as'))->first()->id;
        $inputs['location'] = $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, $user)
    {
        foreach ($senderIds as $sendor_id):
            if (empty($sendor_id['id'])):

                $save['user_id'] = $user->id;
                $save['name'] = $sendor_id['name'];

            else:
                $find = UserSenderId::query()->find($sendor_id['id']);

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

                $find->update($edit);
            endif;

        endforeach;
    }

    private function editSavedDirectors(array $directors, $company)
    {
        foreach ($directors as $director):
            if (empty($director['id'])):

                $save['company_id'] = $company->id;
                $save['name'] = $director['name'];
                $save['designation'] = $director['designation'];


                CompanyDirector::query()->create($save);

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

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

                $find->update($edit);

            endif;


        endforeach;
    }

    private function editSetStatus($company)
    {

        $user = CompanyStatus::query()->where('company_id', $company->id)->first();

        if (!empty($user)):
            $user->update([
                'status' => 3
            ]);
        endif;


    }

    public function delete($id)
    {
        $company = Company::query()->find($id);
        try {
            DB::beginTransaction();
            $company->history()->delete();
            DB::commit();
        } catch (\Exception $e) {
        }

        return redirect()->back()->withErrors("Company Successfully Deleted");
    }


    use CompanyTrait;


}