<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use App\Models\User;
use App\Models\CabinClass;
use App\Models\Product;
use App\Models\Folder;
use App\Models\Document;
use App\Models\Company;
use App\Models\UserNotification;
use App\Events\UserNotificationEvent;
use App\Models\EmailQueue;

use League\Flysystem\Filesystem;


class CompanyController extends Controller
{

    private $local_store;


    public function __construct()
    {
        $this->local_store = 'fake_s3';

        $this->middleware('auth:admin', [ 'except' => ['exportInactivePN', 'exportCustomersAndFiles']]);

        $adminUser = auth()->guard('admin')->user();

        if (!$adminUser)
        {
            return response()->json(['error' => 'Unauthorized.'], 401);
        }

    }

    public function index(Request $req) {

        if (isset( $req->inactive ) && $req->inactive == 1) {

            $companies = Company::where('active', '!=', 1)->with('cabinClasses')->withCount('users')->get();

        }else{

            $companies = Company::with('cabinClasses')->withCount('users')->get();
        }

        return response()->json($companies);
    }

    public function delete(Request $request) {

        $company = Company::where('id', $request->id)->with('cabinClasses')->first();

        if ($company) {
            
            if ($company->cabinClasses) {        

                foreach ($company->cabinClasses as $k_cc => $v_cc) {
                    $products_to_delete = Product::where('cabin_class_id', $v_cc->id)->get();


                    if ($products_to_delete) {
                        foreach ($products_to_delete as $k_p => $v_p) {
                            $document = Document::where('product_id', $v_p->product_id)->first();

                            // Unlink documento
                            // if ($document) {
                            //     $document->product_id = null;
                            //     $document->save();
                            // }
                            if ($document) {
                                $document->delete();
                            }
                            // Elimino il prodotto
                            $v_p->company_id = null;
                            $v_p->delete();
                        }
                    }
                    // Elimino le cabin Clasess
                    $v_cc->delete();
                }
                $company->cabinClasses()->delete();
            }

            $company->folder()->delete();

            // Elimino la company
            # $company->folder_id = null;
            # $company->save();
            # $company = Company::where('id', $request->id)->first();

            $users = User::where('company_id', $request->id)->get();
            if ($users) {                
                foreach ($users as $key => $v_user) {
                    $v_user->company_id = 0;
                    $v_user->save();
                }
            }

            $company->delete();

            return response()->json(['success' => 'Company deleted successfully.'], 200);

        }else{
            return response()->json(['error' => 'Company not found.'], 404);
        }

        // ----- Deprecato da qui in poi --- 

        die('ok');
        # $company = Company::find($request->id)->with('cabinClasses');
        
        if ($company) {

            $company->folder()->delete();

            $company->delete();
            return response()->json(['success' => 'Company deleted successfully.'], 200);
        }
        else {
            return response()->json(['error' => 'Company not found.'], 404);
        }


    }

    public function show($id, Request $request) {
        $company = Company::where('id', $id)->with('cabinClasses')->with('folder')->with('users')->first();

        if ($company) {
            # var_dump( $company->cabinClasses );
            # var_dump( $company->folder );die;
            if (count($company->cabinClasses) != count($company->folder) && count($company->folder) <= 4 &&  count($company->cabinClasses) <= 4) {
                $company->missing_folders = 1;
            }else{
                $company->missing_folders = 0;
            }

            foreach ($company->cabinClasses as $cabinClass) {
                $cabinClass->removable = true;
                $cabinClass->products = Product::where('cabin_class_id', $cabinClass->id)->get();

                foreach ($cabinClass->products as $k => $v) {
                    $cabinClass->products[$k]->active = ($cabinClass->products[$k]->active == 1 ? true : false);
                }
            }
        }

        if (!$company) {
            return response()->json(['error' => 'Company not found.'], 404);
        }

        return response()->json(['company' => $company], 200);
    }


    public function getCompanyByName(Request $request) {

        $company = Company::where('name', $request->company_name)->with('cabinClasses')->with('cabinClasses.products')->first();

        if (!$company)
        {
            return response()->json(['error' => 'Company not found.'], 404);
        }

        return response()->json(['company' => $company]);

    }


