<?php

namespace App\Http\Controllers;

use App\Models\Vendor;
use Maatwebsite\Excel\Facades\Excel;
use App\Models\User;
use App\Imports\PricingImport;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
class VendorsController extends Controller


{
public function storeVendor(Request $request)
{
    // Validate input
    $validator = Validator::make($request->all(), [
        'name' => 'required|string|max:255',
        'email' => 'required|email|unique:users,email',
        'phone_number' => 'required|string|regex:/^[0-9]{10}$/|unique:users,phone_number',
        'role' => 'nullable|string|in:user,vendor,driver,admin',
        'store_name' => 'required|string|max:255',
        'complete_address' => 'required|string',
        'gstin' => 'required|string|unique:vendors,gstin',
        'longitude' => 'required|numeric',
        'latitude' => 'required|numeric',
        'services' => 'required',  // Expecting services in array format
        'pan' => 'required|string|size:10|unique:vendors,pan',
        'store_adhar.*' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
        'store_documents.*' => 'nullable|mimes:pdf,jpeg,png|max:2048',
        'store_pictures.*' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
        'store_selfies.*' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
        'profile_image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
        'opening_hours' => 'nullable|json',
    ]);

    if ($validator->fails()) {
        return redirect()->back()->with('error', 'Validation failed: ' . $validator->errors()->first());
    }

    $validatedData = $validator->validated();

    // Convert `services` array into an associative array format
    $services = $validatedData['services'];
    $serviceObject = [];
    if (is_array($services)) {
        foreach ($services as $index => $service) {
            $serviceObject['service' . ($index + 1)] = $service;
        }
    }

    // Generate a unique user ID
    $user_id = $this->generateUniqueId('vendor');

    // Create user record
    $newUser = User::create([
    'user_id' => $user_id,
    'name' => $validatedData['name'],
    'email' => $validatedData['email'],
    'phone_number' => $validatedData['phone_number'],
    'role' => 'vendor',  // Always set role as 'vendor'
]);


    // Create vendor record
    $vendor = new Vendor();
    $vendor->user_id = $newUser->user_id;
    $vendor->gstin = $validatedData['gstin'];
    $vendor->pan = $validatedData['pan'];
    $vendor->store_name = $validatedData['store_name'];
    $vendor->complete_address = $validatedData['complete_address'];
    $vendor->longitude = $validatedData['longitude'];
    $vendor->latitude = $validatedData['latitude'];
    $vendor->services = $serviceObject;

    // Default opening hours if not provided
    $defaultOpeningHours = [
        "Monday" => "09:00-17:00",
        "Tuesday" => "09:00-17:00",
        "Wednesday" => "09:00-17:00",
        "Thursday" => "09:00-17:00",
        "Friday" => "09:00-17:00",
        "Saturday" => "09:00-17:00",
        "Sunday" => "09:00-17:00"
    ];

    // Merge with provided opening hours
    $openingHours = json_decode($validatedData['opening_hours'] ?? '{}', true);
    $vendor->opening_hours = array_merge($defaultOpeningHours, $openingHours);

    // Handle file uploads
    $this->handleFileUploads($request, $vendor);

    // Save vendor record
    $vendor->save();

   return redirect()->back()->with('success', 'Vendor  saved successfully');

}




// Method to generate the unique user_id
private function generateUniqueId($role)
{
    $prefix = '';
    switch ($role) {
        case 'vendor':
            $prefix = 'CleaneoVendor';
            break;
        case 'driver':
            $prefix = 'CleaneoAgent';
            break;
        case 'admin':
            $prefix = 'CleaneoAdmin';
            break;
        default:
            $prefix = 'Cleaneo';
            break;
    }

    // Get the latest user of the same role
    $latestUser = DB::table('users')
                    ->where('role', $role)
                    ->orderBy('id', 'desc')
                    ->first();

    $lastId = 0;
    if ($latestUser) {
        $lastId = (int)substr($latestUser->user_id, strlen($prefix));
    }

    // Increment the ID and format it to always have a leading zero (4 digits for vendor)
    $newId = $lastId + 1;
    $formattedId = str_pad($newId, 6, '0', STR_PAD_LEFT);

    return $prefix . $formattedId;
}



public function updateOpeningHours(Request $request, $vendorId)
{
    // Validation rules
    $validator = Validator::make($request->all(), [
        'opening_hours' => 'required|json',
    ]);

    // Return validation errors if any
    if ($validator->fails()) {
        return response()->json([
            'success' => false,
            'errors' => $validator->errors(),
        ], 400);
    }

    // Fetch the vendor by user_id using Query Builder
    $vendor = DB::table('vendors')->where('user_id', $vendorId)->first();

    if (!$vendor) {
        return response()->json([
            'success' => false,
            'message' => 'Vendor not found.',
        ], 404);
    }

    // Decode opening hours from the request
    $openingHours = json_decode($request->opening_hours, true);

    // Ensure opening hours are valid
    if (!is_array($openingHours)) {
        return response()->json([
            'success' => false,
            'message' => 'Invalid opening hours format.',
        ], 400);
    }

    // Update only the opening_hours field using Query Builder
    $updated = DB::table('vendors')->where('user_id', $vendorId)->update([
        'opening_hours' => json_encode($openingHours),
    ]);

    if ($updated) {
        return response()->json([
            'success' => true,
            'message' => 'Opening hours updated successfully.',
            'opening_hours' => $openingHours,
        ], 200);
    } else {
        return response()->json([
            'success' => false,
            'message' => 'Failed to update opening hours.',
        ], 500);
    }
}

