<?php

namespace App\Service\Vendor;

use App\Http\Requests\Vendor\CreateVendorServiceRequest;
use App\Http\Requests\Vendor\UpdateVendorServiceRequest;
use App\Http\Resources\VendorServiceResource;
use App\Http\Resources\ServiceItemResource;
use App\Models\VendorService;
use App\Models\VendorServiceFeature;
use App\Models\Vendor;
use App\Traits\JsonResponseTrait;
use App\Traits\PaginationResponseTrait;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class VendorServiceService
{
    use JsonResponseTrait, PaginationResponseTrait;

    /**
     * Get all vendor services with search, sort, filter and pagination
     */
    public function getAllServices(array $filters = [])
    {
        $query = VendorService::with(['features.featureOption.featureType', 'serviceItem.serviceCategory', 'vendor']);

        // Search functionality - search across multiple fields
        if (!empty($filters['search'])) {
            $searchTerm = $filters['search'];
            $query->where(function ($q) use ($searchTerm) {
                $q->where('name', 'LIKE', "%{$searchTerm}%")
                    ->orWhere('description', 'LIKE', "%{$searchTerm}%")
                    ->orWhereHas('vendor', function ($vendorQuery) use ($searchTerm) {
                        $vendorQuery->where('firstname', 'LIKE', "%{$searchTerm}%")
                            ->orWhere('lastname', 'LIKE', "%{$searchTerm}%");
                    })
                    ->orWhereHas('serviceItem', function ($serviceQuery) use ($searchTerm) {
                        $serviceQuery->where('name', 'LIKE', "%{$searchTerm}%");
                    });
            });
        }

        // Filter by vendor
        if (!empty($filters['vendor_id'])) {
            $query->byVendor($filters['vendor_id']);
        }

        // Filter by service item
        if (!empty($filters['service_item_id'])) {
            $query->byServiceItem($filters['service_item_id']);
        }

        // Filter by active status
        if (isset($filters['is_active'])) {
            $query->where('is_active', (bool) $filters['is_active']);
        }

        // Filter by category through service item
        if (!empty($filters['category'])) {
            $query->whereHas('serviceItem.serviceCategory', function ($q) use ($filters) {
                $q->where('name', 'LIKE', "%{$filters['category']}%");
            });
        }

        // Filter by price range
        if (!empty($filters['min_price'])) {
            $query->where('price', '>=', $filters['min_price']);
        }

        if (!empty($filters['max_price'])) {
            $query->where('price', '<=', $filters['max_price']);
        }

        // Date range filtering
        if (!empty($filters['created_from'])) {
            $query->whereDate('created_at', '>=', $filters['created_from']);
        }

        if (!empty($filters['created_to'])) {
            $query->whereDate('created_at', '<=', $filters['created_to']);
        }

        // Sorting functionality
        $sortBy = $filters['sort_by'] ?? 'created_at';
        $sortOrder = $filters['sort_order'] ?? 'desc';

        // Validate sort column to prevent SQL injection
        $allowedSortColumns = ['name', 'price', 'created_at', 'updated_at', 'production_days'];
        if (!in_array($sortBy, $allowedSortColumns)) {
            $sortBy = 'created_at';
        }

        // Validate sort order
        $sortOrder = in_array(strtolower($sortOrder), ['asc', 'desc']) ? $sortOrder : 'desc';

        $query->orderBy($sortBy, $sortOrder);

        // Use the pagination trait for consistent response format
        return $this->paginatedResponse(
            VendorServiceResource::class,
            $query,
            [],
            'Services retrieved successfully'
        );
    }

    /**
     * Get a specific vendor service by ID
     */
    public function getServiceById($serviceId)
    {
        $service = VendorService::with(['features.featureOption.featureType', 'serviceItem.serviceCategory', 'vendor'])
            ->find($serviceId);

        if (!$service) {
            return $this->errorResponse(statusCode: 404, message: 'Service not found');
        }

        return $this->successDataResponse(
            data: $service,
            message: 'Service retrieved successfully'
        );
    }

    /**
     * Create a new vendor service
     */
    public function createService(Vendor $vendor, CreateVendorServiceRequest $request)
    {
        DB::beginTransaction();

        try {
            $data = $request->validated();
            $data['vendor_id'] = $vendor->id;

            // Generate slug if not provided
            if (empty($data['slug'])) {
                $data['slug'] = Str::slug($data['name']);
            }

            $service = VendorService::create($data);

            // Create vendor service features if provided
            if (isset($data['features']) && is_array($data['features'])) {
                foreach ($data['features'] as $featureData) {
                    $featureData['vendor_service_id'] = $service->id;
                    VendorServiceFeature::create($featureData);
                }
            }

            DB::commit();

            return $this->successDataResponse(
                data: $service->load(['features.featureOption.featureType', 'serviceItem.serviceCategory']),
                message: 'Service created successfully'
            );
        } catch (\Exception $e) {
            DB::rollBack();

            Log::error('Failed to create vendor service: ' . $e->getMessage(), [
                'vendor_id' => $vendor->id,
                'request_data' => $request->validated(),
                'exception' => $e,
            ]);

            return $this->errorResponse(statusCode: 500, message: 'Failed to create service. Please try again.');
        }
    }

    /**
     * Update an existing vendor service
     */
    public function updateService(VendorService $service, UpdateVendorServiceRequest $request)
    {
        DB::beginTransaction();

        try {
            $data = $request->validated();

            // Update service details
            $service->update($data);

            // Update vendor service features if provided
            if (isset($data['features']) && is_array($data['features'])) {
                // Delete existing features not in the update
                $existingFeatureIds = array_filter(array_column($data['features'], 'id'));
                if (!empty($existingFeatureIds)) {
                    $service->features()->whereNotIn('id', $existingFeatureIds)->delete();
                } else {
                    $service->features()->delete();
                }

                // Update or create new features
                foreach ($data['features'] as $featureData) {
                    if (isset($featureData['id'])) {
                        VendorServiceFeature::where('id', $featureData['id'])
                            ->where('vendor_service_id', $service->id)
                            ->update($featureData);
                    } else {
                        $featureData['vendor_service_id'] = $service->id;
                        VendorServiceFeature::create($featureData);
                    }
                }
            }

            DB::commit();

            return $this->successDataResponse(
                data: $service->load(['features.featureOption.featureType', 'serviceItem.serviceCategory']),
                message: 'Service updated successfully'
            );
        } catch (\Exception $e) {
            DB::rollBack();

            Log::error('Failed to update vendor service: ' . $e->getMessage(), [
                'service_id' => $service->id,
                'request_data' => $request->validated(),
                'exception' => $e,
            ]);

            return $this->errorResponse(statusCode: 500, message: 'Failed to update service. Please try again.');
        }
    }

    /**
     * Delete a vendor service
     */
    public function deleteService(VendorService $service)
    {
        DB::beginTransaction();

        try {
            $service->delete();

            DB::commit();

            return $this->successResponse(message: 'Service deleted successfully');
        } catch (\Exception $e) {
            DB::rollBack();

            Log::error('Failed to delete vendor service: ' . $e->getMessage(), [
                'service_id' => $service->id,
                'exception' => $e,
            ]);

            return $this->errorResponse(statusCode: 500, message: 'Failed to delete service. Please try again.');
        }
    }

    /**
     * Toggle service active status
     */
    public function toggleActive(VendorService $service)
    {
        $service->update(['is_active' => !$service->is_active]);

        return $this->successResponse(message: 'Service status updated successfully');
    }

    /**
     * Get available service items for vendors with search, sort, filter and pagination (Printing & Branding only)
     */
    public function getAvailableServiceItems(array $filters = [])
    {
        $query = \App\Models\ServiceItem::with(['serviceCategory', 'features.featureTypes'])
            ->whereHas('serviceCategory', function ($query) {
                $query->where('name', 'Printing & Branding');
            })
            ->where('is_active', true);

        // Search functionality
        if (!empty($filters['search'])) {
            $searchTerm = $filters['search'];
            $query->where(function ($q) use ($searchTerm) {
                $q->where('name', 'LIKE', "%{$searchTerm}%")
                    ->orWhere('description', 'LIKE', "%{$searchTerm}%")
                    ->orWhereHas('serviceCategory', function ($categoryQuery) use ($searchTerm) {
                        $categoryQuery->where('name', 'LIKE', "%{$searchTerm}%");
                    });
            });
        }

        // Filter by category
        if (!empty($filters['category'])) {
            $query->whereHas('serviceCategory', function ($q) use ($filters) {
                $q->where('name', $filters['category']);
            });
        }

        // Date range filtering
        if (!empty($filters['created_from'])) {
            $query->whereDate('created_at', '>=', $filters['created_from']);
        }

        if (!empty($filters['created_to'])) {
            $query->whereDate('created_at', '<=', $filters['created_to']);
        }

        // Sorting functionality
        $sortBy = $filters['sort_by'] ?? 'name';
        $sortOrder = $filters['sort_order'] ?? 'asc';

        // Validate sort column to prevent SQL injection
        $allowedSortColumns = ['name', 'created_at', 'updated_at'];
        if (!in_array($sortBy, $allowedSortColumns)) {
            $sortBy = 'name';
        }

        // Validate sort order
        $sortOrder = in_array(strtolower($sortOrder), ['asc', 'desc']) ? $sortOrder : 'asc';

        $query->orderBy($sortBy, $sortOrder);

        // Use the pagination trait for consistent response format
        return $this->paginatedResponse(
            ServiceItemResource::class,
            $query,
            [],
            'Available service items retrieved successfully'
        );
    }

    /**
     * Get feature options for a specific service item
     */
    public function getServiceItemFeatures($serviceItemId)
    {
        $serviceItem = \App\Models\ServiceItem::with(['features.featureTypes.options'])
            ->findOrFail($serviceItemId);

        // Ensure it's under Printing & Branding
        if ($serviceItem->serviceCategory->name !== 'Printing & Branding') {
            return $this->errorResponse(statusCode: 403, message: 'Service item not allowed');
        }

        return $this->successDataResponse(
            data: $serviceItem,
            message: 'Service item features retrieved successfully'
        );
    }
}