    public function edit($id, Request $request) {
        $validator = Validator::make($request->all(), [
            'name' => 'required|unique:companies,name,'.$id
        ]);

        if ($validator->fails()) {
            throw new ValidationException($validator);
        }

        $company = Company::where('id', $id)->with('cabinClasses')->first();

        if (!$company) {
            return response()->json(['error' => 'Company not found.'], 404);
        }

        $company->name = $request->name;
        $company->save();

        foreach ($request->cabin_classes as $cabinClass) {
            $cabin = CabinClass::where('id', $cabinClass)->with('products')->first();

            if (!$cabin) {
                $cabin = CabinClass::create(['name' => $cabinClass['name']]);
                $cabin->company_id = $company->id;

                if (!Storage::disk('fake_s3')->exists($company->name.'/'.$cabin->name))
                {
                    Storage::disk('fake_s3')->makeDirectory($company->name.'/'.$cabin->name);

                    $folder = Folder::create([
                        'path' => $company->name.'/'.$cabin->name
                    ]);

                    $folder->parent_id = $company->folder_id;
                    $folder->company_id = $company->id;

                    $folder->save();
                }
            }

            $cabin->save();


            foreach ($cabinClass['products'] as $cabinProduct) {

                $product = isset($cabinProduct['id']) ? Product::find($cabinProduct['id']) : null;

                if (!$product && $cabinProduct['serial_number'] != '')
                {

                    $check = Product::where([ 
                        ['serial_number', '=', $cabinProduct['serial_number']],
                        ['cabin_class_id', '=', $cabin->id],
                    ])->first();

                    // Check PN duplicato

                    if (!$check || $check) {
                        $product = Product::create(['serial_number' => $cabinProduct['serial_number']]);
                        $product->cabin_class_id = $cabin->id;
                        $product->active = 1;
                        $product->save();
                    }

                } else {
                    if ($cabinProduct['serial_number'] != '') {
                        $product->serial_number = $cabinProduct['serial_number'];
                        $product->save();
                    }
                }

            }
        }

        $notification = UserNotification::create(['cta_label' => 'View Company']);
        $notification->company_id = $company->id;
        $notification->message = 'An administrator modified your company.';
        $notification->href = '/company';

        $notification->save();

        event(new UserNotificationEvent($company, $notification));

        return response()->json(['success' => 'Company updated successfully.']);
    }

    public function create(Request $request) {

        $validator = Validator::make($request->all(), [
            'name' => 'required|unique:companies'
        ]);

        if ($validator->fails()) {
            throw new ValidationException($validator);
        }

        $company = Company::create([
            'name' => $request->name
        ]);

        Storage::disk('fake_s3')->makeDirectory($company->name);

        $path = $company->name;

        $companyFolder = Folder::create(['path' => $path]);

        $company->folder_id = $companyFolder->id;
        $companyFolder->company_id = $company->id;

        $company->save();

        $cabinClasses = $request->cabin_classes;

        foreach ($cabinClasses as $cabinClass) {
            $cabin = CabinClass::create([
                'name' => $cabinClass['name']
            ]);

            $cabin->company_id = $company->id;

            Storage::disk('fake_s3')->makeDirectory($company->name.'/'.$cabin->name);

            $folder = Folder::create([
                'path' => $company->name.'/'.$cabin->name
            ]);

            $folder->parent_id = $companyFolder->id;
            $folder->company_id = $company->id;

            $folder->save();

            $cabin->save();


            $products = $cabinClass['products'];

            foreach ($products as $product) {
                if ($product['serial_number'] != '') {

                    $p = Product::create([
                        'serial_number' => $product['serial_number']
                    ]);
                    $p->active = 1;
                    $p->cabin_class_id = $cabin->id;
                    $p->save();
                }
            }

        }

        return response()->json(['success' => 'Company created successfully', 'company' => $company]);

    }

    public function linkUser(Request $request) {
        $company = Company::find($request->company_id);
        $user = User::find($request->user_id);

        if (!$company || !$user) {
            return response()->json(['error' => 'Resource not found.'], 404);
        }

        $user->company_id = $company->id;
        $user->save();

        return response()->json(['success' => 'User linked successfully.'], 200);
    }

    public function unlinkUser(Request $request) {
        $user = User::find($request->user_id);

        if (!$user) {
            return response()->json(['error' => 'User not found'], 404);
        }

        $user->company_id = null;
        $user->save();

        return response()->json(['success' => 'User unlinked successfully.'], 200);
    }


