<?php

namespace App\Actions;

use App\Helpers\GoldPriceHelper;
use App\Jobs\SendGoldPriceUpdateEmail;
use App\Models\GoldPrice;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

use Shopify\Clients\Graphql;
use stdClass;

class UpdateShopifyCollectionCostPriceFrontGold
{
    public function __invoke(Request $request, $sendEmail = true)
    {
        try {
            $operation = $request->input('operation');

            $collection_id = $request->input('collection_id');
            $collection_name = $request->input('collection_name');
            $material = $request->input('material');
            $priceManual = $request->input('price'); // Get manual price if sent from frontend

            // Determine which price to use
            if ($priceManual !== null && $priceManual !== '') {
                // Use manual price from frontend (button "Update")
                $price = round(floatval($priceManual));
            } else {
                // Calculate price using helper (button "Use Gold Price")
                $latestGoldPrice = GoldPrice::latest('created_at')->first();

                if (!$latestGoldPrice) {
                    Log::error('No gold price found in database');
                    throw new \RuntimeException("No gold price found in database");
                }

                $pricePerGram = GoldPriceHelper::calculateGoldPricePerGram($collection_name, $material, $latestGoldPrice->price);
                $price = round($pricePerGram); // Round to integer
            }

            $shop = env('SHOPIFY_DOMAIN');
            $token = env('SHOPIFY_ACCESS_TOKEN');




            if (!$shop || !$token) {
                Log::error("Shopify domain or access token is not set in environment variables.");
                return response()->json(['error' => 'Shopify configuration missing'], 500);
            }

            $client = new Graphql($shop, $token);

            $query = <<<'GRAPHQL'
            query getProductsFromCollection($collection_id: ID!) {
                collection(id: $collection_id) {
                    id
                    title
                    products(first: 200) {
                        edges {
                            node {
                                id
                                title
                                variants(first: 200) {
                                    edges {
                                        node {
                                            id
                                            title
                                            price
                                            compareAtPrice
                                            metafield(namespace: "custom", key: "material") {
                                                key
                                                value
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        GRAPHQL;

            $variables = [
                'collection_id' =>  $collection_id,
            ];


            $response = $client->query(["query" => $query, "variables" => $variables]);

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

            $productsShop  =  $data['data']['collection']['products']['edges'] ?? [];

            $totalVariantsUpdated = 0; // Total variants of the specified material that were updated
            $totalVariantsProcessed = 0; // Total variants of the specified material that were processed
            $totalVariantsErrors = 0;
            $totalProductsUpdated = 0; // Total products updated (products with at least one variant updated)

            foreach ($productsShop as $items) {
                $productId = $items['node']['id'];
                try {
                    $result = (new UpdateShopifyVariantCostPriceActionByMaterial())($material, $productId, $price);

                    // Extract variant count from result (handle both array and object formats)
                    if ($result && is_array($result) && isset($result['data'])) {
                        $variantData = $result['data'];
                        // Handle both object (stdClass) and array formats
                        if (is_object($variantData)) {
                            if (isset($variantData->variants_updated)) {
                                $totalVariantsUpdated += (int)$variantData->variants_updated;
                            }
                            if (isset($variantData->variants_matching_material)) {
                                $totalVariantsProcessed += (int)$variantData->variants_matching_material;
                            }
                            if (isset($variantData->variant_error)) {
                                $totalVariantsErrors += (int)$variantData->variant_error;
                            }
                            if (isset($variantData->product_updated) && $variantData->product_updated) {
                                $totalProductsUpdated++; // Count product as updated if it has at least one variant updated
                            }
                        } elseif (is_array($variantData)) {
                            if (isset($variantData['variants_updated'])) {
                                $totalVariantsUpdated += (int)$variantData['variants_updated'];
                            }
                            if (isset($variantData['variants_matching_material'])) {
                                $totalVariantsProcessed += (int)$variantData['variants_matching_material'];
                            }
                            if (isset($variantData['variant_error'])) {
                                $totalVariantsErrors += (int)$variantData['variant_error'];
                            }
                            if (isset($variantData['product_updated']) && $variantData['product_updated']) {
                                $totalProductsUpdated++; // Count product as updated if it has at least one variant updated
                            }
                        }
                    }
                } catch (\Exception $e) {
                    Log::error("Error updating variants for product", [
                        'product_id' => $productId,
                        'error' => $e->getMessage()
                    ]);
                    // Continue with next product instead of stopping the whole process
                }
            }

            // Send email notification only if sendEmail is true (manual updates from frontend)
            if ($sendEmail) {
                $latestGoldPrice = GoldPrice::latest('created_at')->first();
                $priceUsed = $priceManual !== null && $priceManual !== ''
                    ? $price
                    : GoldPriceHelper::calculateGoldPricePerGram($collection_name, $material, $latestGoldPrice->price);

                $emailCollections = [[
                    'name' => $collection_name,
                    'products_processed' => count($productsShop), // Total products in collection
                    'price_10k' => $material === '10k' ? $priceUsed : null,
                    'price_14k' => $material === '14k' ? $priceUsed : null,
                    'products_updated_10k' => $material === '10k' ? $totalProductsUpdated : 0, // Products updated (not variants)
                    'products_updated_14k' => $material === '14k' ? $totalProductsUpdated : 0, // Products updated (not variants)
                    'errors_10k' => $material === '10k' ? $totalVariantsErrors : 0,
                    'errors_14k' => $material === '14k' ? $totalVariantsErrors : 0,
                    'has_errors' => $totalVariantsErrors > 0,
                    'error_details' => [],
                ]];

                try {
                    SendGoldPriceUpdateEmail::dispatch('manual', $emailCollections, $latestGoldPrice->price);
                } catch (\Exception $e) {
                    Log::error("Failed to dispatch email notification", [
                        'error' => $e->getMessage(),
                        'trace' => $e->getTraceAsString()
                    ]);
                }
            }

            $response = [
                'status' => 200,
                'message' => 'Prices updated successfully',
                'data' => [
                    'collection' => $collection_name,
                    'material' => $material,
                    'price' => $price,
                    'variants_updated' => $totalVariantsUpdated, // Real count of variants updated
                    'variants_processed' => $totalVariantsProcessed, // Real count of variants processed (matching material)
                    'products_updated' => $totalProductsUpdated, // Real count of products updated (products with at least one variant updated)
                    'variants_errors' => $totalVariantsErrors,
                ],
            ];

            return response()->json($response, 200);
        } catch (\Throwable $th) {

            Log::error("Failed to update Shopify products variants", [
                'message' => $th->getMessage(),
                'trace' => $th->getTraceAsString(),
            ]);

            $response = [
                'status' => 500,
                'message' => $th->getMessage(),
                'data' => null,
            ];

            return response()->json($response, 500);
        }
    }
}
