<?php
/**
 * Pricing Service Component
 * Handles pricing lookups with user-specific price bands and account-based pricing
 * 
 * @package PortalPeople\mcp\components
 * @author Portal People Development Team
 */

namespace PortalPeople\mcp\components;

use Yii;
use yii\base\Component;
use common\models\User;

/**
 * PricingService provides pricing information based on user accounts
 * 
 * Usage:
 * ```php
 * $pricing = new PricingService();
 * $price = $pricing->getPrice('item-123', 'user-456');
 * $prices = $pricing->getPricesBulk(['item-1', 'item-2'], 'user-123');
 * ```
 */
class PricingService extends Component
{
    /**
     * Default price band if user has no account
     */
    public const DEFAULT_PRICE_BAND = 'price1';
    
    /**
     * Default currency
     */
    public const DEFAULT_CURRENCY = 'GBP';

    /**
     * Get price for a single item
     * 
     * @param string $itemId The item/product ID
     * @param string|null $userId The user ID (optional)
     * @param string|null $accountCode The account code (optional, overrides user lookup)
     * @return array Price information including price, currency, price_band
     */
    public function getPrice(string $itemId, ?string $userId = null, ?string $accountCode = null): array
    {
        $priceBand = $this->getPriceBand($userId, $accountCode);
        
        // Look up product - adjust model name based on your schema
        $product = $this->findProduct($itemId);
        
        if (!$product) {
            return [
                'item_id' => $itemId,
                'price' => null,
                'currency' => self::DEFAULT_CURRENCY,
                'price_band' => $priceBand,
                'available' => false,
                'error' => 'Product not found'
            ];
        }
        
        // Get the price from the appropriate price band column
        $price = $this->extractPrice($product, $priceBand);
        
        return [
            'item_id' => $itemId,
            'price' => $price,
            'currency' => self::DEFAULT_CURRENCY,
            'price_band' => $priceBand,
            'available' => true,
            'product_name' => $product->name ?? $product->title ?? null,
            'sku' => $product->sku ?? $product->code ?? null
        ];
    }

    /**
     * Get prices for multiple items (bulk operation)
     * 
     * @param array $itemIds Array of item/product IDs
     * @param string|null $userId The user ID (optional)
     * @param string|null $accountCode The account code (optional)
     * @return array Array of price information for each item
     */
    public function getPricesBulk(array $itemIds, ?string $userId = null, ?string $accountCode = null): array
    {
        $priceBand = $this->getPriceBand($userId, $accountCode);
        $results = [];
        
        foreach ($itemIds as $itemId) {
            $results[] = $this->getPrice($itemId, $userId, $accountCode);
        }
        
        return $results;
    }

    /**
     * Search for products with price information
     * 
     * @param array $criteria Search criteria (category, min_price, max_price, etc.)
     * @param string|null $userId The user ID (optional)
     * @param int $limit Maximum number of results
     * @return array Search results with pricing
     */
    public function searchPrices(array $criteria, ?string $userId = null, int $limit = 50): array
    {
        $priceBand = $this->getPriceBand($userId);
        
        // Build query based on your product model
        $query = $this->buildProductQuery();
        
        // Apply filters
        if (isset($criteria['category'])) {
            $query->andWhere(['category' => $criteria['category']]);
        }
        
        if (isset($criteria['min_price']) || isset($criteria['max_price'])) {
            // Filter by price in the user's price band
            if (isset($criteria['min_price'])) {
                $query->andWhere(['>=', $priceBand, $criteria['min_price']]);
            }
            if (isset($criteria['max_price'])) {
                $query->andWhere(['<=', $priceBand, $criteria['max_price']]);
            }
        }
        
        $products = $query->limit($limit)->all();
        
        $results = [];
        foreach ($products as $product) {
            $results[] = [
                'item_id' => $product->id,
                'price' => $this->extractPrice($product, $priceBand),
                'currency' => self::DEFAULT_CURRENCY,
                'price_band' => $priceBand,
                'product_name' => $product->name ?? $product->title ?? null,
                'sku' => $product->sku ?? $product->code ?? null
            ];
        }
        
        return $results;
    }