    public function toggleActiveProduct(Request $request)
    {
        $product_id = $request->product_id;
        $active = $request->active;

        if ($product_id > 0) {
            $product = Product::find($product_id);

            if ($active == true) {
                $product->active = 1;
            }else{
                $product->active = 0;
            }
            $product->save();
        }

        return response()->json(['success' => 'Product Activation toggled successfully'], 200);
    }

    public function validateCompany(Request $request)
    {
        if (isset($request->company_id)) {
            $company = Company::where('id', $request->company_id)->with('cabinClasses')->with('cabinClasses.products')->with('users')->with('folder')->first();
            $first_validation = 0;
            if ($company && $company->active == 0) {

                if (count($company->folder) == 0) {
                    
                    Storage::disk('fake_s3')->makeDirectory($company->name);
                    $path = $company->name;
                    $companyFolder = Folder::create(['path' => $path]);
                    $company->folder_id = $companyFolder->id;
                    $companyFolder->company_id = $company->id;

                    if (count( $company->cabinClasses ) > 0) {
                        foreach ($company->cabinClasses as $kk => $v_cabin) {

                            $v_cabin->removable = true;

                            Storage::disk('fake_s3')->makeDirectory($company->name.'/'.$v_cabin->name);
                            $folder = Folder::create([
                                'path' => $company->name.'/'.$v_cabin->name
                            ]);
                            if ($companyFolder) {
                                $folder->parent_id = $companyFolder->id;
                            }
                            $folder->company_id = $company->id;
                            $folder->save();

                            if (count($v_cabin->products) > 0) {
                                foreach ($v_cabin->products as $k => $value) {
                                    $v_cabin->products[$k]->active = ($v_cabin->products[$k]->active == 1 ? true : false);
                                }
                            }

                        }
                    }
                    $company->active = 1;
                    //$company->save();
                    $first_validation = 1;
                    $company->missing_folders = 0;
                    $company->save();


                }

                if ($company->active == 0) {
                    $company->active = 1;
                    $company->save();
                }
            }
            // Caso in cui la Company esiste, è attiva, ma un utente ha richiesto una classe non presente prima
            if ($company && $company->active == 1 && $first_validation != 1) {
                if (count($company->cabinClasses) != count($company->folder) ) {
                    $company->missing_folders = 0;
                    $company->save();

                    $dirs = Storage::disk('fake_s3')->allDirectories($company->name);
                    $check_real_dirs = [];
                    foreach ($dirs as $key => $value) {
                        $check_real_dirs[ $value ] = $value;
                    }

                    $folder_list = [];
                    foreach ($company->folder as $k => $v_folder) {
                        
                        $name_expl = explode("/", $v_folder->path);
                        $name = $name_expl[count($name_expl)-1];

                        $folder_list[ $name ] = $v_folder->path;
                    }
                    foreach ($company->cabinClasses as $key => $v_cabin) {

                        // Se manca va creata
                        if ( !array_key_exists($v_cabin->name, $folder_list) ) {

                            $v_cabin->removable = true;

                            Storage::disk('fake_s3')->makeDirectory($company->name.'/'.$v_cabin->name);
                            $folder = Folder::create([
                                'path' => $company->name.'/'.$v_cabin->name
                            ]);
                            if ($company->folder_id) {
                                $folder->parent_id = $company->folder_id;
                            }
                            $folder->company_id = $company->id;
                            $folder->save();

                            if (count($v_cabin->products) > 0) {
                                foreach ($v_cabin->products as $k => $value) {
                                    $v_cabin->products[$k]->active = ($v_cabin->products[$k]->active == 1 ? true : false);
                                }
                            }
                        }else{
                            unset($folder_list[ $v_cabin->name ]);
                            unset($check_real_dirs[ $company->name.'/'.$v_cabin->name ]);
                        }
                    }
                }
                
               # var_dump($check_real_dirs);die();

                foreach ($check_real_dirs as $k => $dir_to_delete) {
                    if (strpos($dir_to_delete, "/") > 0) {
                        Storage::disk('fake_s3')->deleteDirectory($dir_to_delete);
                        $folder = Folder::where('path', $dir_to_delete)->first();
                        if ($folder) {
                            $folder->delete();
                        }
                        $company->missing_folders = 0;
                        $company->save();

                    }
                }


                // if (count( $folder_list ) > 0 ) {
                //     foreach ($folder_list as $k => $v_folder) {
                //        // Local delete

                //         // Subfolder
                //         if (strpos($v_folder, "/") > 0) {
                //             Storage::disk('fake_s3')->deleteDirectory($v_folder);
                //             $folder = Folder::where('path', $v_folder)->first();
                //             if ($folder) {
                //                 $folder->delete();
                //             }
                //         }else{
                //             var_dump($dirs);
                //             var_dump($company->folder);
                //             var_dump($folder_list);
                //             die();
                //         }

                //     }
                // }

            }

            if (!$company) {
                return response()->json(['error' => 'Company not found.'], 404);
            }

            return response()->json(['company' => $company], 200);
        }
    }

