<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;
use App\Services\DiamondSearchService;
use Illuminate\Support\Facades\Http;
use Nette\Utils\Json;
use Illuminate\Support\Arr;
use Validator;

class VDBController extends Controller
{
    public $base_url;
    public $apiToken;
    public $apiKey;
    public $vdb_env;
    public function __construct()
    {
        $this->vdb_env = config('services.vdb.env');
        if ($this->vdb_env == 'PROD') {
            $this->apiToken = config('services.vdb.prod.auth_token');
            $this->apiKey = config('services.vdb.prod.api_key');
        } else {
            $this->apiToken = config('services.vdb.dev.auth_token');
            $this->apiKey = config('services.vdb.dev.api_key');
        }
    }

    public function getMinAndMaxValues(Request $request)
    {
        // Validation rules
        $rules = [
            'type' => 'required|in:Diamond,Lab_grown_diamond'
        ];

        $messages = [
            'type.required' => 'Diamond type is required.',
        ];

        // Validate request
        $validator = Validator::make($request->all(), $rules, $messages);
        if ($validator->fails()) {
            return response()->json(['res' => 'error', 'msg' => $validator->errors()->first()], 401);
        }

        $diamondType = $request->input('type');

        $env = config('services.vdb.env');
        $dir = ($env === 'PROD') ? 'diamonds' : 'diamonds_dev';
        $fileName = $diamondType == 'Diamond' ? 'natural_diamond.json' : 'lab_grown_diamond.json';
        // Combine directory and filename
        $filePath = $dir . '/' . $fileName;

        // $filePath = ($diamondType === 'Diamond')
        //     ? 'diamonds/natural_diamond.json'
        //     : 'diamonds/lab_grown_diamond.json';

        // Check if file exists in S3
        if (!Storage::disk('s3_storage')->exists($filePath)) {
            return response()->json(['res' => 'error', 'msg' => 'File not found'], 404);
        }

        try {
            // Read JSON content from S3
            $jsonContent = Storage::disk('s3_storage')->get($filePath);
            $data = json_decode($jsonContent, true);

            if (!isset($data['response']['body']['diamonds'])) {
                return response()->json(['res' => 'error', 'msg' => 'Invalid JSON format'], 500);
            }

            $diamonds = $data['response']['body']['diamonds'];

            // Filters
            $allowedClarities = ['SI2', 'SI1', 'VS2', 'VS1', 'VVS2', 'VVS1', 'IF', 'FL'];
            $allowedCuts = ['Ideal', 'Excellent', 'Very Good', 'Good', 'Fair'];
            $allowedLabs = ['IGI', 'GIA'];
            $allowedShapes = ['Round', 'Emerald', 'Princess', 'Oval', 'Pear', 'Marquise', 'Cushion'];

            // Filter diamonds based on allowed values
            $filteredDiamonds = array_filter($diamonds, function ($diamond) use ($allowedClarities, $allowedCuts, $allowedLabs, $allowedShapes) {
                return in_array($diamond['clarity'] ?? '', $allowedClarities)
                    && in_array($diamond['cut'] ?? '', $allowedCuts)
                    && in_array($diamond['lab'] ?? '', $allowedLabs)
                    && in_array(ucfirst(strtolower($diamond['shape'] ?? '')), $allowedShapes);
            });

            // Extract prices and sizes
            $prices = array_filter(array_column($filteredDiamonds, 'total_sales_price'), 'is_numeric');
            $sizes = array_filter(array_column($filteredDiamonds, 'size'), 'is_numeric');

            // Get min and max values
            $minPrice = !empty($prices) ? (int) round(min($prices)) : 0;
            $maxPrice = !empty($prices) ? (int) round(max($prices)) : 0;
            $minSize = !empty($sizes) ? (float) min($sizes) : 0.5;
            $maxSize = !empty($sizes) ? (float) max($sizes) : 5.1;

            return response()->json([
                'res' => 'success',
                'msg' => 'Here is the min and max value of diamonds',
                'data' => [
                    'min_price' => $minPrice,
                    'max_price' => $maxPrice,
                    'min_size' => $minSize,
                    'max_size' => $maxSize,
                ],
            ], 200, [], JSON_PRESERVE_ZERO_FRACTION);
        } catch (\Exception $e) {
            return response()->json([
                'res' => 'error',
                'msg' => 'Error reading file',
                'error' => $e->getMessage()
            ], 500);
        }
    }