    private function deleteOldImages(Vendor $vendor)
    {
        // Delete old images if they exist
        $this->deleteFilesFromJson($vendor->store_adhar);
        $this->deleteFilesFromJson($vendor->store_documents);
        $this->deleteFilesFromJson($vendor->store_pictures);
        $this->deleteFilesFromJson($vendor->store_selfies);
        if ($vendor->profile_image) {
            Storage::disk('public')->delete(json_decode($vendor->profile_image));
        }
    }

    private function deleteFilesFromJson($json)
    {
        if ($json) {
            foreach (json_decode($json) as $file) {
                Storage::disk('public')->delete($file);
            }
        }
    }

    private function handleFileUploads(Request $request, Vendor $vendor)
    {
        // Define the vendor-specific directory in the public storage
        $vendorDirectory = 'vendors/';

        // Handle file uploads
        if ($request->hasFile('store_adhar')) {
            $vendor->store_adhar = $this->uploadFiles($request->file('store_adhar'), $vendorDirectory, 'adhar');
        }

        if ($request->hasFile('store_documents')) {
            $vendor->store_documents = $this->uploadFiles($request->file('store_documents'), $vendorDirectory, 'documents');
        }

        if ($request->hasFile('store_pictures')) {
            $vendor->store_pictures = $this->uploadFiles($request->file('store_pictures'), $vendorDirectory, 'pictures');
        }

        if ($request->hasFile('store_selfies')) {
            $vendor->store_selfies = $this->uploadFiles($request->file('store_selfies'), $vendorDirectory, 'selfies');
        }

        if ($request->hasFile('profile_image')) {
            $vendor->profile_image = $this->uploadFiles([$request->file('profile_image')], $vendorDirectory, 'profile');
        }
    }

    private function uploadFiles($files, $vendorDirectory, $type)
    {
        $uploadedFiles = [];
        foreach ($files as $index => $file) {
            // Create a new file name based on a unique identifier and the original extension
            $fileName = uniqid($type . '_') . '_' . ($index + 1) . '.' . $file->getClientOriginalExtension();
            // Store the file in the public storage and save the path
            $uploadedFiles[] = $file->storeAs("public/{$vendorDirectory}{$type}", $fileName);
        }
        return json_encode(array_map(fn($file) => str_replace('public/', '', $file), $uploadedFiles)); // Return JSON encoded string without 'public/'
    }
        