    public function allInactivePN(Request $request)
    {
        $only_inactive = 0;
            if (isset($request->only_inactive) && $request->only_inactive == 1) {
                $only_inactive = 1;
                $companies = Company::where('id', '>', 0)->with('cabinClasses')->with('folder')->with('cabinClasses.products', function($query) {
                    return $query->where('active', '<', 1);
                })->get();
            }else{
                $companies = Company::where('id', '>', 0)->with('cabinClasses')->with('folder')->with('cabinClasses.products')->get();
            }
        
        # $companies = Company::where('id', '>', 0)->with('cabinClasses', function($query) {
            # return $query->where('active', '<', 1)})->with('folder')->with('cabinClasses.products')->get();

        $selected_companies_with_inactive_pn = [];

        foreach ($companies as $k => $v) {

            $cabin_folders = [];
            foreach ($v->folder as $kf => $vf) {
                if (isset( $path_expl[1] )) {
                    $path_expl = explode("/", $vf['path']);
                    $cabin_folders[ $path_expl[1] ] = $vf['id'];
                }
            }

            
            foreach ($v->cabinClasses as $kk => $v_cabin) {

                if ( count($v_cabin->products) ) {
                    
                    $selected_companies_with_inactive_pn['list'][$k] = $v;
                    
                    $cabin_name = $v_cabin['name'];

                    foreach ($v_cabin->products as $kkk => $v_product) {
                            
                        # if ($v_product->active != 1 || $only_inactive = 0) {

                            if ($selected_companies_with_inactive_pn['list'][$k]['cabinClasses'][$kk]['products'][$kkk]['active'] == 1) {
                                $selected_companies_with_inactive_pn['list'][$k]['cabinClasses'][$kk]['products'][$kkk]['active'] = true;
                            }else{
                                $selected_companies_with_inactive_pn['list'][$k]['cabinClasses'][$kk]['products'][$kkk]['active'] = false;

                            }
                            if (array_key_exists($cabin_name, $cabin_folders)) {
                                $selected_companies_with_inactive_pn['list'][$k]['cabinClasses'][$kk]['folder_id'] = $cabin_folders[ $cabin_name ];
                            }

                        # }

                    }
                }

            }

        }

        $selected_companies_with_inactive_pn['count'] = count($selected_companies_with_inactive_pn);

        return response()->json($selected_companies_with_inactive_pn, 200);
    }

