Please improve this Laravel 9 code. <?php

namespace App\Http\Controllers;
use App;
use App\Models\Application;
use App\Models\Catalog\Certificate;
use App\Models\Layout;
use App\Models\Vessel;
use Carbon\Carbon;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Inertia\Inertia;
use PhpOffice\PhpWord\TemplateProcessor;
use Str;


class LayoutController extends Controller
{

    public function download_filled_layout()
    {
        $application_id = Request::input('application_id');
        $layout_id = Request::input('layout_id');
        $validated_file = Request::input('validated_file');
        $application = Application::find($application_id);
        $layout = Layout::find($layout_id);

        $name = $layout->layout_name . '_' . $application->surname . '_' . $application->name .'_'.ranks()->get($application->rank_id);
        $name = Str::slug($name, '_');

        if($layout and $application) {

            $file = $validated_file . '.docx';
            $path = Storage::disk('root')->path($file);

            return response()->download($path, $name . '.docx')->deleteFileAfterSend(true);

        } else {
            return null;
        }

    }

    public function show_all_layouts()
    {
        // DB::enableQueryLog();
        $layouts = Layout::filter(Request::all(['selected']))->orderBy('id', 'desc')->paginate(14)->appends(request()->query());
        //  dd(DB::getQueryLog());

        return Inertia::render('Iview/Layouts/Index', [
            'layouts' => $layouts,
            'title' => __('Layouts')
        ]);
    }

    public function layouts_new_files_upload()
    {
        $validator = Validator::make(Request::all(), [
            'file' => 'mimes:docx|max:5000'
        ]);
        if ($validator->fails()) {
            return response()->json($validator->messages(), 200);
        } else {
            try {
                $layout_original_name = pathinfo(Request::file('file')->getClientOriginalName(), PATHINFO_FILENAME);
                $layout_create_db_record = Layout::create([
                    'layout_name' => $layout_original_name,
                    'created_at' => Carbon::now()->toDateTimeString()
                ]);
                if ($layout_create_db_record) {
                    $file_location_original = Request::file('file')->storeAs(
                        '/',
                        $layout_create_db_record->id . '.docx',
                        'layouts'
                    );
                }
            } catch (\Exception $e) {
                return response()->json(['file' => [$e->getMessage()]], 200);
            }
        }

    }

    public function layout_change_name()
    {
        Layout::find(Request::input('field_id'))->update(['layout_name' => Request::input('new_field_name')]);
    }

    public function layout_download()
    {
        $layout = Layout::findorFail(Request::input('layout_id'));

        if ($layout) {
            $s = Storage::disk('layouts');
            $f = Request::input('layout_id') . '.docx';
            if ($s->exists($f)) {
                return response()->json(['file' => $f, 'file_name' => $layout->layout_name . '.docx'], 200);
            } else {
                return response()->json(['nofile' => 'No File'], 200);
            }
        } else {
            return response()->json(['nofile' => 'No File'], 200);
        }

    }

    public function layout_download_link()
    {
        return Storage::disk('layouts')->download(Request::input('file'), Request::input('file_name'));
    }


    public function layout_delete()
    {
        $layoutId = request()->input('layout_id');
        $layout = Layout::findOrFail($layoutId);

        $storage = Storage::disk('layouts');
        $fileName = $layoutId . '.docx';

        if ($storage->exists($fileName)) {
            $storage->delete($fileName);
        }

        $layout->delete();
    }


