<?php
defined('BASEPATH') OR exit('No direct script access allowed');

use GuzzleHttp\Client;

class JewelryExportCLI extends CI_Controller {

    public function __construct() {
        parent::__construct();
    }

	private function getJewelryPr($params) {
		$record = [];

		$client = new Client();

		$headers = [];
		  
		$response = $client->request('GET', 'https://shop.simplexdiam.com/admin/auto_shopify_api', [
			'http_errors' => false,
			'headers' => $headers,
		    'query' => $params
		]);
		  
		if($response->getStatusCode() > 300) {
		    return $record;
		}

		$body = $response->getBody();
		$parsedBody = json_decode($body, true);

		$record = $parsedBody['records'];

// 		$dataLog = [
//             'request' => json_encode($params),
//             'response' => json_encode($parsedBody),
//             'method' => 'GET',
//             'endpoint' => "https://shop.simplexdiam.com/admin/auto_shopify_api",
//             'added_at' => date('Y-m-d h:i'),
//         ];
//         $this->db->insert('external_api_log', $dataLog);

		return $record;
	}

private function splitJewelryByStoneTypePr($jewelryRecords) {
     // $currentDateTime = date('Y-m-d H:i:s');
    //  echo $currentDateTime;
	 //   die;
    $result = [];

    // Map metal codes to full metal names
    $metalMap = [
        'KW' => 'White Gold',
        'KY' => 'Yellow Gold',
        'KR' => 'Rose Gold',
        'TT' => 'Two Tone'
    ];

    foreach ($jewelryRecords as $item) {
        if (!isset($item['variants']) || empty($item['variants'])) {
            $result[] = $item;
            continue;
        }

        $labGrownVariants = [];
        $naturalDiamondVariants = [];

        // Group images by metal for easy lookup
        $imagesByMetal = [];
        if (isset($item['images']) && is_array($item['images'])) {
            foreach ($item['images'] as $img) {
                $metalName = $img['metal'] ?? '';
                $imagesByMetal[$metalName][] = $img['src'];
            }
        }

        // Classify variants and handle image checks
        foreach ($item['variants'] as $variant) {
            $variantMetal = $variant['metal'] ?? '';
            $metalCode = substr($variantMetal, -2); // e.g., "KW"
            $metalName = $metalMap[$metalCode] ?? '';
           // echo 'website_stonetype'. $variant['metal_v'].'=>'.$variant['website_stonetype']."<br>";
            // If no image for this metal, set inventory_quantity = 0
            $hasImage = isset($imagesByMetal[$metalName]) && !empty($imagesByMetal[$metalName]);
            if (!$hasImage) {
                $variant['inventory_quantity'] = 0;
            }

            // Normalize stone type
            $stonetypeRaw = isset($variant['website_stonetype']) ? trim($variant['website_stonetype']) : '';
            $stonetype = strtolower($stonetypeRaw);
          //  echo  $variant['metal_v'].'=>'.$stonetype."<br>";
            // Lab Grown check
            if (strpos($stonetype, 'lab grown') !== false) {
                //echo 'lab grown'. $variant['metal_v'].'=>'.$stonetype."<br>";;
                $labGrownVariants[] = $variant;
            }
            // Natural Diamond (including variants with GemStn/Gemstone/gemstone)
            // elseif (
            //     $stonetype === '' ||
            //     $stonetype === 'diamond' ||
            //     preg_match('/^natural diamond\s*(\/\s*(gemstn|gemstone))?$/i', $stonetypeRaw)
            // ) {
            //     echo 'Natural Diamond'.$variant['metal_v'].'=>'.$stonetype."<br>";
            //     $naturalDiamondVariants[] = $variant;
            // }
            else{
                //  echo 'else'. $variant['metal_v'].'=>'.$stonetype."<br>";
                 $naturalDiamondVariants[] = $variant;
            }
        }

        // Create Lab Grown record if exists
        if (!empty($labGrownVariants)) {
            $labItem = $item;
            $labItem['variants'] = $labGrownVariants;
            $labItem['sku'] = rtrim($labItem['sku'], '/') . '/Lab';
            $labItem['setcode'] = rtrim($labItem['setcode'], '/') . '/Lab';
            $labItem['stone_type'] = 'Lab Grown';
            $result[] = $labItem;
        }

        // Create Natural Diamond record if exists
        if (!empty($naturalDiamondVariants)) {
            $naturalItem = $item;
            $naturalItem['variants'] = $naturalDiamondVariants;
            $naturalItem['stone_type'] = 'Natural Diamond';
            $result[] = $naturalItem;
        }
    }
    
     $this->checkAndUpdateShopify($result);

    return $result;
}
  public function exportJewelryRecordsToCSV($jewelryRecords) {
    $headers = [
        // Parent-level fields
        'Jewelry Barcode', 'SKU', 'Stock', 'Set Code', 'Title', 'Description',
        'Product Type', 'Jewelry Category', 'Stone Type', 'Diamond Quantity', 'CTW',
        'Average Color', 'Average Clarity', 'Type Code', 'Category Code', 'Class Code',
        'Website Department', 'Website Brand', 'Collection Code', 'Colorstone Quality',
        'Colorstone Quantity', 'Color Name', 'Ebay Type', 'Setting Style', 'Metal Name',
        'Ring Size', 'Total Carat Weight', 'Occasion', 'Country of Origin', 'Unit Quantity',
        'Diamond Quality', 'New Arrival', 'Best Seller', 'Status', 'Tags', 'Created At', 'Updated At','parent_asin','parent_asin_lab',

        // Variant-level fields
        'Variant Item No', 'Variant Metal', 'Variant Metal Code', 'Variant Size', 'Variant Price','jewelryboutique price',
        'Compare at Price', 'CTW', 'Variant Quality', 'Variant Inventory Qty', 'Website Stone Type','child_asin'
    ];

    $fileName = 'jewelry_simplexdiam_' . date('Y-m-d') . '.csv';
    $file = fopen($fileName, 'w');

    // Write headers
    fputcsv($file, $headers);

    foreach ($jewelryRecords as $record) {
        // Prepare parent-level data (use null coalescing to avoid errors)
        $parentData = [
            $record['jewelrybarcode'] ?? '',
            $record['sku'] ?? '',
            $record['stock'] ?? '',
            $record['setcode'] ?? '',
            $record['title'] ?? '',
            $record['description'] ?? '',
            $record['product_type'] ?? '',
            $record['jewelry_category'] ?? '',
            $record['stone_type'] ?? '',
            $record['diamond_quantity'] ?? '',
            $record['appr_ctw'] ?? '',
            $record['avg_color'] ?? '',
            $record['avg_clarity'] ?? '',
            $record['type_code'] ?? '',
            $record['category_code'] ?? '',
            $record['class_code'] ?? '',
            // website_department might be array, implode with comma
            is_array($record['website_department'] ?? null) ? implode(',', $record['website_department']) : ($record['website_department'] ?? ''),
            $record['website_brand'] ?? '',
            $record['collection_code'] ?? '',
            $record['colorstone_quality'] ?? '',
            $record['colorstone_quantity'] ?? '',
            $record['color_name'] ?? '',
            $record['ebay_type'] ?? '',
            $record['setting_style'] ?? '',
            $record['metalname'] ?? '',
            $record['ring_size'] ?? '',
            $record['total_carat_weight'] ?? '',
            $record['ocassion'] ?? '',
            $record['country_of_origin'] ?? '',
            $record['unit_quantity'] ?? '',
            $record['diamond_quality'] ?? '',
            $record['new_arrival'] ?? '',
            $record['best_seller'] ?? '',
            $record['status'] ?? '',
            $record['tags'] ?? '',
            $record['created_at'] ?? '',
            $record['updated_at'] ?? '',
            $record['parent_asin'] ?? '',
            $record['parent_asin_lab'] ?? ''
        ];

        // Check if variants exist and are array
        if (isset($record['variants']) && is_array($record['variants']) && count($record['variants']) > 0) {
            foreach ($record['variants'] as $variant) {
                $variantData = [
                    $variant['item_no'] ?? '',
                    $variant['metal'] ?? '',
                    $variant['metal_v'] ?? '',
                    $variant['size'] ?? '',
                    $variant['price'] ?? '',
                    $variant['jewelryboutique_price'] ?? '',
                    $variant['compare_at_price'] ?? '',
                    $variant['ctw'] ?? '',
                    $variant['quality'] ?? '',
                    $variant['inventory_quantity'] ?? '',
                    $variant['website_stonetype'] ?? '',
                    $variant['child_asin'] ?? ''
                ];
                // Write combined parent + variant row
                fputcsv($file, array_merge($parentData, $variantData));
            }
        } else {
            // No variants: write parent data + empty variant columns
            $emptyVariant = array_fill(0, 10, '');
            fputcsv($file, array_merge($parentData, $emptyVariant));
        }
    }

    fclose($file);

    echo "CSV Exported successfully: $fileName\n";
}