    function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
        // open raw memory as file so no temp files needed, you might run out of memory though
        $f = fopen('php://memory', 'w'); 
        // loop over the input array
        foreach ($array as $line) { 
            // generate csv lines from the inner arrays
            fputcsv($f, $line, $delimiter); 
        }
        // reset the file pointer to the start of the file
        fseek($f, 0);
        // tell the browser it's going to be a csv file
        header('Content-Type: text/csv');
        // tell the browser we want to save it instead of displaying it
        header('Content-Disposition: attachment; filename="'.$filename.'";');
        // make php send the generated csv lines to the browser
        fpassthru($f);
    }

    public function exportInactivePN(Request $request)
    {

        $companies = Company::where('id', '>', 0)->with('cabinClasses')->with('folder')->with('cabinClasses.products', function($query) {
            return $query->where('active', '<', 1);
        })->get();

        $out_obj = [];

        $out_obj[] = ['Company', 'Cabin Class', 'PN'];
        $out_txt = "<b>COMPANY, CABIN CLASS, PN</b><br>";

        foreach ($companies as $k => $v) {

            $cabin_folders = [];
            foreach ($v->folder as $kf => $vf) {
                $path_expl = explode("/", $vf['path']);
                $cabin_folders[ $path_expl[1] ] = $vf['id'];
            }

            foreach ($v->cabinClasses as $kk => $v_cabin) {

                if ( count($v_cabin->products) ) {
                    
                    $cabin_name = $v_cabin['name'];

                    foreach ($v_cabin->products as $kkk => $v_product) {
                            
                        $out_obj[] = [
                            $v->name,
                            $cabin_name,
                            $v_product->serial_number
                        ];
                        $out_txt .= $v->name.', <i>'.$cabin_name.'</i>: <b>'.$v_product->serial_number."</b><br>";
                    }
                }

            }

        }
        // INACTIVE PNs
        $mail = EmailQueue::create([
            'label' => 'Inactive P/N (s)',
            'type' => '3',
            'info' => $out_txt,
            'to' => "test.sito@external.aviointeriors.it"
        ]);

        $this->array_to_csv_download(
          $out_obj,
          "export.csv"
        );
        die();

        return response()->json($out_obj, 200);
    }

    public function exportCustomersAndFiles(Request $request)
     {
        $file_list = [];
        $file_list[] = [
            'Nome compagnia' => 'Nome compagnia',
            'Nome file' => 'Nome file',
            'Percorso file' => 'Percorso file',
            'Email' => 'Email',
            'Nome e cognome' => 'Nome e cognome'
        ];

        // Prendo tutte le Compagnie attive
        $companies = Company::where('id', '>', 0)->with('cabinClasses')->with('folder')->with('cabinClasses.products', function($query) {
            return $query->where('active', '>=', 1);
        })->get();

        foreach ($companies as $k => $v_company) {

            $company_folder_id = $v_company->folder_id;

            foreach ($v_company->folder as $kf => $v_folder) {

                // Prendo il path
                $current_folder_path = $v_folder->path;

                if ($current_folder_path != '' ) {

                    // Cerco i file presenti nella tabella documents, e poi vedo se esistono davvero sul filesystem
                    $documents = Document::where('path', 'LIKE', "%".$current_folder_path."%")->get();

                    # return response()->json($documents, 200);
                    
                    foreach ($documents as $kd => $v_document) 
                    {
                        $current_document = $v_document->path;
                        $current_document_name = $v_document->name;

                        // Controllo su filesystem
                        $file_check = Storage::disk($this->local_store)->exists($current_document);

                        // Se esiste
                        if ($file_check) {

                            $file_list_item = [
                                'Nome compagnia' => $v_company->name,
                                'Nome file' => '',
                                'Percorso file' => '',
                                'Email' => '',
                                'Nome e cognome' => ''
                            ];
                            
                            // Controllo se è associato a un prodotto

                            if ($v_document->product_id != NULL) {
                                $product = Product::find($v_document->product_id);

                                // Controllo se il prodotto esiste ancora e se ha un utente associato
                                if ($product && $product->user_id != NULL) 
                                {
                                    $user_info = User::find($product->user_id);

                                    // Se lo è prendo eventuali info del cliente che ha richiesto il PN
                                    if ($user_info) {
                                        
                                        $nome_completo = $user_info->first_name." ".$user_info->last_name;
                                        $email = $user_info->email;

                                        $file_list_item['Email'] = $email;
                                        $file_list_item['Nome e cognome'] = $nome_completo;
                                    }    
                                }
                            }
                            
                            // Se no lo inserisco in lista senza queste info  

                            $file_list_item['Percorso file'] = $current_document;
                            $file_list_item['Nome file'] = $current_document_name;

                        }

                        #return response()->json($file_check, 200);
                        $file_list[] = $file_list_item;
                    }
                }
             } 
        }

        $this->array_to_csv_download(
          $file_list,
          "export_file_list_".date("Y-m-d").".csv"
        );
        die();

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

     } 

     protected function pathFromUrl($path) {
         $path = str_replace(config('app.url'), '', $path);
         $path = str_replace('storage/', '', $path);
         $path = trim($path, '/');
         return $path;
     }


}
