<?php

namespace App\Core\Service;

use App\Core\Repository\PropertyAwardsCertificate\PropertyAwardsCertificateRepository;
use App\Core\Repository\AwardsCertificateCategory\AwardsCertificateCategoryRepository;
use App\Core\Repository\Property\PropertyRepository;
use App\Core\Validator\PropertyAwardsCertificate\PropertyAwardsCertificateCreateValidator;
use App\Core\Validator\PropertyAwardsCertificate\PropertyAwardsCertificateUpdateValidator;
use App\Core\Validator\PropertyAwardsCertificate\PropertyAwardCertificateUploadValidator;

use App;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use Exception;
use App\Exceptions\ApiErrorException;
use Intervention\Image\Facades\Image;

class PropertyAwardsCertificateService
{

    private $propertyAwardsCertificateRepository;
    private $awardsCertificateCategoryRepository;
    private $propertyAwardsCertificateCreateValidator;
    private $propertyAwardsCertificateUpdateValidator ;
    private $propertyAwardCertificateUploadValidator;
    private $propertyRepository;


    public function __construct(
        PropertyAwardsCertificateRepository $propertyAwardsCertificateRepository,
        PropertyAwardsCertificateCreateValidator $propertyAwardsCertificateCreateValidator,
        PropertyAwardsCertificateUpdateValidator $propertyAwardsCertificateUpdateValidator,
        PropertyAwardCertificateUploadValidator $propertyAwardCertificateUploadValidator,
        PropertyRepository $propertyRepository,
        AwardsCertificateCategoryRepository $awardsCertificateCategoryRepository
    )
    {
        $this->propertyAwardsCertificateRepository = $propertyAwardsCertificateRepository;
        $this->awardsCertificateCategoryRepository = $awardsCertificateCategoryRepository;
        $this->propertyAwardsCertificateCreateValidator = $propertyAwardsCertificateCreateValidator ;
        $this->propertyAwardsCertificateUpdateValidator = $propertyAwardsCertificateUpdateValidator;
        $this->propertyAwardCertificateUploadValidator = $propertyAwardCertificateUploadValidator;
        $this->propertyRepository = $propertyRepository ;
    }

    public function create($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $validationResult = $this->propertyAwardsCertificateCreateValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }
            $filePath = null ;
            $fileType = null ;

            if($params['file']){

                // upload new image ...
                $uploadFile = $this->uploadCertificate($params);
                if ($uploadFile['status'] != 'success') {
                    throw new Exception($uploadFile['message']);
                }

                $filePath = $uploadFile['data']['file_path'] ;
                $fileType = $uploadFile['data']['file_type'] ;

            }

            $insertData = [
                'property_id' => fillOnUndefined($params, 'property_id'),
                'category_id' => fillOnUndefined($params, 'category_id'),
                'language_code' => fillOnUndefined($params, 'language_code'),
                'name' => fillOnUndefined($params, 'name'),
                'date' => fillOnUndefined($params, 'date'),
                'url' => fillOnUndefined($params, 'url'),
                'file_path' => $filePath,
                'file_type' => $fileType,
                "status" => fillOnUndefined($params, "status", 1),
                "created_by" => fillOnUndefined($params, "user_id"),
                "updated_by" => fillOnUndefined($params, "user_id"),
                "created_at" => time(),
                "updated_at" => time(),
            ];

            $createResult = $this->propertyAwardsCertificateRepository->create($insertData);

