<?php

namespace App\Console\Commands;

use App\Actions\ListShopifyCollectionsAction;
use App\Helpers\GoldPriceHelper;
use App\Models\Configuration;
use App\Models\GoldPrice;
use App\Models\GoldPriceWeightRule;
use Illuminate\Console\Command;
use Shopify\Clients\Graphql;

class TestWeightRulesDemo extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'test:weight-rules-demo {--collection= : Collection name to test}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Test weight-based rules calculation (DEMO - does not update Shopify)';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $this->info('=== TEST: Weight-Based Rules Demo ===');
        $this->newLine();

        // Step 1: Create or get test rule (0-20g)
        $this->info('Step 1: Setting up test rule (0-20g)...');
        $testRule = $this->setupTestRule();
        if (!$testRule) {
            $this->error('Failed to create test rule');
            return 1;
        }
        $this->info("✓ Test rule created: {$testRule->min_weight}g - {$testRule->max_weight}g");
        $this->info("  Fee 10k: \${$testRule->fee_10k} | Fee 14k: \${$testRule->fee_14k}");
        $this->newLine();

        // Step 2: Get collection
        $collectionName = $this->option('collection');
        if (!$collectionName) {
            $config = Configuration::getInstance();
            $collections = $config->collections ?? [];
            if (empty($collections)) {
                $this->error('No collections configured. Please specify --collection=CollectionName');
                return 1;
            }
            $firstEnabled = collect($collections)->firstWhere('enabled', true);
            if (!$firstEnabled) {
                $this->error('No enabled collections found. Please specify --collection=CollectionName');
                return 1;
            }
            $collectionName = $firstEnabled['name'];
            $this->info("Using first enabled collection: {$collectionName}");
        }

        $this->info("Step 2: Fetching collection '{$collectionName}' from Shopify...");
        $collectionsData = (new ListShopifyCollectionsAction())($collectionName);
        $collections = $collectionsData['collections'] ?? [];

        if (empty($collections)) {
            $this->error("Collection '{$collectionName}' not found in Shopify");
            return 1;
        }

        $collection = $collections[0];
        $collectionId = is_array($collection) ? $collection['id'] : $collection->id;
        $collectionTitle = is_array($collection) ? $collection['title'] : $collection->title;
        $this->info("✓ Collection found: {$collectionTitle} (ID: {$collectionId})");
        $this->newLine();

        // Step 3: Get products from collection
        $this->info('Step 3: Fetching products from collection...');
        $products = $this->fetchCollectionProducts($collectionId);
        $this->info("✓ Found " . count($products) . " products");
        $this->newLine();

        // Step 4: Get latest gold price
        $latestGoldPrice = GoldPrice::latest('created_at')->first();
        if (!$latestGoldPrice) {
            $this->error('No gold price found in database');
            return 1;
        }
        $this->info("Step 4: Using gold price: \${$latestGoldPrice->price}/troy oz");
        $this->newLine();

        // Step 5: Calculate prices for each variant
        $this->info('Step 5: Calculating prices using weight rules...');
        $this->newLine();

        $results = [];
        $variantCount = 0;

        foreach ($products as $product) {
            $productId = $product['node']['id'];
            $productTitle = $product['node']['title'];
            $variants = $product['node']['variants']['edges'] ?? [];

            foreach ($variants as $variant) {
                $variantId = $variant['node']['id'];
                $variantTitle = $variant['node']['title'];
                $currentPrice = (float)($variant['node']['price'] ?? 0);
                
                // Get weight
                $weight = $variant['node']['inventoryItem']['measurement']['weight']['value'] ?? 0;
                $weightUnit = $variant['node']['inventoryItem']['measurement']['weight']['unit'] ?? 'g';
                
                // Get material
                $metalPurity = strtolower($variant['node']['metafield']['value'] ?? '');
                $material = null;
                if (strpos($metalPurity, '10k') !== false) {
                    $material = '10k';
                } elseif (strpos($metalPurity, '14k') !== false) {
                    $material = '14k';
                }

                // Skip if no weight or no material
                if ($weight <= 0 || !$material) {
                    continue;
                }

                // Convert weight to grams if needed
                if ($weightUnit !== 'g' && $weightUnit !== 'GRAMS') {
                    // Assume it's already in grams or skip conversion for demo
                    $this->warn("  ⚠ Variant has weight unit '{$weightUnit}', assuming grams");
                }

                // Calculate price using weight rules
                $pricePerGram = GoldPriceHelper::calculateGoldPricePerGram(
                    $collectionName,
                    $material,
                    $latestGoldPrice->price,
                    $weight // Pass weight to use weight-based rules
                );

                // Check if rule was applied
                $appliedRule = GoldPriceWeightRule::findRuleForWeight($weight);
                $ruleApplied = $appliedRule ? 'Yes' : 'No';
                $feeUsed = $appliedRule 
                    ? ($material === '10k' ? $appliedRule->fee_10k : $appliedRule->fee_14k)
                    : 'General';

                $calculatedPrice = round($pricePerGram * $weight);
                $priceDifference = $calculatedPrice - $currentPrice;

                $results[] = [
                    'product' => $productTitle,
                    'variant' => $variantTitle,
                    'material' => strtoupper($material),
                    'weight' => number_format($weight, 3) . 'g',
                    'current_price' => '$' . number_format($currentPrice, 2),
                    'price_per_gram' => '$' . number_format($pricePerGram, 2),
                    'calculated_price' => '$' . number_format($calculatedPrice, 2),
                    'rule_applied' => $ruleApplied,
                    'fee_used' => is_numeric($feeUsed) ? '$' . number_format($feeUsed, 2) : $feeUsed,
                    'difference' => '$' . number_format($priceDifference, 2),
                ];

                $variantCount++;
            }
        }

        // Step 6: Display results table
        $this->info("Step 6: Results Summary");
        $this->info("Total variants processed: {$variantCount}");
        $this->newLine();

        if (empty($results)) {
            $this->warn('No variants found with weight and material information');
            return 0;
        }

        // Display table
        $headers = [
            'Product',
            'Variant',
            'Material',
            'Weight',
            'Current Price',
            'Price/Gram',
            'Calculated Price',
            'Rule Applied',
            'Fee Used',
            'Difference'
        ];

        $this->table($headers, $results);

        // Summary statistics
        $this->newLine();
        $this->info('=== Summary Statistics ===');
        
        $withRule = collect($results)->where('rule_applied', 'Yes')->count();
        $withoutRule = collect($results)->where('rule_applied', 'No')->count();
        
        $this->info("Variants with weight rule applied: {$withRule}");
        $this->info("Variants using general fees: {$withoutRule}");
        
        $avgDifference = collect($results)->avg(function ($item) {
            return (float)str_replace(['$', ','], '', $item['difference']);
        });
        $this->info("Average price difference: $" . number_format($avgDifference, 2));

        $this->newLine();
        $this->info('=== Test Complete ===');
        $this->warn('NOTE: This was a DEMO. No prices were updated in Shopify.');

        return 0;
    }

    /**
     * Setup test rule (0-20g)
     */
    private function setupTestRule(): ?GoldPriceWeightRule
    {
        // Check if rule already exists
        $existingRule = GoldPriceWeightRule::where('min_weight', 0)
            ->where('max_weight', 20)
            ->first();

        if ($existingRule) {
            // Update fees for testing
            $existingRule->update([
                'fee_10k' => 3.00,
                'fee_14k' => 4.00,
            ]);
            return $existingRule;
        }

        // Create new rule
        try {
            $rule = GoldPriceWeightRule::create([
                'min_weight' => 0,
                'max_weight' => 20,
                'fee_10k' => 3.00,
                'fee_14k' => 4.00,
                'order' => 0,
            ]);
            return $rule;
        } catch (\Exception $e) {
            $this->error("Error creating test rule: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Fetch products from collection
     */
    private function fetchCollectionProducts(string $collectionId): array
    {
        $shop = env('SHOPIFY_DOMAIN');
        $token = env('SHOPIFY_ACCESS_TOKEN');

        if (!$shop || !$token) {
            throw new \Exception('Shopify configuration missing');
        }

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

        $query = <<<'GRAPHQL'
            query getProductsFromCollection($collection_id: ID!) {
                collection(id: $collection_id) {
                    id
                    title
                    products(first: 50) {
                        edges {
                            node {
                                id
                                title
                                variants(first: 50) {
                                    edges {
                                        node {
                                            id
                                            title
                                            price
                                            metafield(namespace: "custom", key: "metal_purity") {
                                                key
                                                value
                                            }
                                            inventoryItem {
                                                measurement {
                                                    weight {
                                                        unit
                                                        value
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        GRAPHQL;

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

        $response = $client->query(["query" => $query, "variables" => $variables]);
        $data = json_decode($response->getBody(), true);

        return $data['data']['collection']['products']['edges'] ?? [];
    }
}