    public function gemstones(Request $request)
    {
        $vdb_url = config('services.vdb.url') . '/gemstones';
        $parameters = $request->query();
        $query_parts = [];

        foreach ($parameters as $key => $value) {
            if (is_array($value)) {
                foreach ($value as $item) {
                    $query_parts[] = $key . '[]=' . urlencode($item);
                }
            } else {
                $query_parts[] = $key . '=' . urlencode($value);
            }
        }

        $full_url = !empty($query_parts) ? $vdb_url . '?' . implode('&', $query_parts) : $vdb_url;
        $cacheKey = 'gemstones_' . md5($full_url);

        $data = Cache::remember($cacheKey, now()->addMinutes(30), function () use ($full_url, $cacheKey) {

            $curl = curl_init();
            curl_setopt_array($curl, [
                CURLOPT_URL => $full_url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => '',
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 0,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => 'GET',
                CURLOPT_HTTPHEADER => [
                    'Authorization: Token token=' . $this->apiToken . ', api_key=' . $this->apiKey
                ],
            ]);

            $response = curl_exec($curl);
            $error = curl_error($curl);
            curl_close($curl);

            if ($error || !$response) {
                return ['error' => 'Failed to fetch data from API and no cache available'];
            }

            $gemstones = json_decode($response, true);

            if (!isset($gemstones['response']['body']['gemstones'])) {
                return ['error' => 'Invalid response from API and no cache available'];
            }

            return [
                'response' => [
                    'body' => [
                        'gemstones' => array_map(function ($gemstone) {
                            return [
                                'id' => $gemstone['id'] ?? null,
                                'stock_num' => $gemstone['stock_num'] ?? null,
                                'short_title' => $gemstone['short_title'] ?? null,
                                'vendor_id' => $gemstone['vendor_id'] ?? null,
                                'total_sales_price' => $gemstone['total_sales_price'] ?? null,
                                'size' => $gemstone['size'] ?? null,
                                'country' => $gemstone['country'] ?? null,
                                'available' => $gemstone['available'] ?? null,
                                'shape' => $gemstone['shape'] ?? null,
                                'color' => $gemstone['color'] ?? null,
                                'image_url' => $gemstone['image_url'] ?? null,
                                'cert_url' => $gemstone['cert_url'] ?? null,
                                'video_url' => $gemstone['video_url'] ?? null,
                                'price_per_carat' => $gemstone['price_per_carat'] ?? null,
                                'lab' => $gemstone['lab'] ?? null,
                                'clarity' => $gemstone['clarity'] ?? null,
                                'cut' => $gemstone['cut'] ?? null,
                                'symmetry' => $gemstone['symmetry'] ?? null,
                                'polish' => $gemstone['polish'] ?? null,
                                'gem_type' => $gemstone['gem_type'] ?? null,
                                'meas_ratio' => $gemstone['meas_ratio'] ?? null,
                                'meas_length' => $gemstone['meas_length'] ?? null,
                                'meas_width' => $gemstone['meas_width'] ?? null,
                                'meas_depth' => $gemstone['meas_depth'] ?? null,
                                'depth_percent' => $gemstone['depth_percent'] ?? null,
                                'table_percent' => $gemstone['table_percent'] ?? null,
                                'fluor_intensity' => $gemstone['fluor_intensity'] ?? null, // FIXED
                                'culet_size' => $gemstone['culet_size'] ?? null,
                                'girdle_condition' => $gemstone['girdle_condition'] ?? null,
                                'country_of_origin' => $gemstone['country_of_origin'] ?? null,
                            ];
                        }, $gemstones['response']['body']['gemstones']),
                        'total_gemstones_found' => $gemstones['response']['body']['total_gemstones_found'] ?? 0
                    ]
                ]
            ];
        });

        return response()->json($data, 200, [
            'Content-Type' => 'application/json',
            'Access-Control-Allow-Origin' => '*',
            'Access-Control-Allow-Methods' => 'GET, POST',
        ]);
    }