            if ($createResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $userData = $createResult["data"];
            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function select($params= [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $data = $this->propertyAwardsCertificateRepository->findByCriteria($params, $column);

            $response = [
                'status' => true,
                'data' => $data,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function update($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $validationResult = $this->propertyAwardsCertificateUpdateValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }
            $id = fillOnUndefined($params, 'award_certificate_id') ;
            $filePath = null ;
            $fileType = null ;
            $deleteThisImage = null ;

            $requestCriteria = [
                'criteria' => [
                   // ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['award_certificate_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'firstRow' => 1,
            ];
            $columns = ['id', 'property_id', 'category_id', 'name', 'date', 'url', 'file_path', 'file_type', 'status'];
            $awardCertificate = $this->propertyAwardsCertificateRepository->findByCriteria($requestCriteria,$columns);
            if (!$awardCertificate) {
                throw new Exception('api-unknown_error');
            }
            $fileUpdateData = [];

            if($params['file']){

                // upload new image ...
                $uploadFile = $this->uploadCertificate($params);
                if ($uploadFile['status'] != 'success') {
                    throw new Exception($uploadFile['message']);
                }

                $filePath = $uploadFile['data']['file_path'] ;
                $fileType = $uploadFile['data']['file_type'] ;

                // set delete old image+++++++
                if($awardCertificate['file_path']){
                    $urlPath =  '/property-photos/' . $awardCertificate['property_id'] . "/awards-certificates/";
                    $deleteThisImage = Config::get('app.fileSystemDriver') . $urlPath . $awardCertificate['file_path'];
                }
                $fileUpdateData = [
                    'file_path' => $filePath,
                    'file_type' => $fileType,
                ];
            }

            $updateData = [
                'category_id' => fillOnUndefined($params, 'category_id'),
                'language_code' => fillOnUndefined($params, 'language_code'),
                'name' => fillOnUndefined($params, 'name'),
                'date' => fillOnUndefined($params, 'date'),
                'url' => fillOnUndefined($params, 'url'),
                "updated_by" => fillOnUndefined($params, "user_id"),
                "updated_at" => time(),
            ];
            $updateData = array_merge($updateData, $fileUpdateData) ;

            $updateResult = $this->propertyAwardsCertificateRepository->update($id, $updateData);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $updateData = $updateResult["data"];

            if($deleteThisImage) {
                if (File::exists($deleteThisImage)) {
                    File::delete($deleteThisImage);
                }
            }

            $response = [
                'status' => true,
                'data' => $updateData,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function getCategoryList($params= [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $requestCriteria = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['property_id']]
                ],
                'firstRow' => 1
            ];
            $columns = ['id', 'name', 'country'];
            $property = $this->propertyRepository->findByCriteria($requestCriteria, $columns);

            $requestCriteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'whereOr' => [
                    ['field' => 'country_code', 'condition' => '=', 'value' => $property['country']],
                    ['field' => 'country_code', 'condition' => '=', 'value' => null],
                ],
                'orderBy' => [
                    ["field" => "name", "value" => "ASC"],
                ]

            ];
            $columns = ['id', 'name', 'language_key', 'country_code', 'logo', 'type', 'status'];

            $data = $this->awardsCertificateCategoryRepository->findByCriteria($requestCriteria,$columns);

            $response = [
                'status' => true,
                'data' => $data,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function listAwardsCertificates($params= [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $requestCriteria = [
                'criteria' => [
                //    ['field' => 'status', 'condition' => '=', 'value' => 1]
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']]
                ],
                'with' => ['awardsCertificateCategory']
            ];
            $columns = ['id', 'property_id', 'category_id', 'name',  'language_code', 'date', 'url', 'file_path', 'file_type', 'status'];
            $data = $this->propertyAwardsCertificateRepository->findByCriteria($requestCriteria,$columns);

            $responseData = collect($data)->map(function ($value){
                $return = $value ;
                unset($return['awards_certificate_category']) ;
                $image = null ;

                if($value['file_path']){
                    $urlPath =  '/property-photos/' . $value['property_id'] . "/awards-certificates/";
                    $image = Config::get('app.imageUrl') . $urlPath . $value['file_path'];
                }

                $return['file_path'] = $image ? $image : null ;

                $category = [
                    'category_name' => $value['awards_certificate_category']['name'],
                    'category_language_key' => $value['awards_certificate_category']['language_key'],
                    'category_country_code' => $value['awards_certificate_category']['country_code'],
                    'category_logo' => $value['awards_certificate_category']['logo'],
                    'category_type' => $value['awards_certificate_category']['type'],
                    'category_status' => $value['awards_certificate_category']['status'],
                ];
                return array_merge($return, $category) ;
            })->values()->all() ;

            array_multisort(
                array_column($responseData, 'category_name'), SORT_ASC,
                array_column($responseData, 'id'), SORT_DESC,
                $responseData
            );


            $response = [
                'status' => true,
                'data' => $responseData,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function uploadCertificate($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try
        {
            $fileParam = [] ;
            $validateParams = [
                'file' => $params['file']
            ];

            $validationResult = $this->propertyAwardCertificateUploadValidator->validate($validateParams);
            if ($validationResult->errors()->first()) {
                throw new ApiErrorException($validationResult->errors()->all());
            }

            $filePath = Config::get('app.fileSystemDriver') . '/property-photos/' . $params['property_id'] . "/awards-certificates/";
            if (!File::exists($filePath)) {
                File::makeDirectory($filePath, 0777, true);
            }
            $uploadedFile = $params['file'];
            $fileExt = $uploadedFile->getClientOriginalExtension();
            $fileName = time() . '_'. generateRandomString(10) . '.' . $fileExt;
            $quality = 80 ;

            if(strtolower($fileExt) == 'pdf'){
                $move = $params['file']->move($filePath, $fileName);
                if ($move) {
                    $fileParam =
                        [
                            'file_path' => $fileName,
                            'file_type' => 'PDF',
                        ];
                }
            }else{

                $uploadedOriginalImage =  Image::make($uploadedFile);
                $imageWidth = $uploadedOriginalImage->width() ;
                $imageHeight = $uploadedOriginalImage->height();

                if ($imageHeight > $imageWidth) {

                    if($imageHeight > 768){

                        $imageHRatio = $imageHeight / 768 ;
                        $imageResizedOriginalWidth = intval($imageWidth / $imageHRatio);
                        $image = $uploadedOriginalImage->fit($imageResizedOriginalWidth, 768)->save($filePath . $fileName , $quality) ;
                    }else{
                        $image = $uploadedOriginalImage->save($filePath . $fileName , $quality) ;
                    }

                } else {

                    if($imageWidth > 1024) {
                        $imageWRatio = $imageWidth / 1024 ;
                        $imageResizedOriginalHeight = intval($imageHeight / $imageWRatio);
                        $image = $uploadedOriginalImage->fit(1024, $imageResizedOriginalHeight)->save($filePath . $fileName , $quality) ;
                    }else{
                        $image = $uploadedOriginalImage->save($filePath . $fileName , $quality) ;
                    }
                }

                $fileParam =
                    [
                        'file_path' => $fileName,
                        'file_type' => 'IMG',
                    ];
                $uploadedOriginalImage->destroy();
            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $fileParam];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
            $response['data'] = '';
            $response['statusCode'] = 400;
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            $response['data'] = '';
            $response['statusCode'] = 400;
        }

        return output($response);
    }

    public function deletePhotoAwardsCertificates($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $requestCriteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['award_certificate_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'firstRow' => 1,
            ];
            $columns = ['id', 'property_id', 'category_id', 'name', 'date', 'url', 'file_path', 'file_type', 'status'];
            $awardCertificate = $this->propertyAwardsCertificateRepository->findByCriteria($requestCriteria,$columns);
            if (!$awardCertificate) {
                throw new Exception('api-unknown_error');
            }

            $urlPath =  '/property-photos/' . $awardCertificate['property_id'] . "/awards-certificates/";
            $deleteThisImage = Config::get('app.fileSystemDriver') . $urlPath . $awardCertificate['file_path'];

            if($deleteThisImage) {
                if (File::exists($deleteThisImage)) {
                    File::delete($deleteThisImage);
                }
            }

            $id = $awardCertificate['id'] ;
            $updateData = [
                'file_path' => null,
                'file_type' => null,
                "updated_by" => fillOnUndefined($params, "user_id"),
                "updated_at" => time(),
            ];

            $updateResult = $this->propertyAwardsCertificateRepository->update($id, $updateData);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $response = [
                'status' => true,
                'data' => null,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }

    public function updateStatus($param = [])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $updateId = fillOnUndefined($param, "award_certificate_id") ;
            $placeRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($param, 'property_id')],
                    ['field' => 'id', 'condition' => '=', 'value' => $updateId],
                ]
            ];
            $propertyWebData = $this->propertyAwardsCertificateRepository->findByCriteria($placeRequest, ['id', 'name']);

            if (!$propertyWebData) {
                throw new Exception('api-unknown_error');
            }

            $updateData =
                [
                    "status" => fillOnUndefined($param, "set_status", 0),
                    "updated_by" => fillOnUndefined($param, "user_id"),
                    "updated_at" => time(),
                ];

            $updateResult = $this->propertyAwardsCertificateRepository->update($updateId, $updateData);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $response = [
                'status' => true,
                'data' => null,
            ];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }

        return output($response);
    }


}
