Your IP : 216.73.216.145


Current Path : /home/users/unlimited/www/admin.eclassify.codeskitter.site/app/Http/Controllers/
Upload File :
Current File : /home/users/unlimited/www/admin.eclassify.codeskitter.site/app/Http/Controllers/ItemController.php

<?php

namespace App\Http\Controllers;

use App\Models\Category;
use App\Models\City;
use App\Models\Country;
use App\Models\CustomField;
use App\Models\CustomFieldCategory;
use App\Models\Item;
use App\Models\ItemCustomFieldValue;
use App\Models\ItemImages;
use App\Models\State;
use App\Models\UserFcmToken;
use App\Services\BootstrapTableService;
use App\Services\FileService;
use App\Services\HelperService;
use App\Services\NotificationService;
use App\Services\ResponseService;
use Carbon\Carbon;
use DB;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;
use Str;
use Throwable;
use Validator;

class ItemController extends Controller {

    public function index() {
        ResponseService::noAnyPermissionThenRedirect(['advertisement-list', 'advertisement-update', 'advertisement-delete']);
        $countries = Country::all();
        $cities = City::all();
        return view('items.index' ,compact('countries','cities'));
    }

    public function show($status , Request $request) {
        try {
            ResponseService::noPermissionThenSendJson('advertisement-list');
            $offset = $request->input('offset', 0);
            $limit = $request->input('limit', 10);
            $sort = $request->input('sort', 'id');
            $order = $request->input('order', 'ASC');
            $sql = Item::with(['custom_fields', 'category:id,name', 'user:id,name', 'gallery_images','featured_items'])->withTrashed();
            if (!empty($request->search)) {
                $sql = $sql->search($request->search);
            }




            if ($status == 'approved') {
                $sql->where('status', 'approved')->getNonExpiredItems()->whereNull('items.deleted_at');
            } elseif ($status == 'requested') {
                $sql->where('status', '!=', 'approved')
                    ->orWhere(function ($query) {
                        $query->where('status', 'approved')
                              ->whereNotNull('expiry_date')
                              ->where('expiry_date', '<', Carbon::now())
                              ->orWhereNotNull('items.deleted_at');
                    });
            }
            if (!empty($request->filter)) {
                $sql = $sql->filter(json_decode($request->filter, false, 512, JSON_THROW_ON_ERROR));
            }

            $total = $sql->count();
            $sql = $sql->sort($sort, $order)->skip($offset)->take($limit);
            $result = $sql->get();
            $bulkData = array();
            $bulkData['total'] = $total;
            $rows = array();

            $itemCustomFieldValues = ItemCustomFieldValue::whereIn('item_id', $result->pluck('id'))->get();
            foreach ($result as $row) {
                /* Merged ItemCustomFieldValue's data to main data */
                $itemCustomFieldValue = $itemCustomFieldValues->filter(function ($data) use ($row) {
                    return $data->item_id == $row->id;
                });
                $featured_status = $row->featured_items->isNotEmpty() ? 'Featured' : 'Premium';
                $row->custom_fields = collect($row->custom_fields)->map(function ($customField) use ($itemCustomFieldValue) {
                    $customField['value'] = $itemCustomFieldValue->first(function ($data) use ($customField) {
                        return $data->custom_field_id == $customField->id;
                    });

                    if ($customField->type == "fileinput" && !empty($customField['value']->value)) {
                        if (!is_array($customField->value)) {
                            $customField['value'] = !empty($customField->value) ? [url(Storage::url($customField->value))] : [];
                        } else {
                            $customField['value'] = null;
                        }
//                        $customField['value']->value = url(Storage::url($customField['value']->value));
                    }
                    return $customField;
                });
                $tempRow = $row->toArray();
                $operate = '';
                if (count($row->custom_fields) > 0 && Auth::user()->can('advertisement-list')) {
                    // View Custom Field
                    $operate .= BootstrapTableService::button('fa fa-eye', '#', ['editdata', 'btn-light-danger  '], ['title' => __("View"), "data-bs-target" => "#editModal", "data-bs-toggle" => "modal",]);
                }

                if ($row->status !== 'sold out' && Auth::user()->can('advertisement-update')) {
                    $operate .= BootstrapTableService::editButton(route('advertisement.approval', $row->id), true, '#editStatusModal', 'edit-status', $row->id);
                }
                  if (Auth::user()->can('advertisement-update')) {
                    $operate .= BootstrapTableService::button('fa fa-wrench', route('advertisement.edit', $row->id), ['btn', 'btn-light-warning'], ['title' => __('Advertisement Update')]);
                }
                if (Auth::user()->can('advertisement-delete')) {
                    $operate .= BootstrapTableService::deleteButton(route('advertisement.destroy', $row->id));
                }
                $tempRow['active_status'] = empty($row->deleted_at);//IF deleted_at is empty then status is true else false
                $tempRow['featured_status'] = $featured_status;
                $tempRow['operate'] = $operate;

                $rows[] = $tempRow;
            }
            $bulkData['rows'] = $rows;
            return response()->json($bulkData);

        } catch (Throwable $th) {
            ResponseService::logErrorResponse($th, "ItemController --> show");
            ResponseService::errorResponse();
        }
    }
    public function updateItemApproval(Request $request, $id) {
        try {
            ResponseService::noPermissionThenSendJson('advertisement-update');
            $item = Item::with('user')->withTrashed()->findOrFail($id);
            $item->update([
                ...$request->all(),
                'rejected_reason' => ($request->status == "soft rejected" || $request->status == "permanent rejected") ? $request->rejected_reason : ''
            ]);
            $user_token = UserFcmToken::where('user_id', $item->user->id)->pluck('fcm_token')->toArray();
            if (!empty($user_token)) {
                NotificationService::sendFcmNotification($user_token, 'About ' . $item->name, "Your Advertisement is " . ucfirst($request->status), "item-update", ['id' => $request->id,]);
            }
            ResponseService::successResponse('Advertisement Status Updated Successfully');
        } catch (Throwable $th) {
            ResponseService::logErrorResponse($th, 'ItemController ->updateItemApproval');
            ResponseService::errorResponse('Something Went Wrong');
        }
    }