    public function run() {
    echo "Fetching records...\n";
    $records = $this->getJewelryPr([]);
    if (empty($records)) {
        echo "No records found.\n";
        return;
    }

    echo "Processing records...\n";
    $processed = $this->splitJewelryByStoneTypePr($records);

  //  echo "Exporting to CSV...\n";
    
    // Commenting out the export to CSV functionality
  //  $this->exportJewelryRecordsToCSV($processed);

    echo "Done.\n";
}

private function checkAndUpdateShopify($jewelryRecords) {
    // Iterate over all jewelry records
    foreach ($jewelryRecords as $record) {            

//if ($record['jewelrybarcode'] == '554249' || $record['jewelrybarcode'] == '464238' || $record['jewelrybarcode'] == '546350' || $record['jewelrybarcode'] == '572155' || $record['jewelrybarcode'] == '511169' || $record['jewelrybarcode'] == '449902' || $record['jewelrybarcode'] == '224007' || $record['jewelrybarcode'] == '524338' || $record['jewelrybarcode'] == '490206' || $record['jewelrybarcode'] == '512650' || $record['jewelrybarcode'] == '531749' || $record['jewelrybarcode'] == '28954') {
        // Example: Check if the jewelry barcode matches a specific one 
      //   if ($record['jewelrybarcode'] == '554249' ) {
            // Check if the variants are present and valid
            if (isset($record['variants']) && is_array($record['variants'])) {
                foreach ($record['variants'] as $variant) {
                    // Get the Shopify SKU from the 'metal_v' field in the jewelry record
                    $shopifySku = $variant['metal_v'] ?? '';  // Jewelry record's 'metal_v' corresponds to Shopify SKU
                    echo "Checking SKU: " . $shopifySku . "<br>"; // This is where the output buffering will help
                    
                    if (!$shopifySku) {
                        continue; // Skip if no metal_v (Shopify SKU) in the jewelry record
                    }

                    // Check if the product exists in the database (sh_product_variant table) and get the variant_id
                    $checkVariant = $this->db->query(
                        "SELECT variant_id, product_id,inventory_item_id FROM sh_product_variant 
                         WHERE TRIM(sim_sku) = TRIM(BINARY '$shopifySku') 
                         ORDER BY id LIMIT 1"
                    )->result();

                    // Skip if no variant_id is found in the database
                    if (empty($checkVariant)) {
                        echo "No matching variant_id found for SKU: $shopifySku<br>";
                        continue; // Skip if no matching variant_id is found
                    }

                    $variant_id = $checkVariant[0]->variant_id;
                    $inventory_item_id = $checkVariant[0]->inventory_item_id;
                    // Fetch product details from Shopify using the product_id
                    $shopifyProduct = $this->getShopifyProductById($checkVariant[0]->product_id);  // Fetch product using product_id
                    
                    // Debugging: print the fetched Shopify product info
                    echo "Fetched Shopify Product for SKU: " . $shopifySku . "<br>";
                   // print_pre($shopifyProduct);  // Print the full product response for debugging
                   // echo "product_id". $checkVariant[0]->product_id;
                    if (!$shopifyProduct) {
                        echo "Product not found for SKU: $shopifySku<br>";
                        continue; // Skip if product is not found in Shopify
                    }

                    // Loop through all variants in the Shopify product
                    // $variantFound = false;
                    foreach ($shopifyProduct['variants'] as $shopifyVariant) {
                        // Compare the SKU of the variant with the jewelry variant SKU
                        // if ($shopifyVariant['sku'] == $shopifySku) {
                        //     $variantFound = true; // Set flag to true if the variant exists          
                            $shopifyPrice = $shopifyVariant['price'] ?? null;
                            $shopifyInventoryQty = $shopifyVariant['inventory_quantity'] ?? null;

                            // Initialize mismatch flag
                            $mismatch = false;
                            $compare_at_price = null;
                            echo "SKU:". $shopifySku ."shopifyPrice:". $shopifyPrice ."for variantprice:". $variant['price']." <br>";
                            // If price mismatch, log and update
                            if ($shopifyPrice != $variant['price']) {
                                $price = floatval($variant['price']);
                                // Determine the price increase based on the price range
                                if ($price < 200) {
                                    $increase = 50; 
                                } elseif ($price >= 200 && $price < 500) {
                                    $increase = 60; 
                                } elseif ($price >= 500 && $price < 1000) {
                                    $increase = 67; 
                                } elseif ($price >= 1000 && $price < 2000) {
                                    $increase = 73; 
                                } elseif ($price >= 2000 && $price < 5000) {
                                    $increase = 80; 
                                } else {
                                    $increase = 100;  
                                }
                                // Avoid division by zero
                                if ($increase == 100) {
                                    $compare_at_price = $price * 2; // 100% increase means double the price
                                } else {
                                    $compare_at_price = $price / (1 - $increase / 100);
                                }

                                // Round the compare_at_price
                                $compare_at_price = round($compare_at_price);

                                $mismatch = true;
                                echo "Price mismatch for SKU: $shopifySku <br>";
                                echo "Shopify Price: $shopifyPrice, Jewelry Price: " . $variant['price'] . "<br>";
                            }

                            // If inventory mismatch, log and update
                            if ($shopifyInventoryQty != $variant['inventory_quantity']) {
                                $mismatch = true;
                                echo "Inventory mismatch for SKU: $shopifySku\n";
                                echo "Shopify Inventory: $shopifyInventoryQty, Jewelry Inventory: " . $variant['inventory_quantity'] . "\n";
                                // if (isset($shopifyVariant['inventory_item_id']) && isset($shopifyVariant['inventory_item_id']) && $shopifyVariant['inventory_item_id']) {
                                    	$updateLocal = [];
                                	$dataInventory = [
                            			    "location_id"=> SHOP_LOCATION,
                            			    "inventory_item_id"=> $inventory_item_id,
                            			    "available"=> $variant['inventory_quantity']  ?: 0
                            			];
                            			$updatedRecord = $this->updateInventory(json_encode($dataInventory));
                            
                            			if(empty($updatedRecord)) {
                            				$updateLocal[] = [
                            					'variant_id'=> $variant_id,
                            					'is_quantity_update'=> 2,
                            				];
                            
                            				continue;
                            			}
                            
                                		$updateLocal[] = [
                            				'variant_id'=> $variant_id,
                            				'is_quantity_update'=> 1,
                            			];
                            		  if (!empty($updateLocal)) {
                            			$this->db->update_batch('sh_product_variant', $updateLocal, 'variant_id');
                            		}
                                    
                            }

                            // If there's any mismatch in price or inventory, update only the variant in Shopify and the database
                            if ($mismatch) {
                                
                                // Prepare the JSON body for the Shopify API update request
                                $jsonBody = json_encode([
                                    'variant' => [
                                        'id' => $variant_id,  // Shopify variant ID
                                        'price' => $variant['price'],  // New price
                                        'compare_at_price' => $compare_at_price,  // New compare_at_price
                                        'inventory_quantity' => $variant['inventory_quantity']  // New inventory quantity
                                    ]
                                ]);

                                // Call the Shopify API directly to update the variant
                                $this->updateVariantInShopify($variant_id, $jsonBody);
                            }
                        }
                    }

                   
                }
            }
     //   }
   }