    public function desiredCriteria(Request $request)
    {
        $rules = [
            'type' => 'required',
        ];
        $messages = [
            'type.required' => 'Diamond type is required.',
        ];

        $validator = \Validator::make($request->all(), $rules, $messages);
        if ($validator->fails()) {
            return response()->json([
                'res' => 'error',
                'errors' => $validator->errors(),
            ], 422);
        }

        $desiredCriteria = [
            ['shape' => 'Round', 'size' => '1-1.5', 'cut' => 'Good-Ideal', 'color' => 'G-I', 'clarity' => 'VS2-VS1'],
            ['shape' => 'Round', 'size' => '0.5-.99', 'cut' => 'Good-Ideal', 'color' => 'D-F', 'clarity' => 'VVS2-IF'],
            ['shape' => 'Oval', 'size' => '2.0-2.5', 'cut' => 'Good-Ideal', 'color' => 'G-I', 'clarity' => 'VS2-VVS1'],
            ['shape' => 'Princess', 'size' => '1-1.5', 'cut' => 'Good-Ideal', 'color' => 'D-F', 'clarity' => 'SI2-SI1'],
            ['shape' => 'Princess', 'size' => '1-1.5', 'cut' => 'Good-Ideal', 'color' => 'G-I', 'clarity' => 'VS2-VS1'],
            ['shape' => 'Round', 'size' => '1-2', 'cut' => 'Good-Ideal', 'color' => 'G-I', 'clarity' => 'VS2-VS1'],
            ['shape' => 'Emerald', 'size' => '1-1.5', 'cut' => 'Good-Ideal', 'color' => 'D-F', 'clarity' => 'IF-VVS2-IF'],
            ['shape' => 'Emerald', 'size' => '1-2', 'cut' => 'Good-Ideal', 'color' => 'D-F', 'clarity' => 'SI2-SI1'],
            ['shape' => 'Oval', 'size' => '1-1.5', 'cut' => 'Good-Ideal', 'color' => 'G-I', 'clarity' => 'SI2-SI1'],
            ['shape' => 'Cushion', 'size' => '1-1.5', 'cut' => 'Good-Ideal', 'color' => 'D-F', 'clarity' => 'VVS2-IF'],
            ['shape' => 'Cushion', 'size' => '1-1.5', 'cut' => 'Good-Ideal', 'color' => 'G-I', 'clarity' => 'VS2-VS1'],
            ['shape' => 'Round', 'size' => '1.5-1.99', 'cut' => 'Good-Ideal', 'color' => 'D-F', 'clarity' => 'VVS2-IF'],
        ];

        $diamondType = $request->input('type');
        $env = config('services.vdb.env');
        $dir = ($env === 'PROD') ? 'diamonds' : 'diamonds_dev';
        $fileName = $diamondType == 'Diamond' ? 'natural_diamond.json' : 'lab_grown_diamond.json';
        $filePath = $dir . '/' . $fileName;

        if (!Storage::disk('s3_storage')->exists($filePath)) {
            return response()->json(['res' => 'error', 'msg' => 'File not found'], 404);
        }

        $cacheKey = $request->type . '_12_desired_criteria_diamonds';
        $collection = cache()->remember($cacheKey, 7200, function () use ($desiredCriteria, $filePath) {
            $jsonContent = Storage::disk('s3_storage')->get($filePath);
            $data = json_decode($jsonContent, true);
            $allDiamonds = $data['response']['body']['diamonds'] ?? [];

            if (empty($allDiamonds)) {
                return [];
            }

            $cutOrder = [
                'Good' => 0,
                'Very Good' => 1,
                'Excellent' => 2,
                'Ideal' => 3,
            ];

            $colorOrder = [
                'J' => 0,
                'I' => 1,
                'H' => 2,
                'G' => 3,
                'F' => 4,
                'E' => 5,
                'D' => 6,
            ];

            $clarityOrder = [
                'SI2' => 0,
                'SI1' => 1,
                'VS2' => 2,
                'VS1' => 3,
                'VVS2' => 4,
                'VVS1' => 5,
                'IF' => 6,
                'FL' => 7,
            ];

            $matchesCriterion = function ($diamond, $criterion) use ($cutOrder, $colorOrder, $clarityOrder) {
                if (!isset($diamond['shape'], $diamond['size'], $diamond['cut'], $diamond['color'], $diamond['clarity'])) {
                    return false;
                }

                // Only allow GIA or IGI
                if (!in_array($diamond['lab'], ['GIA', 'IGI'])) {
                    return false;
                }

                if ($diamond['shape'] !== $criterion['shape']) {
                    return false;
                }

                $sizeRange = explode('-', $criterion['size']);
                $minSize = floatval($sizeRange[0]);
                $maxSize = floatval($sizeRange[1]);
                $diamondSize = floatval($diamond['size']);
                if ($diamondSize < $minSize || $diamondSize > $maxSize) {
                    return false;
                }

                $cutParts = explode('-', $criterion['cut']);
                $cutRanks = array_filter(array_map(function ($cut) use ($cutOrder) {
                    return $cutOrder[$cut] ?? null;
                }, $cutParts), 'is_numeric');

                if (count($cutRanks) < count($cutParts)) {
                    return false;
                }
                $minCutRank = min($cutRanks);
                $maxCutRank = max($cutRanks);
                $diamondCutRank = $cutOrder[$diamond['cut']] ?? null;
                if ($diamondCutRank === null || $diamondCutRank < $minCutRank || $diamondCutRank > $maxCutRank) {
                    return false;
                }

                $colorParts = explode('-', $criterion['color']);
                $colorRanks = array_filter(array_map(function ($color) use ($colorOrder) {
                    return $colorOrder[$color] ?? null;
                }, $colorParts), 'is_numeric');
                if (count($colorRanks) < count($colorParts)) {
                    return false;
                }
                $minColorRank = min($colorRanks);
                $maxColorRank = max($colorRanks);
                $diamondColorRank = $colorOrder[$diamond['color']] ?? null;
                if ($diamondColorRank === null || $diamondColorRank < $minColorRank || $diamondColorRank > $maxColorRank) {
                    return false;
                }

                $clarityParts = explode('-', $criterion['clarity']);
                $clarityRanks = array_filter(array_map(function ($clarity) use ($clarityOrder) {
                    return $clarityOrder[$clarity] ?? null;
                }, $clarityParts), 'is_numeric');
                if (count($clarityRanks) < count($clarityParts)) {
                    return false;
                }
                $minClarityRank = min($clarityRanks);
                $maxClarityRank = max($clarityRanks);
                $diamondClarityRank = $clarityOrder[$diamond['clarity']] ?? null;
                if ($diamondClarityRank === null || $diamondClarityRank < $minClarityRank || $diamondClarityRank > $maxClarityRank) {
                    return false;
                }

                return true;
            };

            shuffle($allDiamonds);
            $selectedDiamonds = [];
            $selectedIds = [];

            // ✅ Define allowed keys once
            $allowedKeys = [
                'id',
                'type',
                'stock_num',
                'short_title',
                'vendor_id',
                'total_sales_price',
                'size',
                'country',
                'available',
                'shape',
                'color',
                'image_url',
                'cert_url',
                'video_url',
                'price_per_carat',
                'lab',
                'clarity',
                'cut',
                'symmetry',
                'polish',
                'meas_ratio',
                'meas_length',
                'meas_width',
                'depth_percent',
                'table_percent',
                'fluor_intensity',
                'culet_size',
                'girdle_condition',
            ];

            // ✅ Create default structure with all keys = null
            $defaultDiamond = array_fill_keys($allowedKeys, null);

            foreach ($desiredCriteria as $criterion) {
                foreach ($allDiamonds as $diamond) {
                    if (in_array($diamond['id'], $selectedIds)) {
                        continue;
                    }
                    if ($matchesCriterion($diamond, $criterion)) {
                        // ✅ Guarantee all keys exist in the response
                        $filteredDiamond = array_merge($defaultDiamond, Arr::only($diamond, $allowedKeys));
                        $selectedDiamonds[] = $filteredDiamond;
                        $selectedIds[] = $diamond['id'];
                        break;
                    }
                }
            }

            return $selectedDiamonds;
        });

        $page = request('page', 1);
        $perPage = request('per_page', 12);
        $offset = ($page - 1) * $perPage;
        $pagedData = array_slice($collection, $offset, $perPage);

        return response()->json([
            'res' => 'success',
            'page_number' => $page,
            'per_page' => $perPage,
            'total' => count($collection),
            'total_pages' => ceil(count($collection) / $perPage),
            'response' => [
                'body' => [
                    'diamonds' => $pagedData,
                    'total_diamonds_found' => count($collection)
                ]
            ],
        ], 200)->header('cache-control', 'public, max-age=7200');
    }