    public function prepare_layout_before_download()
    {
        try {

            $validator = Validator::make(Request::all(), [
                'layout_id' => 'required|integer',
                'application_id' => 'required|integer',
            ]);

            if ($validator->fails()) {

                return response()->json($validator->messages(), 200);

            } else {

                if ($this->checkIfLayoutExists(Request::input('layout_id'))) {

                    $layout_id = (int)Request::input(['layout_id']);
                    $application_id = (int)Request::input(['application_id']);

                    $application = Application::with(['experiences', 'documents.certificate' => function ($query) {
                        $query->orderBy('id', 'ASC');
                    },])->find($application_id);

                    $gender = collect([1 => 'male', 2 => 'female']);
                    if ($application->documents) {

                        foreach ($application->documents as $document) {

                           // if ($document->certificate->template_name and $document->primary_ == 1) {
                                $data['application'][$document->certificate->template_name] = certificate_no_groups()->get($document->certificate_id);
                                $data['application'][$document->certificate->template_name . '_number'] = $document->number;
                                $data['application'][$document->certificate->template_name . '_country'] = countries()->get($document->country_id);
                                $data['application'][$document->certificate->template_name . '_from'] = $document->from;
                                $data['application'][$document->certificate->template_name . '_till'] = $document->till;
                            //}

                        }
                    }

                    $data['application']['rank'] = ranks()->get($application->rank_id);
                    $data['application']['name'] = $application->name;
                    $data['application']['surname'] = $application->surname;
                    $data['application']['middlename'] = $application->middlename;
                    $data['application']['dob'] = $application->dob;
                    $data['application']['age'] = age_date_($application->dob);
                    $data['application']['pob'] = $application->pob;
                    $data['application']['nationality'] = nationality()->get($application->citizenship);

                    $data['application']['gender'] = $gender->get($application->gender);

                    if ($application->avatar) {

                        $data['application']['avatar'] = Storage::disk('seaman')->path($application->avatar);
                    } else {
                        $data['application']['avatar'] = '';
                    }

                    $data['application']['today'] = date('d.m.Y');

                    $vessel = Vessel::find($application->current_vessel);

                    $data['application']['currentvessel'] = $vessel ? $vessel->name : '';
                    $data['application']['country'] = countries()->get($application->country);
                    $data['application']['city'] = $application->city;
                    $data['application']['address'] = $application->address;
                    $data['application']['phone'] = $application->phone;
                    $data['application']['postcode'] = $application->postcode;
                    $data['application']['mobile'] = $application->mobile;
                    $data['application']['alt_phone'] = $application->alt_phone;
                    $data['application']['email'] = $application->email;
                    $data['application']['skype'] = $application->skype;
                    $data['application']['readiness'] = $application->available_from;
                    $data['application']['pd_eyes'] = $application->pd_eyes;
                    $data['application']['pd_weight'] = $application->pd_weight;
                    $data['application']['pd_hair'] = $application->pd_hair;
                    $data['application']['pd_height'] = $application->pd_height;
                    $data['application']['pd_shoes'] = $application->pd_shoes;
                    $data['application']['pd_boilersuit'] = $application->pd_boilersuit;
                    $data['application']['nok_name'] = $application->nok_name;
                    $data['application']['nok_relationship'] = $application->nok_relationship;
                    $data['application']['nok_mobile'] = $application->nok_mobile;
                    $data['application']['nok_address'] = $application->nok_address;
                    $data['application']['flight_details'] = $application->flight_details;
                    $data['application']['agent_details'] = $application->agent_details;
                    $data['application']['additional_information'] = $application->additional_information;
                    $documents = $application->documents;
                    $experience = $application->experiences;
                    $layout_path = Storage::disk('layouts')->path($layout_id . '.docx');
                    $templateProcessor = new TemplateProcessor($layout_path);
                    $template_variables = collect($templateProcessor->getVariables());
                    $temp_ = $template_variables->flip();
                    $new_application_data_array = collect($data['application'])->diffKeys(collect($data['application'])->diffKeys($temp_));
                    $delete_empty_data = $temp_->diffKeys($new_application_data_array);

                    foreach ($data['application'] as $key => $value) {


                        if ($key == 'avatar') {
                            if ($temp_->has('avatar')) {


                                if (File::exists($value)) {
                                    $templateProcessor->setImageValue('avatar', array('path' => $value, 'width' => 200, 'height' => 200, 'ratio' => true));
                                }

                            }
                        }


                        if (!is_array($value) and $key !== 'avatar') {
                            if ($temp_->has($key)) {
                                $templateProcessor->setValue($key, $value);
                            }


                        }

                        if (is_array($value)) {
                            foreach ($value as $key_ => $value_) {

                                if ($temp_->has($key_)) {
                                    $templateProcessor->setValue($key_, $value_);
                                }

                            }

                        }

                    }

                    if ($temp_->has('exp_vessel')) {
                        $total_exp = count($experience);
                        if ($total_exp > 0) {
                            $templateProcessor->cloneRow('exp_vessel', $total_exp);
                            $k = 1;
                            foreach ($experience as $exp) {

                                if ($exp['from']) {
                                    $from = date('d.m.Y', strtotime($exp->from));
                                } else {
                                    $from = '';
                                }

                                if ($exp['till']) {
                                    $till = date('d.m.Y', strtotime($exp->till));
                                } else {
                                    $till = '';
                                }

	                            $dif_ = '';
	                            try {
		                            if(!empty($exp->from) and !empty($exp->till)){
			                            $dif_ = exp_diff_date($exp->from, $exp->till);
		                            }
		                            else {
			                            $dif_ = '';
		                            }
	                            }
	                            catch (\Exception $e) {

	                            }

                                $templateProcessor->setValue('exp_vessel' . '#' . $k, $exp['vessel']);
                                $templateProcessor->setValue('exp_flag' . '#' . $k, mb_strtoupper(countries_a3()->get($exp->flag)));
                                $templateProcessor->setValue('exp_engine' . '#' . $k, vessel_engines()->get($exp->vessel_engine_id));
                                $templateProcessor->setValue('exp_kwt' . '#' . $k, $exp->kwt);
                                $templateProcessor->setValue('exp_type' . '#' . $k, vessel_types_no_groups()->get($exp->vessel_type_id));
                                $templateProcessor->setValue('exp_dwt' . '#' . $k, $exp->dwt);
                                $templateProcessor->setValue('exp_rank' . '#' . $k, ranks()->get($exp->rank_id));
                                $templateProcessor->setValue('exp_from' . '#' . $k, $from);
                                $templateProcessor->setValue('exp_teu' . '#' . $k, $exp->teu);
                                $templateProcessor->setValue('exp_yob' . '#' . $k, $exp->yob);
                                $templateProcessor->setValue('exp_model' . '#' . $k, $exp->engine_model);
                                $templateProcessor->setValue('exp_till' . '#' . $k, $till);
	                            $templateProcessor->setValue('exp_dif' . '#' . $k, $dif_);
                                $templateProcessor->setValue('exp_company' . '#' . $k, $exp->company);
                                $k++;
                            }

                        } else {
                            $templateProcessor->setValue('exp_vessel', '');
                            $templateProcessor->setValue('exp_flag', '');
                            $templateProcessor->setValue('exp_engine', '');
                            $templateProcessor->setValue('exp_kwt', '');
                            $templateProcessor->setValue('exp_type', '');
                            $templateProcessor->setValue('exp_dwt', '');
                            $templateProcessor->setValue('exp_rank', '');
                            $templateProcessor->setValue('exp_from', '');
                            $templateProcessor->setValue('exp_till', '');
                            $templateProcessor->setValue('exp_company', '');

                        }

                    }

                    if ($temp_->has('cert_name')) {
                        $total_docs = count($documents);
                        if ($total_docs > 0) {
                            $templateProcessor->cloneRow('cert_name', $total_docs);
                            $k = 1;
                            foreach ($documents as $cert) {

                                if ($cert['from']) {
                                    $from = date('d.m.Y', strtotime($cert['from']));
                                } else {
                                    $from = '';
                                }

                                if ($cert['till']) {
                                    $till = date('d.m.Y', strtotime($cert['till']));
                                } else {
                                    $till = '';
                                }
                                $templateProcessor->setValue('cert_name' . '#' . $k, certificate_no_groups()->get($cert['certificate_id']));
                                $templateProcessor->setValue('cert_number' . '#' . $k, $cert['number']);
                                $templateProcessor->setValue('cert_country' . '#' . $k, mb_strtoupper(countries()->get($cert['country_id'])));
                                $templateProcessor->setValue('cert_from' . '#' . $k, $from);
                                $templateProcessor->setValue('cert_till' . '#' . $k, $till);
                                $k++;
                            }

                        } else {
                            $templateProcessor->setValue('cert_name', '');
                            $templateProcessor->setValue('cert_number', '');
                            $templateProcessor->setValue('cert_country', '');
                            $templateProcessor->setValue('cert_from', '');
                            $templateProcessor->setValue('cert_till', '');

                        }
                    }

                    if ($delete_empty_data) {
                        foreach ($delete_empty_data as $key => $value) {
                            $templateProcessor->setValue($key, '');
                        }
                    }

                    $temp_name = Str::random(15);
                    $path = Storage::disk('root')->path($temp_name . '.docx');
                    $templateProcessor->saveAs($path);

                    return response()->json(['validated_file' => $temp_name, 'application_id' => $application_id, 'layout_id' => $layout_id], 200);

                } else {
                    return response()->json(['validator' => 'Layout not found'], 200);

                }

            }

        } catch (\Exception $e) {

            return response()->json([$e->getMessage()], 200);
        }


    }