    // End output buffering and send the output

// Function to update inventory in Shopify
private function updateInventory($jsonBody) {
     sleep(1);
    if (empty($jsonBody)) {
        return [];
    }

    $client = new Client([
        'base_uri' => SHOP_URL
    ]);

    $headers = [
        'Content-Type' => 'application/json',
        'X-Shopify-Access-Token' => SHOP_TOKEN
    ];

    try {
        // Send POST request to update inventory level
        $response = $client->request('POST', "inventory_levels/set.json", [
            'http_errors' => false,
            'headers' => $headers,
            'body' => $jsonBody
        ]);

        $body = $response->getBody();
        $parsedBody = json_decode($body, true);

        // Check for response status and log errors
        if ($response->getStatusCode() > 300) {
            $dataError = [
                'request' => $jsonBody,
                'response' => json_encode($parsedBody),
                'method' => 'POST',
                'endpoint' => "inventory_levels/set.json",
                'added_at' => date('Y-m-d h:i'),
            ];
            $this->db->insert('error_log', $dataError);

            return [];
        }

        return $parsedBody;
    } catch (\Exception $e) {
        echo "Error updating inventory: " . $e->getMessage() . "<br>";
        return [];
    }
}

private function updateVariantInShopify($variant_id, $jsonBody) {
     sleep(1);
    $client = new Client([
        'base_uri' => SHOP_URL,  // Your Shopify store URL (e.g., https://your-shop-name.myshopify.com)
    ]);

    $headers = [
        'Content-Type' => 'application/json',
        'X-Shopify-Access-Token' => SHOP_TOKEN  // Your Shopify Access Token
    ];

    try {
        // Send the PUT request to update the variant
        $response = $client->request('PUT', "/admin/api/2025-07/variants/{$variant_id}.json", [
            'headers' => $headers,
            'body' => $jsonBody
        ]);

        // Check if the request was successful
        if ($response->getStatusCode() == 200) {
            echo "Variant updated successfully: Variant ID {$variant_id}<br>";
        } else {
            echo "Failed to update variant. Status code: " . $response->getStatusCode() . "<br>";
        }
    } catch (\Exception $e) {
        echo "Error updating variant: " . $e->getMessage() . "<br>";
    }
}
// private function getShopifyProductById($product_id) {
//     // Use the product_id to fetch the Shopify product details
//     $client = new Client([
//         'base_uri' => SHOP_URL  // Shopify store URL (set in your config)
//     ]);

//     $headers = [
//         'Content-Type' => 'application/json',
//         'X-Shopify-Access-Token' => SHOP_TOKEN  // Shopify Access Token
//     ];

//     try {
//         // Fetch product by ID
//         $response = $client->request('GET', "products/{$product_id}.json", [
//             'http_errors' => false,
//             'headers' => $headers
//         ]);

//         if ($response->getStatusCode() == 200) {
//             $body = $response->getBody();
//             $product = json_decode($body, true);
//             return $product['product'] ?? null;  // Return product details
//         }

//     } catch (\Exception $e) {
//         echo "Error fetching Shopify product by ID: " . $e->getMessage() . "\n";
//     }

//     return null;  // Return null if the product is not found
// }

private function getShopifyProductById($product_id) {
    	sleep(5);
    $client = new Client([
        'base_uri' => SHOP_URL  // Shopify store URL (set in your config)
    ]);

    $headers = [
        'Content-Type' => 'application/json',
        'X-Shopify-Access-Token' => SHOP_TOKEN  // Shopify Access Token
    ];

    $maxRetries = 5;  // Number of retries on failure
    $retryDelay = 1;  // Initial delay in seconds (for exponential backoff)
    $retryCount = 0;

    while ($retryCount < $maxRetries) {
        try {
            // Fetch product by ID
            $response = $client->request('GET', "products/{$product_id}.json", [
                'http_errors' => false,
                'timeout' => 10,  // Set timeout for the request
                'headers' => $headers
            ]);

            $statusCode = $response->getStatusCode();
            $body = $response->getBody();
            
            if ($statusCode == 200) {
                $product = json_decode($body, true);

                if ($product === null) {
                    echo "Error decoding JSON response: " . json_last_error_msg() . "\n";
                    return null;
                }

                return $product['product'] ?? null;  // Return product details
            } elseif ($statusCode == 429) {
                // Handle rate limiting (429)
                $retryAfter = $response->getHeaderLine('Retry-After');
                $retryDelay = $retryAfter ? (int) $retryAfter : $retryDelay * 2; // Exponential backoff
                echo "Rate limit exceeded. Retrying after {$retryDelay} seconds...\n";

                // Sleep for the delay before retrying
                sleep($retryDelay);
                $retryCount++;
            } else {
                echo "Failed to fetch product. Status Code: " . $statusCode . "\n";
                echo "Response Body: " . $body . "\n";  // Log body for debugging
                return null;
            }
        } catch (\GuzzleHttp\Exception\RequestException $e) {
            echo "Error fetching Shopify product by ID: " . $e->getMessage() . "\n";
            return null;
        }
    }

    echo "Max retries reached. Could not fetch the product.\n";
    return null;  // Return null if all retries fail
}

// private function updateProduct($jsonBody, $productId) {
//     // Initialize the HTTP client
//     $client = new Client([
//         'base_uri' => SHOP_URL  // Shopify store URL (set in your config)
//     ]);

//     // Set the headers including the Shopify access token
//     $headers = [
//         'Content-Type' => 'application/json',
//         'X-Shopify-Access-Token' => SHOP_TOKEN  // Shopify Access Token
//     ];

//     try {
//         // Send a PUT request to update the product variant price and inventory
//         $response = $client->request('PUT', "products/{$productId}.json", [
//             'http_errors' => false,
//             'headers' => $headers,
//             'body' => $jsonBody
//         ]);

//         // Check if the response is successful
//         if ($response->getStatusCode() == 200) {
//             // Successful update
//             echo "Product updated successfully on Shopify\n";
//             return json_decode($response->getBody(), true);  // Return the updated product response
//         } else {
//             // If error occurs, log the status code
//             echo "Error updating product on Shopify. Status code: " . $response->getStatusCode() . "\n";
//             return null;  // Return null if update failed
//         }

//     } catch (\Exception $e) {
//         // Catch any errors that occur during the API request
//         echo "Error updating Shopify product: " . $e->getMessage() . "\n";
//         return null;
//     }
// }

//   private function getShopifyProduct($sku) {
//     // Use the SKU to fetch the Shopify product details
//     $client = new Client([
//         'base_uri' => SHOP_URL  // Shopify store URL (set in your config)
//     ]);

//     $headers = [
//         'Content-Type' => 'application/json',
//         'X-Shopify-Access-Token' => SHOP_TOKEN  // Shopify Access Token
//     ];

//     try {
//         // Fetch all products and their variants
//         $response = $client->request('GET', 'products.json', [
//             'http_errors' => false,
//             'headers' => $headers,
//             'query' => ['fields' => 'id,variants']  // Only request necessary fields
//         ]);

//         if ($response->getStatusCode() == 200) {
//             $body = $response->getBody();
//             $products = json_decode($body, true);

//             // Loop through each product and check if the SKU exists in any variant
//             foreach ($products['products'] as $product) {
//                 foreach ($product['variants'] as $variant) {
//                     // If SKU matches the variant SKU, return the product
//                     if ($variant['sku'] == $sku) {
//                         return $product;  // Return the product if SKU matches
//                     }
//                 }
//             }
//         }

//     } catch (\Exception $e) {
//         echo "Error fetching Shopify product: " . $e->getMessage() . "\n";
//     }

//     return null;  // Return null if no product/variant matches the SKU
// }
  
}
