<?php

namespace Modules\CashRegister\Services;

use Modules\CashRegister\Entities\CashRegisterSession;
use Modules\CashRegister\Entities\CashRegisterTransaction;
use Modules\CashRegister\Entities\CashDenomination;
use Modules\CashRegister\Entities\Denomination;
use Illuminate\Support\Facades\Cache;

/**
 * Cash Register Cache Service
 * Provides caching for frequently accessed cash register data
 */
class CashRegisterCacheService
{
    /**
     * Cache duration in seconds
     */
    const CACHE_TTL = 300; // 5 minutes
    const SESSION_CACHE_TTL = 60; // 1 minute (sessions change frequently)
    const DENOMINATION_CACHE_TTL = 3600; // 1 hour (denominations rarely change)

    /**
     * Get active session for user (cached)
     * 
     * @param int $userId
     * @param int $branchId
     * @return CashRegisterSession|null
     */
    public static function getActiveSession(int $userId, int $branchId): ?CashRegisterSession
    {
        $cacheKey = "cashregister.session.active.{$userId}.{$branchId}";
        
        return Cache::remember($cacheKey, self::SESSION_CACHE_TTL, function () use ($userId, $branchId) {
            return CashRegisterSession::with(['branch', 'cashier', 'openedBy'])
                ->where('opened_by', $userId)
                ->where('branch_id', $branchId)
                ->where('status', 'open')
                ->latest('opened_at')
                ->first();
        });
    }

    /**
     * Clear session cache for user
     * 
     * @param int $userId
     * @param int|null $branchId
     */
    public static function clearSessionCache(int $userId, ?int $branchId = null): void
    {
        if ($branchId) {
            Cache::forget("cashregister.session.active.{$userId}.{$branchId}");
        } else {
            // Clear for all branches
            $branches = \App\Models\Branch::pluck('id');
            foreach ($branches as $bid) {
                Cache::forget("cashregister.session.active.{$userId}.{$bid}");
            }
        }
    }

    /**
     * Get denominations for branch (cached)
     * 
     * @param int $branchId
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public static function getDenominationsForBranch(int $branchId)
    {
        $cacheKey = "cashregister.denominations.branch.{$branchId}";
        
        return Cache::remember($cacheKey, self::DENOMINATION_CACHE_TTL, function () use ($branchId) {
            // Try branch-specific denominations first
            $denominations = Denomination::where('branch_id', $branchId)
                ->where('is_active', true)
                ->orderBy('sort_order')
                ->get();
            
            // Fallback to restaurant-level if no branch-specific
            if ($denominations->isEmpty()) {
                $branch = \App\Models\Branch::find($branchId);
                if ($branch) {
                    $denominations = Denomination::where('restaurant_id', $branch->restaurant_id)
                        ->whereNull('branch_id')
                        ->where('is_active', true)
                        ->orderBy('sort_order')
                        ->get();
                }
            }
            
            return $denominations;
        });
    }

    /**
     * Get session totals (cached for 30 seconds)
     * 
     * @param int $sessionId
     * @return array
     */
    public static function getSessionTotals(int $sessionId): array
    {
        $cacheKey = "cashregister.session.totals.{$sessionId}";
        
        return Cache::remember($cacheKey, 30, function () use ($sessionId) {
            $transactions = CashRegisterTransaction::where('cash_register_session_id', $sessionId)->get();
            
            return [
                'cash_sales' => $transactions->where('type', 'cash_sale')->sum('amount'),
                'cash_in' => $transactions->where('type', 'cash_in')->sum('amount'),
                'cash_out' => $transactions->where('type', 'cash_out')->sum('amount'),
                'change_given' => $transactions->where('type', 'change_given')->sum('amount'),
                'safe_drop' => $transactions->where('type', 'safe_drop')->sum('amount'),
                'refund' => $transactions->where('type', 'refund')->sum('amount'),
            ];
        });
    }

    /**
     * Clear session totals cache
     * 
     * @param int $sessionId
     */
    public static function clearSessionTotalsCache(int $sessionId): void
    {
        Cache::forget("cashregister.session.totals.{$sessionId}");
    }

    /**
     * Clear all cash register caches for a branch
     * 
     * @param int $branchId
     */
    public static function clearBranchCache(int $branchId): void
    {
        Cache::forget("cashregister.denominations.branch.{$branchId}");
        
        // Clear session caches
        $sessions = CashRegisterSession::where('branch_id', $branchId)->pluck('id', 'opened_by');
        foreach ($sessions as $sessionId => $userId) {
            self::clearSessionCache($userId, $branchId);
            self::clearSessionTotalsCache($sessionId);
        }
    }

    /**
     * Clear all cash register caches
     */
    public static function clearAll(): void
    {
        // More selective than flush - only clear our caches
        // This would require tagging which Laravel Redis/file cache supports
        // For now, we'll clear specific patterns
        // Note: Full implementation would use cache tags if available
    }
}