    ## get all ranges diamonds at once
    public function quickSelectDiamonds(Request $request)
    {
        // Validate request
        $validator = Validator::make($request->all(), [
            'type' => 'required|in:natural,lab_grown',
            'shape' => 'nullable|string'
        ]);

        if ($validator->fails()) {
            return response()->json(['res' => 'error', 'msg' => $validator->errors()->all()], 401);
        }
        $cutRanges = [1, 1.5, 2, 2.5];
        $shape = $request->input('shape') ?? 'round';
        $diamondType = $request->input('type');

        $filePath = sprintf(
            '%s/%s',
            config('services.vdb.env') === 'PROD' ? 'diamonds' : 'diamonds_dev',
            $diamondType === 'natural' ? 'natural_diamond.json' : 'lab_grown_diamond.json'
        );

        if (!Storage::disk('s3_storage')->exists($filePath)) {
            return response()->json(['res' => 'error', 'msg' => 'Diamond file not found'], 404);
        }

        $jsonContent = Storage::disk('s3_storage')->get($filePath);
        $diamonds = data_get(json_decode($jsonContent, true), 'response.body.diamonds', []);

        if (empty($diamonds)) {
            return response()->json(['res' => 'error', 'msg' => 'No diamond data found'], 200);
        }

        // Filters
        $allowedColors = ['F', 'G', 'H', 'I', 'E', 'D'];
        $allowedClarities = ['VS1', 'VS2', 'SI1', 'SI2', 'VVS2', 'VVS1'];
        $allowedCuts = ['Excellent', 'Very Good', 'Ideal'];
        $certifiedLabs = ['IGI', 'GIA'];

        // Pre-filter all diamonds
        $filtered = array_filter($diamonds, function ($diamond) use ($shape, $allowedColors, $allowedClarities, $allowedCuts, $certifiedLabs) {
            return (
                strtolower($diamond['shape'] ?? '') === strtolower($shape) &&
                in_array($diamond['color'] ?? '', $allowedColors) &&
                in_array($diamond['clarity'] ?? '', $allowedClarities) &&
                in_array($diamond['cut'] ?? '', $allowedCuts) &&
                in_array($diamond['lab'] ?? '', $certifiedLabs)
            );
        });

        $result = [];

        foreach ($cutRanges as $caratTarget) {
            // Filter by size within ±0.05 carat
            $matches = array_filter($filtered, function ($diamond) use ($caratTarget) {
                $carat = floatval($diamond['size'] ?? 0);
                return abs($carat - $caratTarget) <= 0.05;
            });

            // Sort by price ascending
            usort($matches, function ($a, $b) {
                return floatval($a['price'] ?? PHP_FLOAT_MAX) <=> floatval($b['price'] ?? PHP_FLOAT_MAX);
            });

            // Take the cheapest one
            if (!empty($matches)) {
                $diamond = $matches[0];
                $result[] = [
                    'id' => $diamond['id'] ?? null,
                    'type' => $diamond['type'] ?? null,
                    'stock_num' => $diamond['stock_num'] ?? null,
                    'short_title' => $diamond['short_title'] ?? null,
                    'total_sales_price' => $diamond['total_sales_price'] ?? null,
                    'size' => $diamond['size'] ?? null,
                    'available' => $diamond['available'] ?? null,
                    'shape' => $diamond['shape'] ?? null,
                    'color' => $diamond['color'] ?? null,
                    'price_per_carat' => $diamond['price_per_carat'] ?? null,
                    'lab' => $diamond['lab'] ?? null,
                    'clarity' => $diamond['clarity'] ?? null,
                    'cut' => $diamond['cut'] ?? null,
                    'cert_url' => $diamond['cert_url'] ?? null,
                ];
            }
        }
        return response()->json([
            'res' => 'success',
            'response' => [
                'body' => [
                    'diamonds' => $result
                ]
            ]
        ], 200);
    }



    ## function for fetch diamond based on center_stone in details page
    public function getDiamondBansedOnChoosenCarat(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'min_carat' => 'required|numeric',
            'max_carat' => 'required|numeric',
            'type' => 'required|string',
            'shape' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json(['res' => 'error', 'msg' => $validator->errors()->all()], 401);
        }

        $minCarat = $request->min_carat;
        $maxCarat = $request->max_carat;
        $shape = $request->input('shape');
        $diamondType = $request->input('type');

        $filePath = sprintf(
            '%s/%s',
            config('services.vdb.env') === 'PROD' ? 'diamonds' : 'diamonds_dev',
            $diamondType === 'natural' ? 'natural_diamond.json' : 'lab_grown_diamond.json'
        );

        // Use file path as part of cache key
        $cacheKey = 'diamonds_' . md5($filePath);

        $diamonds = Cache::remember($cacheKey, now()->addHours(1), function () use ($filePath) {
            if (!Storage::disk('s3_storage')->exists($filePath)) {
                return null;
            }

            $jsonContent = Storage::disk('s3_storage')->get($filePath);
            return data_get(json_decode($jsonContent, true), 'response.body.diamonds', []);
        });

        if (empty($diamonds)) {
            return response()->json(['res' => 'error', 'msg' => 'No diamond data found'], 200);
        }

        // Filters
        $allowedColors = ['F', 'G', 'H', 'I', 'E', 'D'];
        $allowedClarities = ['VS1', 'VS2', 'SI1', 'SI2', 'VVS2', 'VVS1'];
        $allowedCuts = ['Excellent', 'Very Good', 'Ideal'];
        $certifiedLabs = ['IGI', 'GIA'];