    public function destroy($id) {
        ResponseService::noPermissionThenSendJson('advertisement-delete');

        try {
            $item = Item::with('gallery_images')->withTrashed()->findOrFail($id);
            foreach ($item->gallery_images as $gallery_image) {
                FileService::delete($gallery_image->getRawOriginal('image'));
            }
            FileService::delete($item->getRawOriginal('image'));

            $item->forceDelete();

            ResponseService::successResponse('Advertisement deleted successfully');
        } catch (Throwable $th) {
            ResponseService::logErrorResponse($th);
            ResponseService::errorResponse('Something went wrong');
        }
    }
    public function requestedItem() {
        ResponseService::noAnyPermissionThenRedirect(['advertisement-list', 'advertisement-update', 'advertisement-delete']);
        $countries = Country::all();
        $cities = City::all();
        return view('items.requested_item' ,compact('countries','cities'));
    }
    public function searchCities(Request $request)
    {
        $countryName = trim($request->query('country_name'));
        if ($countryName == 'All') {
            return response()->json(['message' => 'Success', 'data' => []]);
        }
        $country = Country::where('name', $countryName)->first();
        if (!$country) {
            return response()->json(['message' => 'Success', 'data' => []]);
        }
        $cities = City::where('country_id', $country->id)->get();
        return response()->json(['message' => 'Success', 'data' => $cities]);
    }
    public function editForm($id)
            {
                $item = Item::with(
                    'user:id,name,email,mobile,profile,country_code',
                    'category.custom_fields', // get custom fields from category
                    'gallery_images:id,image,item_id',
                    'featured_items',
                    'favourites',
                    'item_custom_field_values.custom_field',
                    'area'
                )->findOrFail($id);

                   $categories = Category::whereNull('parent_category_id')
                    ->with([
                        'custom_fields', // level 0
                        'subcategories.custom_fields', // level 1
                        'subcategories.subcategories.custom_fields', // level 2
                        'subcategories.subcategories.subcategories.custom_fields', // level 3
                        'subcategories.subcategories.subcategories.subcategories.custom_fields', // level 4 (optional)
                    ])
                    ->get();


                    $customFieldCategories = CustomFieldCategory::with('custom_fields')
                    ->where('category_id', $item->category_id)
                    ->get();

                    // Get saved custom field values for this item
                    $savedValues = ItemCustomFieldValue::where('item_id', $item->id)->get()->keyBy('custom_field_id');


                    // Build the custom fields array with values
                $custom_fields = $customFieldCategories->map(function ($relation) use ($savedValues) {
            $field = $relation->custom_fields;
            if (!$field) return null;

            $value = $savedValues->get($field->id)->value ?? null;

            if ($field->type === 'fileinput') {
                $field->value = $value ? [url(Storage::url($value))] : [];
            } else {
                if (is_array($value)) {
                    if (in_array($field->type, ['textbox', 'number'])) {
                        $field->value = implode(', ', $value);
                    } else {
                        $field->value = $value;
                    }
                } elseif (is_string($value)) {
                    $decodedValue = json_decode($value, true);
                    if (is_array($decodedValue)) {
                        if (in_array($field->type, ['textbox', 'number'])) {
                            $field->value = implode(', ', $decodedValue);
                        } else {
                            $field->value = $decodedValue;
                        }
                    } else {
                        $field->value = $decodedValue ?? $value;
                    }
                } else {
                    $field->value = '';
                }
            }

        // Fix for dropdown and radio: ensure $field->value is string
        if (in_array($field->type, ['dropdown', 'radio'])) {
            if (is_array($field->value)) {
                $field->value = count($field->value) > 0 ? (string)$field->value[0] : '';
            } elseif (is_object($field->value)) {
                $field->value = '';
            }
        }

        return $field;
    })->filter();
                $countries = Country::all();
                    $states = State::get();
                    $cities = city::get();
                $selected_category = [$item->category_id];
                return view('items.update', compact('item', 'categories', 'custom_fields', 'selected_category','countries','states','cities'));
        }