   public function import(Request $request)
{
    $request->validate([
        'vendor_id' => 'required|string',
        'commission' => 'required|numeric|min:0',
        'file' => 'required|mimes:xlsx,xls,csv',
    ]);

    $vendorId = $request->input('vendor_id');
    $commission = $request->input('commission');

    // Import the pricing data from the Excel file
    $import = new PricingImport($vendorId, $commission);
    Excel::import($import, $request->file('file'));

    // Redirect with a success message and the vendor preview URL
    return redirect()->route('vendor_preview', ['id' => $vendorId])
        ->with('success', 'Data imported successfully!');
}
public function getFilteredVendors(Request $request)
{
    try {
        // Fetch services for filtering by ID and name
        $service = $request->query('service', null);
        $servicesMap = DB::table('services')
            ->pluck('name', 'id')
            ->mapWithKeys(function ($name, $id) {
                return [strtolower($name) => ['id' => $id, 'name' => $name]];
            })
            ->toArray();

        // Determine services to filter
        $servicesToFilter = $service ? [strtolower($service)] : [
            'wash', 'wash & iron', 'dry clean', 'wash & steam', 'steam iron', 'shoe & bag care', 'laundry by kg'
        ];

        // Fetch vendors from the `vendors` table
        $vendors = DB::table('vendors')->select(
            'id', 'user_id', 'store_name', 'complete_address', 'gstin', 'longitude', 'latitude',
            'services', 'pan', 'balance', 'store_adhar', 'store_documents', 'store_pancard',
            'store_pictures', 'store_selfies', 'profile_image', 'online_status', 'approval_status',
            'reason', 'total_orders', 'opening_hours', 'created_at', 'updated_at'
        )->get();

        // Fetch all reviews
        $reviews = DB::table('review')->select('userID', 'star')->get();
        $filteredVendors = [];

        foreach ($vendors as $vendor) {
            // Decode `services` JSON field for each vendor
            $vendorServices = json_decode($vendor->services, true);
            if (!$vendorServices) continue; // Skip vendors with invalid JSON

            // Prepare a list of services that match `services` table entries
            $matchedServices = [];
            foreach ($vendorServices as $serviceName) {
                $lowerName = strtolower($serviceName);
                if (isset($servicesMap[$lowerName])) {
                    $matchedServices[] = $servicesMap[$lowerName];
                }
            }

            // Check if any matched services correspond to the filter criteria
            $serviceMatch = array_filter($matchedServices, function ($service) use ($servicesToFilter) {
                return in_array(strtolower($service['name']), $servicesToFilter);
            });

            // If matching services are found, include the vendor
            if (!empty($serviceMatch)) {
                // Calculate average rating if reviews exist
                $vendorReviews = $reviews->where('userID', $vendor->user_id);
                $vendor->rating = $vendorReviews->count() > 0
                    ? round($vendorReviews->sum('star') / $vendorReviews->count(), 2)
                    : null;

                // Decode additional JSON fields
                $vendor->store_adhar = json_decode($vendor->store_adhar, true);
                $vendor->store_documents = json_decode($vendor->store_documents, true);
                $vendor->store_pictures = json_decode($vendor->store_pictures, true);
                $vendor->store_selfies = json_decode($vendor->store_selfies, true);
                $vendor->profile_image = json_decode($vendor->profile_image, true);

                // Reshape opening hours into the desired format
                $openingHours = json_decode($vendor->opening_hours, true);
                $formattedOpeningHours = [];
                if (is_array($openingHours)) {
                    foreach ($openingHours as $day => $timing) {
                        $formattedOpeningHours[] = [
                            'day' => $day,
                            'timing' => $timing
                        ];
                    }
                }
                $vendor->opening_hours = $formattedOpeningHours;

                $vendor->services = $matchedServices; // Set formatted services

                $filteredVendors[] = $vendor;
            }
        }

        // Return the response with vendors data under `vendors` key
        return response()->json(['vendors' => $filteredVendors]);

    } catch (\Exception $e) {
        // Handle exceptions
        return response()->json(['error' => 'Error occurred: ' . $e->getMessage()], 500);
    }
}


   public function getAllServices()
{
    try {
        // Fetch all services from the `services` table
        $services = DB::table('services')->select('id', 'name', 'image', 'icon')->get();

        // Map the image URLs to include the full path
        $services = $services->map(function ($service) {
            $service->image = 'https://drycleaneo.com/admin/storage/app/public/' . $service->image;
            return $service;
        });

        return response()->json($services);

    } catch (\Exception $e) {
        // Handle any exceptions
        return response()->json(['error' => 'Error occurred: ' . $e->getMessage()], 500);
    }
}

    
}