        $filtered = collect($diamonds)->filter(function ($d) use ($minCarat, $maxCarat, $shape, $allowedColors, $allowedClarities, $allowedCuts, $certifiedLabs) {
            return
                isset($d['size'], $d['shape'], $d['lab'], $d['cut'], $d['clarity'], $d['color']) &&
                $d['size'] >= $minCarat &&
                $d['size'] <= $maxCarat &&
                $d['shape'] === $shape &&
                in_array($d['color'], $allowedColors) &&
                in_array($d['clarity'], $allowedClarities) &&
                in_array($d['cut'], $allowedCuts) &&
                in_array($d['lab'], $certifiedLabs);
        });

        $sorted = $filtered->sort(function ($a, $b) use ($allowedColors, $allowedClarities, $allowedCuts) {
            $colorA = array_search($a['color'], $allowedColors);
            $colorB = array_search($b['color'], $allowedColors);
            if ($colorA !== $colorB)
                return $colorA <=> $colorB;

            $clarityA = array_search($a['clarity'], $allowedClarities);
            $clarityB = array_search($b['clarity'], $allowedClarities);
            if ($clarityA !== $clarityB)
                return $clarityA <=> $clarityB;

            $cutA = array_search($a['cut'], $allowedCuts);
            $cutB = array_search($b['cut'], $allowedCuts);
            if ($cutA !== $cutB)
                return $cutA <=> $cutB;

            return ($a['total_sales_price'] ?? 0) <=> ($b['total_sales_price'] ?? 0);
        });

        $bestDiamond = $sorted->first();

        if (!$bestDiamond) {
            return response()->json(['res' => 'error', 'msg' => 'No diamond found.'], 200);
        }