    public function update(Request $request, $id)
      {
        ResponseService::noPermissionThenSendJson('advertisement-update');
        // Validate input
        $validator = Validator::make($request->all(), [
            'name'                 => 'required|string|max:255',
            'slug'                 => 'nullable|regex:/^[a-z0-9-]+$/',
            'price'                => 'required|numeric|min:0',
            'description'          => 'nullable|string',
            'latitude'             => 'nullable',
            'longitude'            => 'nullable',
            'address'              => 'nullable',
            'contact'              => 'nullable',
            'image'                => 'nullable|mimes:jpeg,jpg,png|max:7168',
            'custom_fields'        => 'nullable',
            'custom_field_files'   => 'nullable|array',
            'custom_field_files.*' => 'nullable|mimes:jpeg,png,jpg,pdf,doc|max:7168',
            'gallery_images'       => 'nullable|array',
            'admin_edit_reason'    => 'required|string|max:1000',
        ]);

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        DB::beginTransaction();
        try {
            $item = Item::findOrFail($id);

            $category = Category::findOrFail($request->category_id);
                $isJobCategory = $category->is_job_category;
                $isPriceOptional = $category->price_optional;

                if ($isJobCategory || $isPriceOptional) {
                    $validator = Validator::make($request->all(), [
                        'min_salary' => 'nullable|numeric|min:0',
                        'max_salary' => 'nullable|numeric|gte:min_salary',
                    ]);
                } else {
                    $validator = Validator::make($request->all(), [
                        'price' => 'required|numeric|min:0',
                    ]);
                }

           $customFieldCategories = CustomFieldCategory::with('custom_fields')
                ->where('category_id', $request->category_id)
                ->get();

            $customFieldErrors = [];
            foreach ($customFieldCategories as $relation) {
                $field = $relation->custom_fields;
                if (empty($field) || $field->required != 1) continue;
                $fieldId = $field->id;
                $fieldLabel = $field->name;

                if (in_array($field->type, ['textbox', 'number', 'dropdown', 'radio'])) {
                    if (empty($request->input("custom_fields.$fieldId"))) {
                        $customFieldErrors["custom_fields.$fieldId"] = "The $fieldLabel field is required.";
                    }
                }

                if ($field->type === 'checkbox') {
                    if (!is_array($request->input("custom_fields.$fieldId")) || empty($request->input("custom_fields.$fieldId"))) {
                        $customFieldErrors["custom_fields.$fieldId"] = "The $fieldLabel field is required.";
                    }
                }

                if ($field->type === 'fileinput') {
                    $existing = ItemCustomFieldValue::where([
                        'item_id' => $id,
                        'custom_field_id' => $fieldId
                    ])->first();

                    if (!$request->hasFile("custom_field_files.$fieldId") && empty($existing?->value)) {
                        $customFieldErrors["custom_field_files.$fieldId"] = "The $fieldLabel file is required.";
                    }
                }
            }
            if (!empty($customFieldErrors)) {
                return back()->withErrors($customFieldErrors)->withInput();
            }

            $data = array_merge($request->all(), [
                'is_edited_by_admin' => 1,
                'admin_edit_reason' => $request->admin_edit_reason,
            ]);

            // $data['slug'] = $uniqueSlug;
           $manualAddress = $request->input('manual_address');

            if ($manualAddress) {
                $data['address'] = $manualAddress;
                $city = City::find($request->city);
                $state = State::find($request->state);
                $country = Country::find($request->country);

                $data['country']   = $country?->name ?? $request->country;
                $data['state']     = $state?->name ?? $request->state;
                $data['city']      = $city?->name ?? $request->city;
                $data['latitude']  = $city?->latitude ?? null;
                $data['longitude'] = $city?->longitude ?? null;
            } else {
                $data['address'] = $request->input('address_input');
                $data['country'] = $request->input('country_input');
                $data['state']   = $request->input('state_input');
                $data['city']    = $request->input('city_input');
                $data['latitude'] = $request->input('latitude');
                $data['longitude'] = $request->input('longitude');
            }
            // Handle main image
            if ($request->hasFile('image')) {
                $data['image'] = FileService::compressAndReplace($request->file('image'), 'uploads/items', $item->getRawOriginal('image'));
            }

            // Update item
                 $item->update($data);

                if ($request->custom_fields) {
                    $itemCustomFieldValues = [];
                    foreach ($request->custom_fields  as $key => $custom_field) {
                      $value = is_array($custom_field) ? $custom_field : [$custom_field];

                        $itemCustomFieldValues[] = [
                            'item_id'         => $item->id,
                            'custom_field_id' => $key,
                            'value'           => json_encode($value, JSON_THROW_ON_ERROR), // ✅ encode to string
                            'updated_at'      => now()
                        ];
                    }
                    if (!empty($itemCustomFieldValues)) {
                        ItemCustomFieldValue::upsert($itemCustomFieldValues, ['item_id', 'custom_field_id'], ['value', 'updated_at']);
                    }
                }
                if ($request->hasFile('custom_field_files')) {
                    $itemCustomFieldValues = [];
                    foreach ($request->file('custom_field_files') as $key => $file) {
                        $value = ItemCustomFieldValue::where(['item_id' => $item->id, 'custom_field_id' => $key])->first();

                        $path = $value
                            ? FileService::replace($file, 'custom_fields_files', $value->getRawOriginal('value'))
                            : FileService::upload($file, 'custom_fields_files');

                        $itemCustomFieldValues[] = [
                            'item_id'         => $item->id,
                            'custom_field_id' => $key,
                            'value'           => $path,
                            'updated_at'      => now()
                        ];
                    }

                    if (!empty($itemCustomFieldValues)) {
                        ItemCustomFieldValue::upsert($itemCustomFieldValues, ['item_id', 'custom_field_id'], ['value', 'updated_at']);
                    }
                }


            // Add gallery images
            if ($request->hasFile('gallery_images')) {
                $galleryImages = [];
                foreach ($request->file('gallery_images') as $file) {
                    $galleryImages[] = [
                        'image'      => FileService::compressAndUpload($file, 'uploads/items'),
                        'item_id'    => $item->id,
                        'created_at' => time(),
                        'updated_at' => time(),
                    ];
                }
                if (count($galleryImages) > 0) {
                    ItemImages::insert($galleryImages);
                }
            }

            // Custom field files
           foreach ($request->allFiles() as $key => $file) {
                if (Str::startsWith($key, 'custom_fields.')) {
                    $customFieldId = Str::after($key, 'custom_fields.');
                    $value = ItemCustomFieldValue::where(['item_id' => $item->id, 'custom_field_id' => $customFieldId])->first();

                    if ($value) {
                        $filePath = FileService::replace($file, 'custom_fields_files', $value->getRawOriginal('value'));
                    } else {
                        $filePath = FileService::upload($file, 'custom_fields_files');
                    }

                    ItemCustomFieldValue::updateOrCreate(
                        ['item_id' => $item->id, 'custom_field_id' => $customFieldId],
                        ['value' => $filePath, 'updated_at' => now()]
                    );
                }
            }

            // Delete gallery images if needed
            if (!empty($request->delete_item_image_id)) {
                $itemImageIds = explode(',', $request->delete_item_image_id);
                foreach (ItemImages::whereIn('id', $itemImageIds)->get() as $itemImage) {
                    FileService::delete($itemImage->getRawOriginal('image'));
                    $itemImage->delete();
                }
            }

            DB::commit();
            $isApproved = $item->status === 'approved';
            $isNonExpired = $item->expired_at === null || $item->expired_at > now();
            $isNotDeleted = $item->deleted_at === null;
            $user_token = UserFcmToken::where('user_id', $item->user->id)->pluck('fcm_token')->toArray();
            if (!empty($user_token)) {
                NotificationService::sendFcmNotification($user_token, 'About ' . $item->name, "Your Advertisement is edited by admin" ,"item-edit", ['id' => $request->id,]);
            }

            if ($isApproved && $isNonExpired && $isNotDeleted) {
                 ResponseService::successRedirectResponse("Advertisement Updated Successfully", route('advertisement.index'));
            } else {
                 ResponseService::successRedirectResponse("Advertisement Updated Successfully", route('advertisement.requested.index'));
            }
        } catch (Throwable $th) {
            DB::rollBack();
            report($th);
            return redirect()->back()->with('error', 'An error occurred while updating the item.');
        }
    }
        public function getCustomFields($categoryId)
        {
            $fields = $this->getFieldsRecursively($categoryId);
            $category = Category::findOrFail($categoryId);

            return response()->json(['fields' => $fields,
            'is_job_category' => $category->is_job_category,
            'price_optional' => $category->price_optional,
        ]);
        }
        protected function getFieldsRecursively($categoryId)
        {
            $customFieldCategories = CustomFieldCategory::with('custom_fields')
                ->where('category_id', $categoryId)
                ->get();

              $fields = $customFieldCategories->map(function ($relation) {
            return $relation->custom_fields; // it's a single object per category
                })->filter()->values();

            if ($fields) {
                return $fields;
            }

            $category = Category::find($categoryId);

            if ($category && $category->parent_category_id) {
                return $this->getFieldsRecursively($category->parent_category_id);
            }
            return collect();
        }




}