    /**
     * Checks if a layout exists in the database and storage, and deletes the file if the layout is missing in the database.
     *
     * @param int $layoutId The ID of the layout to check.
     * @return bool Returns true if the layout exists in both the database and storage, otherwise false.
     */
    protected function checkIfLayoutExists($layoutId)
    {
        // Attempt to find the layout in the database.
        $layout = Layout::find($layoutId);

        // Define the storage disk and the file name.
        $storage = Storage::disk('layouts');
        $fileName = "{$layoutId}.docx";

        // If the layout does not exist in the database
        if (!$layout) {
            // Check if the file exists in storage
            if ($storage->exists($fileName)) {
                // Delete the file if it exists
                $storage->delete($fileName);
            }
            return false;
        }

        // Check if the corresponding file exists in the storage for the found layout.
        return $storage->exists($fileName);
    }



    protected function getIdforCrewList ($documents,$name)
    {
        foreach ($documents as $document) {
            if($document->certificate) {
                if ($document->certificate->text === $name) {
                    return [
                        'document'=>$document->certificate->text,
                        'number'=>$document->number,
                        'till'=>$document->till
                    ];
                }
            }
        }
        return [
            'document'=>'',
            'number'=>'',
            'till'=>''
        ];
    }

    public function downloadCrewList() {

        try {
            $vessel = Request::get('vessel');
            $crew = Request::get('crew');
            $filteredData = array_filter($crew, function ($item) {
                return !is_null($item['ap_id']);
            });
            $newArray = collect($filteredData)->pluck('ap_id');
            $applications = Application::with(['documents.certificate'])->whereIn('id',$newArray)->get();

            if($crew) {
                $crewListPath = Storage::disk('root')->path('imo_crew_list.docx');

                $templateProcessor = new TemplateProcessor($crewListPath);
                $templateProcessor->setValue('vessel', $vessel['name']??'');
                $templateProcessor->setValue('imo', $vessel['imo']??'');
                $templateProcessor->setValue('call_sign', $vessel['call_sign']??'');

                $totalCrew = count($crew);
                if($totalCrew > 0) {
                    $templateProcessor->cloneRow('no', $totalCrew);
                    $k = 1;
                    foreach ($crew as $crewMember) {
                        if($crewMember['ap_id']) {
                            $documents = $applications->find($crewMember['ap_id'])->documents;
                            $f = $this->getIdforCrewList($documents,'Passport');
                            // dump($f);
                            $templateProcessor->setValue('nationality' . '#' . $k, $crewMember['_nationality_id']?nationality()->get($crewMember['_nationality_id']):'');
                            $templateProcessor->setValue('doc_name' . '#' . $k, $f['document']);
                            $templateProcessor->setValue('doc_number' . '#' . $k, $f['number']);
                            $templateProcessor->setValue('doc_till' . '#' . $k, $f['till']);
                            $templateProcessor->setValue('no' . '#' . $k, $k);
                            $templateProcessor->setValue('name' . '#' . $k, $crewMember['_name']);
                            $templateProcessor->setValue('surname' . '#' . $k, $crewMember['_surname']);
                            $templateProcessor->setValue('rank' . '#' . $k, $crewMember['rank_name']);
                            $templateProcessor->setValue('dob' . '#' . $k, $crewMember['dob_'] ?? '');
                            $templateProcessor->setValue('pob' . '#' . $k, $crewMember['pob'] ?? '');
                            $templateProcessor->setValue('gender' . '#' . $k, $crewMember['gender'] == 1 ? 'male' : ($crewMember['gender'] == 2 ? 'female' : ''));


                        } else {
                            $templateProcessor->setValue('no' . '#' . $k, $k);
                            $templateProcessor->setValue('nationality' . '#' . $k, '');
                            $templateProcessor->setValue('dob' . '#' . $k, '');
                            $templateProcessor->setValue('pob' . '#' . $k, '');
                            $templateProcessor->setValue('gender' . '#' . $k, '');
                            $templateProcessor->setValue('name' . '#' . $k, '');
                            $templateProcessor->setValue('surname' . '#' . $k, '');
                            $templateProcessor->setValue('rank' . '#' . $k, '');
                            $templateProcessor->setValue('doc_name' . '#' . $k, '');
                            $templateProcessor->setValue('doc_number' . '#' . $k, '');
                            $templateProcessor->setValue('doc_till' . '#' . $k, '');
                        }
                        $k++;
                    }
                    $tempCrewListName = Str::random(20);
                    $filePath = Storage::disk('root')->path($tempCrewListName.'.docx');
                   // $filePath = 'storage/'.env('APP_ENV').'/' . $tempCrewListName.'.docx';
                    $templateProcessor->saveAs($filePath);
                    return response()->json(['crewListTempFile' => $tempCrewListName], 200);
                }

            }
            else {
                return response()->json(['error' => 'There are no vessel berths available'], 404);
            }

        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 404);
        }
        return null;

    }


    public function download_filled_crewlist()
    {
        $vessel = request('vessel');
        $fileName = request('validated_crew_list');
        $filePath = Storage::disk('root')->path($fileName . '.docx');
        $downloadName = 'crew_list_' . Str::slug($vessel, '_') . '_' . now()->format('d_m_Y') . '.docx';

        return response()->download($filePath, $downloadName)->deleteFileAfterSend(true);
    }


    public function get_tags()
    {


        if(App::getLocale() === "en") {
            $data['page_title'] = 'Layout tags';
            $data['page_description'] = 'View tags';
            $data['tags_ap_pd'] = collect([
                'Rank' => 'rank',
                'Name' => 'name',
                'Surname' => 'surname',
                'Middlename' => 'middlename',
                'Date of birth' => 'dob',
                'Age' => 'age',
                'Place of birth' => 'pob',
                'Nationality' => 'nationality',
                'Gender' => 'gender',
                'Photo' => 'avatar',
                'Country' => 'country',
                'City' => 'city',
                'Address' => 'address',
                'Phone (local)' => 'phone',
                'Post code' => 'postcode',
                'Phone (mobile)' => 'mobile',
                'E-mail' => 'email',
                'Skype' => 'skype',
                'Date of readiness' => 'readiness',
                'Eyes colour' => 'pd_eyes',
                'Weight' => 'pd_weight',
                'Hair colour ' => 'pd_hair',
                'Height' => 'pd_height',
                'Shoes size' => 'pd_shoes',
                'Boilersuit size' => 'pd_boilersuit',
                'NOK name' => 'nok_name',
                'NOK relationship' => 'nok_relationship',
                'NOK phone' => 'nok_mobile',
                'NOK address' => 'nok_address',
                'Current vessel' => 'currentvessel',
                'Today date' => 'today',
            ])->flip();
        } else {
            $data['page_title'] = 'Метки шаблона';
            $data['page_description'] = 'Метки';

            $data['tags_ap_pd'] = collect([
                'Должность' => 'rank',
                'Имя' => 'name',
                'Фамилия' => 'surname',
                'Отчество' => 'middlename',
                'Дата рождения' => 'dob',
                'Возраст' => 'age',
                'Место рождения' => 'pob',
                'Национальность' => 'nationality',
                'Пол' => 'gender',
                'Фото' => 'avatar',
                'Страна' => 'country',
                'Город' => 'city',
                'Адрес' => 'address',
                'Телефон (местный)' => 'phone',
                'Почтовый код' => 'postcode',
                'Телефон (мобильный)' => 'mobile',
                'Электронная почта' => 'email',
                'Skype' => 'skype',
                'Дата готовности' => 'readiness',
                'Цвет глаз' => 'pd_eyes',
                'Вес' => 'pd_weight',
                'Цвет волос' => 'pd_hair',
                'Рост' => 'pd_height',
                'Размер обуви' => 'pd_shoes',
                'Размер костюма' => 'pd_boilersuit',
                'Имя (Ближайший родственник)' => 'nok_name',
                'Статус (Ближайший родственник)' => 'nok_relationship',
                'Телефон (Ближайший родственник)' => 'nok_mobile',
                'Адрес (Ближайший родственник)' => 'nok_address',
                'Текущее судно' => 'currentvessel',
                'Сегодняшняя дата' => 'today',
            ])->flip();
        }


        $data['tags_ap_exp'] = collect([
            'Vessel name' => 'exp_vessel',
            'Vessel type' => 'exp_type',
            'Vessel DWT' => 'exp_dwt',
            'Engine type' => 'exp_engine',
            'Engine model' => 'exp_model',
            'Engine power (kwt)' => 'exp_kwt',
            'Vessel flag' => 'exp_flag',
            'TEU' => 'exp_teu',
            'YOB' => 'exp_yob',
            'From' => 'exp_from',
            'Till' => 'exp_till',
            'Company' => 'exp_company',

        ])->flip();

        $data['tags_ap_docs'] = Certificate::whereNotNull('text')->get();

        return response()->json($data, 200);


    }


}