        return response()->json([
            'res' => 'success',
            'response' => [
                'body' => [
                    'diamonds' => [$bestDiamond]
                ]
            ]
        ], 200);
    }



    public function diamonds(Request $request)
    {
        Log::info("=========== DIAMONDS API STARTED ===========");

        $validator = Validator::make($request->all(), [
            'type' => 'required',
        ], [
            'type.required' => 'Diamond type is required.',
        ]);

        if ($validator->fails()) {
            Log::warning("Validation failed", $validator->errors()->toArray());
            return response()->json(['res' => 'error', 'msg' => $validator->errors()->all()], 401);
        }

        try {

            // ====================
            // ENV & PATH INFO
            // ====================

            $diamondType = $request->input('type');
            $env = config('services.vdb.env');

            Log::info("Diamond type received: " . $diamondType);
            Log::info("VDB_ENV value: " . $env);

            $dir = ($env === 'PROD') ? 'diamonds' : 'diamonds_dev';
            $fileName = ($diamondType === 'Diamond') ? 'natural_diamond.csv' : 'lab_grown_diamond.csv';
            $filePath = $dir . '/' . $fileName;

            Log::info("Resolved directory: " . $dir);
            Log::info("Resolved file name: " . $fileName);
            Log::info("Resolved full path: " . $filePath);
            Log::info("Disk in use: s3_storage");

            // ====================
            // S3 CONNECTION TEST
            // ====================

            try {
                Storage::disk('s3_storage')->path('/');
                Log::info("S3 disk connection successful");
            } catch (\Exception $e) {
                Log::error("S3 disk connection FAILED: " . $e->getMessage());
            }

            // ====================
            // DIRECTORY LIST
            // ====================

            try {
                $files = Storage::disk('s3_storage')->files($dir);
                Log::info("Files found in directory [" . $dir . "]: " . json_encode($files));
            } catch (\Exception $e) {
                Log::error("Failed to list directory: " . $e->getMessage());
            }

            // ====================
            // EXISTS CHECK
            // ====================

            try {
                $exists = Storage::disk('s3_storage')->exists($filePath);
                Log::info("File exists check result: " . var_export($exists, true));
            } catch (\Exception $e) {
                Log::error("Exists check failed: " . $e->getMessage());
            }

            if (!Storage::disk('s3_storage')->exists($filePath)) {
                Log::critical("FILE NOT FOUND: " . $filePath);
                return response()->json(['res' => 'error', 'msg' => 'File not found'], 404);
            }

            // ====================
            // FILE SIZE CHECK
            // ====================

            try {
                $fileSize = Storage::disk('s3_storage')->size($filePath);
                Log::info("File size in bytes: " . $fileSize);
            } catch (\Exception $e) {
                Log::error("File size check failed: " . $e->getMessage());
            }

            // ====================
            // READ FILE
            // ====================

            try {
                $csvContent = Storage::disk('s3_storage')->get($filePath);
                Log::info("CSV file loaded successfully. Length: " . strlen($csvContent));
            } catch (\Exception $e) {
                Log::error("File reading failed: " . $e->getMessage());
                throw $e;
            }

            // ====================
            // PARSE CSV
            // ====================

            $rows = array_map('str_getcsv', explode("\n", trim($csvContent)));

            if (!$rows) {
                Log::error("CSV parsed but rows were empty");
            }

            $headers = array_map('trim', array_shift($rows));
            Log::info("CSV headers: " . json_encode($headers));

            $data = [];

            foreach ($rows as $index => $row) {

                if (count($row) !== count($headers)) {
                    Log::warning("ROW MISMATCH AT LINE " . ($index + 2));
                    continue;
                }

                $data[] = array_combine($headers, $row);
            }

            Log::info("CSV successfully parsed. Total diamonds loaded: " . count($data));

            // ====================
            // FILTERS
            // ====================

            $activeFilters = [];

            $activeFilters[] = fn($d) =>
            isset($d['total_sales_price']) &&
                $d['total_sales_price'] !== '';

            Log::info("Default filter applied: price not null");

            if ($vendorId = $request->vendor_id) {
                Log::info("Vendor filter applied: " . $vendorId);
                $activeFilters[] = fn($d) => ($d['vendor_id'] ?? null) == $vendorId;
            }

            if ($fluor = $request->fluorescence_intensities) {
                Log::info("Fluor filters applied: " . json_encode($fluor));
                $activeFilters[] = fn($d) => in_array($d['fluor_intensity'] ?? null, (array)$fluor);
            }

            if ($shapes = $request->shapes) {
                Log::info("Shape filters applied: " . json_encode($shapes));
                $activeFilters[] = fn($d) => in_array($d['shape'] ?? null, (array)$shapes);
            }

            if ($labs = $request->labs) {
                Log::info("Labs filters applied: " . json_encode($labs));
                $activeFilters[] = fn($d) => in_array($d['lab'] ?? null, (array)$labs);
            }

            // ====================
            // APPLY FILTERS
            // ====================

            $data = array_values(array_filter($data, function ($d) use ($activeFilters) {
                foreach ($activeFilters as $filter) {
                    if (!$filter($d)) return false;
                }
                return true;
            }));

            Log::info("Diamonds after filtering: " . count($data));

            // ====================
            // PAGINATION
            // ====================

            $perPage = $request->per_page ?? 30;
            $page = $request->page_number ?? 1;

            $offset = ($page - 1) * $perPage;
            $paginated = array_slice($data, $offset, $perPage);

            Log::info("Pagination values → page: {$page}, per_page: {$perPage}, offset: {$offset}");
            Log::info("Returned count: " . count($paginated));

            return response()->json([
                'res' => 'success',
                'page' => $page,
                'per_page' => $perPage,
                'total' => count($data),
                'response' => [
                    'body' => [
                        'diamonds' => $paginated,
                        'total_diamonds_found' => count($data)

                    ]
                ]
            ], 200);
        } catch (\Exception $e) {

            Log::error("========== DIAMONDS API FAILED ==========");
            Log::error("Exception: " . $e->getMessage());
            Log::error("File: " . $e->getFile());
            Log::error("Line: " . $e->getLine());

            return response()->json([
                'res' => 'error',
                'msg' => 'Processing failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    private function formatDiamond(array $diamond)
    {
        return [
            'id' => $diamond['id'] ?? null,
            'type' => $diamond['type'] ?? null,
            'stock_num' => $diamond['stock_num'] ?? null,
            'short_title' => $diamond['short_title'] ?? null,
            'vendor_id' => $diamond['vendor_id'] ?? null,
            'total_sales_price' => $diamond['total_sales_price'] ?? null,
            'size' => $diamond['size'] ?? null,
            'country' => $diamond['country'] ?? null,
            'available' => $diamond['available'] ?? null,
            'shape' => $diamond['shape'] ?? null,
            'color' => $diamond['color'] ?? null,
            'image_url' => $diamond['image_url'] ?? null,
            'cert_url' => $diamond['cert_url'] ?? null,
            'video_url' => $diamond['video_url'] ?? null,
            'price_per_carat' => $diamond['price_per_carat'] ?? null,
            'lab' => $diamond['lab'] ?? null,
            'clarity' => $diamond['clarity'] ?? null,
            'cut' => $diamond['cut'] ?? null,
            'symmetry' => $diamond['symmetry'] ?? null,
            'polish' => $diamond['polish'] ?? null,
            'meas_ratio' => $diamond['meas_ratio'] ?? null,
            'meas_length' => $diamond['meas_length'] ?? null,
            'meas_width' => $diamond['meas_width'] ?? null,
            'depth_percent' => $diamond['depth_percent'] ?? null,
            'table_percent' => $diamond['table_percent'] ?? null,
            'fluor_intensity' => $diamond['fluor_intensity'] ?? null,
            'culet_size' => $diamond['culet_size'] ?? null,
            'girdle_condition' => $diamond['girdle_condition'] ?? null
        ];
    }



    // public function diamonds(Request $request)
    // {
    //     $validator = Validator::make($request->all(), [
    //         'type' => 'required',
    //     ], [
    //         'type.required' => 'Diamond type is required.',
    //     ]);

    //     if ($validator->fails()) {
    //         return response()->json(['res' => 'error', 'msg' => $validator->errors()->all()], 401);
    //     }

    //     $diamondType = $request->input('type');
    //     $env = config('services.vdb.env');
    //     // Determine the directory based on environment
    //     $dir = ($env === 'PROD') ? 'diamonds' : 'diamonds_dev';
    //     // Set filename based on diamond type
    //     $fileName = $diamondType == 'Diamond' ? 'natural_diamond.json' : 'lab_grown_diamond.json';
    //     // Combine directory and filename
    //     $filePath = $dir . '/' . $fileName;

    //     // $filePath = $diamondType == 'Diamond' ? 'diamonds/natural_diamond.json' : 'diamonds/lab_grown_diamond.json';
    //     if (!Storage::disk('s3_storage')->exists($filePath)) {
    //         return response()->json(['res' => 'error', 'msg' => 'File not found'], 404);
    //     }



    //     try {
    //         $jsonContent = Storage::disk('s3_storage')->get($filePath);
    //         $data = json_decode($jsonContent, true)['response']['body']['diamonds'] ?? [];
    //         $activeFilters = [];

    //         // --- CRITICAL CHANGE: Always exclude diamonds with null prices ---
    //         $activeFilters[] = fn($d) => isset($d['total_sales_price']) && $d['total_sales_price'] !== null;

    //         // Vendor filter
    //         if ($vendorId = $request->input('vendor_id')) {
    //             $activeFilters[] = fn($d) => isset($d['vendor_id']) && $d['vendor_id'] == $vendorId;
    //         }

    //         // Fluorescence intensities
    //         if ($fluor = $request->input('fluorescence_intensities')) {
    //             $activeFilters[] = fn($d) => in_array($d['fluor_intensity'] ?? null, (array) $fluor);
    //         }

    //         // Shapes filter
    //         if ($shapes = $request->input('shapes')) {
    //             $activeFilters[] = fn($d) => in_array($d['shape'] ?? null, (array) $shapes);
    //         }

    //         // Labs filter
    //         if ($labs = $request->input('labs')) {
    //             $activeFilters[] = fn($d) => in_array($d['lab'] ?? null, (array) $labs);
    //         }

    //         // Range filters
    //         $rangeFilters = [
    //             'color' => ['from' => $request->input('color_from'), 'to' => $request->input('color_to')],
    //             'clarity' => [
    //                 'from' => $request->input('clarity_from'),
    //                 'to' => $request->input('clarity_to'),
    //                 'order' => ['SI2', 'SI1', 'VS2', 'VS1', 'VVS2', 'VVS1', 'IF', 'FL']
    //             ],
    //             'cut' => [
    //                 'from' => $request->input('cut_from'),
    //                 'to' => $request->input('cut_to'),
    //                 'order' => ['Ideal', 'Excellent', 'Very Good', 'Good', 'Fair']
    //             ],
    //             'polish' => ['from' => $request->input('polish_from'), 'to' => $request->input('polish_to')],
    //             'depth_percent' => ['from' => $request->input('depth_percent_from'), 'to' => $request->input('depth_percent_to')],
    //             'symmetry' => ['from' => $request->input('symmetry_from'), 'to' => $request->input('symmetry_to')],
    //             'table_percent' => ['from' => $request->input('table_percent_from'), 'to' => $request->input('table_percent_to')],
    //             'size' => ['from' => $request->input('size_from'), 'to' => $request->input('size_to')],
    //             'total_sales_price' => ['from' => $request->input('price_total_from'), 'to' => $request->input('price_total_to')]
    //         ];

    //         foreach ($rangeFilters as $field => $range) {
    //             if ($range['from'] === null || $range['to'] === null)
    //                 continue;

    //             if (isset($range['order'])) {
    //                 $order = $range['order'];
    //                 $fromIdx = array_search($range['from'], $order);
    //                 $toIdx = array_search($range['to'], $order);

    //                 if ($fromIdx !== false && $toIdx !== false) {
    //                     $min = min($fromIdx, $toIdx);
    //                     $max = max($fromIdx, $toIdx);
    //                     $activeFilters[] = fn($d) => ($idx = array_search($d[$field] ?? null, $order)) !== false &&
    //                         $idx >= $min && $idx <= $max;
    //                 }
    //             } else {
    //                 $activeFilters[] = fn($d) => ($d[$field] ?? null) >= $range['from'] &&
    //                     ($d[$field] ?? null) <= $range['to'];
    //             }
    //         }

    //         // Apply all filters
    //         $data = array_values(array_filter($data, function ($d) use ($activeFilters) {
    //             foreach ($activeFilters as $filter) {
    //                 if (!$filter($d))
    //                     return false;
    //             }
    //             return true;
    //         }));

    //         // Handle stock number lookup
    //         if ($stockNo = $request->input('stock_num')) {
    //             $result = array_filter($data, fn($d) => ($d['stock_num'] ?? null) == $stockNo);
    //             if (empty($result)) {
    //                 return response()->json(['res' => 'error', 'msg' => 'Stock number not found.'], 404);
    //             }
    //             $diamond = reset($result);
    //             $formattedDiamond = [
    //                 'id' => $diamond['id'] ?? null,
    //                 'type' => $diamond['type'] ?? null,
    //                 'stock_num' => $diamond['stock_num'] ?? null,
    //                 'short_title' => $diamond['short_title'] ?? null,
    //                 'vendor_id' => $diamond['vendor_id'] ?? null,
    //                 'total_sales_price' => $diamond['total_sales_price'] ?? null,
    //                 'size' => $diamond['size'] ?? null,
    //                 'country' => $diamond['country'] ?? null,
    //                 'available' => $diamond['available'] ?? null,
    //                 'shape' => $diamond['shape'] ?? null,
    //                 'color' => $diamond['color'] ?? null,
    //                 'image_url' => $diamond['image_url'] ?? null,
    //                 'cert_url' => $diamond['cert_url'] ?? null,
    //                 'video_url' => $diamond['video_url'] ?? null,
    //                 'price_per_carat' => $diamond['price_per_carat'] ?? null,
    //                 'lab' => $diamond['lab'] ?? null,
    //                 'clarity' => $diamond['clarity'] ?? null,
    //                 'cut' => $diamond['cut'] ?? null,
    //                 'symmetry' => $diamond['symmetry'] ?? null,
    //                 'polish' => $diamond['polish'] ?? null,
    //                 'meas_ratio' => $diamond['meas_ratio'] ?? null,
    //                 'meas_length' => $diamond['meas_length'] ?? null,
    //                 'meas_width' => $diamond['meas_width'] ?? null,
    //                 'depth_percent' => $diamond['depth_percent'] ?? null,
    //                 'table_percent' => $diamond['table_percent'] ?? null,
    //                 'fluor_intensity' => $diamond['fluor_intensity'] ?? null,
    //                 'culet_size' => $diamond['culet_size'] ?? null,
    //                 'girdle_condition' => $diamond['girdle_condition'] ?? null
    //             ];

    //             return response()->json([
    //                 'res' => 'success',
    //                 'response' => ['body' => ['diamonds' => [$formattedDiamond]]]
    //             ], 200)->header('Cache-Control', 'max-age=86400, public');
    //         }
    //         // Sorting logic
    //         $sortBy = $request->input('sort_by');
    //         $sortOrder = $request->input('sort_order', 'asc');
    //         $sortConfig = [
    //             'order' => $sortOrder === 'desc' ? SORT_DESC : SORT_ASC,
    //             'fields' => [
    //                 'size' => ['key' => 'size', 'type' => SORT_NUMERIC],
    //                 'price' => ['key' => 'total_sales_price', 'type' => SORT_NUMERIC],
    //                 'color' => [
    //                     'key' => 'color',
    //                     'order' => ['D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
    //                     'type' => SORT_REGULAR
    //                 ],
    //                 'clarity' => [
    //                         'key' => 'clarity',
    //                         'order' => ['SI2', 'SI1', 'VS2', 'VS1', 'VVS2', 'VVS1', 'IF', 'FL'],
    //                         'type' => SORT_REGULAR
    //                     ],
    //                 'cut' => [
    //                     'key' => 'cut',
    //                     'order' => ['Ideal', 'Excellent', 'Very Good', 'Good', 'Fair'],
    //                     'type' => SORT_REGULAR
    //                 ]
    //             ]
    //         ];

    //         if ($sortBy && isset($sortConfig['fields'][$sortBy])) {
    //             $fieldConfig = $sortConfig['fields'][$sortBy];
    //             $key = $fieldConfig['key'];

    //             if (isset($fieldConfig['order'])) {
    //                 $order = array_flip($fieldConfig['order']);
    //                 $params = [
    //                     array_column($data, $key),
    //                     $sortConfig['order']
    //                 ];
    //                 array_multisort(
    //                     array_map(fn($x) => $order[$x] ?? PHP_INT_MAX, array_column($data, $key)),
    //                     $sortConfig['order'],
    //                     $data
    //                 );
    //             } else {
    //                 array_multisort(
    //                     array_column($data, $key),
    //                     $sortConfig['order'],
    //                     $fieldConfig['type'],
    //                     $data
    //                 );
    //             }
    //         }

    //         // Pagination
    //         $perPage = $request->input('per_page', 30);
    //         $page = $request->input('page_number', 1);
    //         $offset = ($page - 1) * $perPage;
    //         $paginated = array_slice($data, $offset, $perPage);

    //         // Format response data
    //         $formattedData = array_map(function ($diamond) {
    //             return [
    //                 'id' => $diamond['id'] ?? null,
    //                 'type' => $diamond['type'] ?? null,
    //                 'stock_num' => $diamond['stock_num'] ?? null,
    //                 'short_title' => $diamond['short_title'] ?? null,
    //                 'vendor_id' => $diamond['vendor_id'] ?? null,
    //                 'total_sales_price' => $diamond['total_sales_price'] ?? null,
    //                 'size' => $diamond['size'] ?? null,
    //                 'country' => $diamond['country'] ?? null,
    //                 'available' => $diamond['available'] ?? null,
    //                 'shape' => $diamond['shape'] ?? null,
    //                 'color' => $diamond['color'] ?? null,
    //                 'image_url' => $diamond['image_url'] ?? null,
    //                 'cert_url' => $diamond['cert_url'] ?? null,
    //                 'video_url' => $diamond['video_url'] ?? null,
    //                 'price_per_carat' => $diamond['price_per_carat'] ?? null,
    //                 'lab' => $diamond['lab'] ?? null,
    //                 'clarity' => $diamond['clarity'] ?? null,
    //                 'cut' => $diamond['cut'] ?? null,
    //                 'symmetry' => $diamond['symmetry'] ?? null,
    //                 'polish' => $diamond['polish'] ?? null,
    //                 'meas_ratio' => $diamond['meas_ratio'] ?? null,
    //                 'meas_length' => $diamond['meas_length'] ?? null,
    //                 'meas_width' => $diamond['meas_width'] ?? null,
    //                 'depth_percent' => $diamond['depth_percent'] ?? null,
    //                 'table_percent' => $diamond['table_percent'] ?? null,
    //                 'fluor_intensity' => $diamond['fluor_intensity'] ?? null,
    //                 'culet_size' => $diamond['culet_size'] ?? null,
    //                 'girdle_condition' => $diamond['girdle_condition'] ?? null
    //             ];
    //         }, $paginated);

    //         return response()->json([
    //             'res' => 'success',
    //             'page_number' => $page,
    //             'per_page' => $perPage,
    //             'total' => count($data),
    //             'total_pages' => ceil(count($data) / $perPage),
    //             'response' => [
    //                 'body' => [
    //                     "diamonds" => $formattedData,
    //                     "total_diamonds_found" => count($data)
    //                 ]
    //             ]
    //         ], 200)->header('Cache-Control', 'max-age=86400, public');
    //     } catch (\Exception $e) {
    //         return response()->json(['res' => 'error', 'msg' => 'Error processing request', 'error' => $e->getMessage()], 500);
    //     }
    // }

    ## compare diamonds
    public function compareDiamonds(Request $request)
    {

        $validator = Validator::make($request->all(), [
            'stock_num' => 'required',
            'type' => 'required',
        ], [
            'stock_num.required' => 'Stock number is required.',
            'type.required' => 'Diamond type is required.',
        ]);

        if ($validator->fails()) {
            return response()->json(['res' => 'error', 'msg' => $validator->errors()->all()], 401);
        }

        $stockNum = $request->input('stock_num');
        $diamondType = $request->input('type');

        $diamondService = new DiamondSearchService();
        $result = $diamondService->getSimilarDiamonds($stockNum, $diamondType);

        if ($result['error']) {
            return response()->json(['res' => 'error', 'msg' => $result['message']], 404);
        }

        return response()->json([
            'res' => 'success',
            'msg' => 'Similar diamonds retrieved successfully',
            'diamonds' => $result['diamonds']
        ]);
    }
}