    /**
     * Get the price band for a user or account
     * 
     * @param string|null $userId User ID
     * @param string|null $accountCode Account code (overrides user lookup)
     * @return string Price band (e.g., 'price1', 'price2', etc.)
     */
    protected function getPriceBand(?string $userId = null, ?string $accountCode = null): string
    {
        // If account code is provided directly, look up account
        if ($accountCode !== null) {
            $account = \backend\models\Accounts::findOne(['account_code' => trim($accountCode)]);
            if ($account && $account->price_number !== null) {
                $priceNo = $account->price_number;
                if ($priceNo > 0 && $priceNo < 10) {
                    return 'price' . $priceNo;
                }
            }
        }
        
        // If user ID is provided, get user's price band
        if ($userId !== null) {
            $user = User::findOne($userId);
            if ($user) {
                $accountData = is_string($user->accountData) 
                    ? json_decode($user->accountData, true) 
                    : $user->accountData;
                    
                if (is_array($accountData) && isset($accountData['priceBand'])) {
                    return $accountData['priceBand'];
                }
                
                // Fall back to getting account from user
                $account = $user->account;
                if ($account && $account->price_number !== null) {
                    $priceNo = $account->price_number;
                    if ($priceNo > 0 && $priceNo < 10) {
                        return 'price' . $priceNo;
                    }
                }
            }
        }
        
        return self::DEFAULT_PRICE_BAND;
    }

    /**
     * Find a product by ID
     * Override this method to match your product model structure
     * 
     * @param string $itemId
     * @return \yii\db\ActiveRecord|null
     */
    protected function findProduct(string $itemId)
    {
        // Try different product models - adjust based on your schema
        $modelClasses = [
            '\backend\models\Products',
            '\backend\models\Productsbe',
            '\backend\models\Items',
            '\backend\models\Itemsbe',
        ];
        
        foreach ($modelClasses as $modelClass) {
            if (class_exists($modelClass)) {
                $product = $modelClass::findOne($itemId);
                if ($product) {
                    return $product;
                }
            }
        }
        
        return null;
    }

    /**
     * Build base product query
     * Override this to match your product model structure
     * 
     * @return \yii\db\ActiveQuery
     */
    protected function buildProductQuery()
    {
        $modelClasses = [
            '\backend\models\Products',
            '\backend\models\Productsbe',
            '\backend\models\Items',
            '\backend\models\Itemsbe',
        ];
        
        foreach ($modelClasses as $modelClass) {
            if (class_exists($modelClass)) {
                return $modelClass::find();
            }
        }
        
        throw new \RuntimeException('No product model found');
    }

    /**
     * Extract price from product based on price band
     * 
     * @param \yii\db\ActiveRecord $product
     * @param string $priceBand
     * @return float|null
     */
    protected function extractPrice($product, string $priceBand): ?float
    {
        // Try to get the price from the price band column
        if (property_exists($product, $priceBand) || isset($product->$priceBand)) {
            return (float)$product->$priceBand;
        }
        
        // Fallback to common price fields
        $fallbackFields = ['price', 'cost', 'amount', 'price1'];
        foreach ($fallbackFields as $field) {
            if (property_exists($product, $field) || isset($product->$field)) {
                return (float)$product->$field;
            }
        }
        
        return null;
    }

    /**
     * Get account information for a user
     * 
     * @param string $userId
     * @return array|null Account data
     */
    public function getAccountInfo(string $userId): ?array
    {
        $user = User::findOne($userId);
        if (!$user) {
            return null;
        }
        
        $account = $user->account;
        if (!$account) {
            return null;
        }
        
        $priceBand = 'price1';
        if ($account->price_number !== null) {
            $priceNo = $account->price_number;
            if ($priceNo > 0 && $priceNo < 10) {
                $priceBand = 'price' . $priceNo;
            }
        }
        
        return [
            'account_id' => $account->id,
            'account_code' => $account->account_code,
            'account_group' => $account->account_group,
            'price_band' => $priceBand,
            'price_number' => $account->price_number,
        ];
    }
}
