<?php
/**
 * Cash-Up Controller
 * 
 * Handles end-of-day cash reconciliation processes
 * 
 * LOCATION: /var/www/html/barber/app/controllers/CashUpController.php
 * 
 * FEATURES:
 * - View cash-up history
 * - Create new cash-up session
 * - Count cash by denominations
 * - Calculate variances
 * - Manager verification/approval
 * - Print cash-up reports
 * - Void cash-up (admin only)
 * 
 * USER ROLES:
 * - Cashier: Can initiate and complete cash-up
 * - Admin/SuperUser: Can verify, approve, void cash-ups
 */

class CashUpController extends Controller {
    
    private $cashUpModel;
    private $transactionModel;
    
    public function __construct() {
        parent::__construct();
        $this->cashUpModel = $this->model('CashUp');
        $this->transactionModel = $this->model('Transaction');
    }
    
    /**
     * List all cash-up sessions
     * Shows history of all cash-ups for the location
     */
    public function index() {
        $this->requireLogin();
        
        $user = $this->getCurrentUser();
        $locationId = $user['location_id'];
        
        // Admin/SuperUser can see all locations
	if (in_array($_SESSION['role'] ?? '', ['admin', 'superuser'])) {
	    $locationId = $_GET['location_id'] ?? $locationId;
        }
        
        // Get date range from URL or default to last 30 days
        $dateFrom = $_GET['date_from'] ?? date('Y-m-d', strtotime('-30 days'));
        $dateTo = $_GET['date_to'] ?? date('Y-m-d');
        
        // Get cash-up history
        $cashUps = $this->cashUpModel->getCashUpHistory($locationId, $dateFrom, $dateTo);
        
        // Get all locations for filter (admin only)
        $locations = [];
	if (in_array($_SESSION['role'] ?? '', ['admin', 'superuser'])) {
	    $locationModel = $this->model('Location');
            $locations = $locationModel->getAllLocations();
        }
        
        $data = [
            'title' => 'Cash-Up History',
            'cashUps' => $cashUps,
            'locations' => $locations,
            'selectedLocation' => $locationId,
            'dateFrom' => $dateFrom,
            'dateTo' => $dateTo,
            'user' => $user
        ];
        
        $this->view('cashup/index', $data);
    }
    
    /**
     * Check if cash-up is needed for today
     * Called from dashboard or can be accessed directly
     */
    public function checkRequired() {
        $this->requireLogin();
        $this->requireRole(['cashier', 'admin', 'superuser']);
        
        $user = $this->getCurrentUser();
        $locationId = $user['location_id'];
        $today = date('Y-m-d');
        
        // Check if cash-up already exists for today
        $existingCashUp = $this->cashUpModel->getCashUpByDate($locationId, $today);
        
        if ($existingCashUp) {
            echo json_encode([
                'required' => false,
                'status' => $existingCashUp['status'],
                'message' => 'Cash-up already completed for today'
            ]);
        } else {
            // Check if there are any transactions today
            $dailyTotals = $this->transactionModel->getDailyTotals($locationId, $today);
            
            echo json_encode([
                'required' => true,
                'transaction_count' => $dailyTotals['transaction_count'] ?? 0,
                'total_sales' => $dailyTotals['total_sales'] ?? 0,
                'message' => 'Cash-up required for today'
            ]);
        }
    }
    
    /**
     * Show create cash-up form
     * Step 1: Display expected totals
     * Step 2: Count cash denominations
     * Step 3: Calculate variance
     * Step 4: Submit for verification
     */
    public function create() {
        $this->requireLogin();
        $this->requireRole(['cashier', 'admin', 'superuser']);
        
        $user = $this->getCurrentUser();
        $locationId = $user['location_id'];
	$today = date('Y-m-d');
	error_log("Cash-Up Create - Today's date: $today");
	error_log("Cash-Up Create - Location ID: $locationId");
        
        // Check if cash-up already exists
        $existingCashUp = $this->cashUpModel->getCashUpByDate($locationId, $today);
        
        if ($existingCashUp && $existingCashUp['status'] !== 'void') {
            $this->setFlash('Cash-up already exists for today', 'warning');
            $this->redirect('cashup/viewDetails/' . $existingCashUp['id']);
            return;
        }
        
        // Get daily totals from transactions
        $dailyTotals = $this->transactionModel->getDailyTotals($locationId, $today);
	
	error_log("Daily Totals: " . print_r($dailyTotals, true));

        if (!$dailyTotals || $dailyTotals['transaction_count'] == 0) {
            $this->setFlash('No transactions found for today. Cash-up not needed.', 'info');
            $this->redirect('dashboard');
            return;
        }
        
        // Get payment method breakdown
        $paymentBreakdown = $this->transactionModel->getPaymentBreakdown($locationId, $today);
        
        // Get previous cash-up closing balance
        $previousCashUp = $this->cashUpModel->getLatestCashUp($locationId);
        $openingBalance = $previousCashUp ? $previousCashUp['actual_cash'] : 0;
        
        // Load business settings
        require_once __DIR__ . '/../helpers/settings_loader.php';
        $BUSINESS = loadBusinessSettings();
        
        $data = [
            'title' => 'End of Day Cash-Up',
            'locationId' => $locationId,
            'businessDate' => $today,
            'dailyTotals' => $dailyTotals,
            'paymentBreakdown' => $paymentBreakdown,
            'openingBalance' => $openingBalance,
            'expectedCash' => $openingBalance + ($paymentBreakdown['cash'] ?? 0),
            'varianceThreshold' => $BUSINESS['cashup_variance_threshold'] ?? 50,
            'user' => $user,
            'csrfToken' => $this->generateCsrfToken()
        ];
        
        $this->view('cashup/create', $data);
    }
    
    /**
     * Save cash-up session
     * Processes the submitted cash-up data
     */
    public function save() {
        $this->requireLogin();
        $this->requireRole(['cashier', 'admin', 'superuser']);
        
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            $this->redirect('cashup/create');
            return;
        }
        
        // Validate CSRF token
        if (!$this->validateCSRF($_POST['csrf_token'] ?? '')) {
            $this->setFlash('Invalid security token', 'error');
            $this->redirect('cashup/create');
            return;
        }
        
        $user = $this->getCurrentUser();
        $locationId = $user['location_id'];
        
        // Get form data
        $businessDate = $_POST['business_date'] ?? date('Y-m-d');
        $actualCash = floatval($_POST['actual_cash'] ?? 0);
        $actualCard = floatval($_POST['actual_card'] ?? 0);
        $actualMobile = floatval($_POST['actual_mobile'] ?? 0);
        $varianceReason = trim($_POST['variance_reason'] ?? '');
        $notes = trim($_POST['notes'] ?? '');
        
        // Get denominations
        $denominations = [];
        $denominationValues = [200, 100, 50, 20, 10, 5, 2, 1, 0.50, 0.20, 0.10, 0.05];
        
        foreach ($denominationValues as $denom) {
            $key = 'denom_' . str_replace('.', '_', $denom);
            $count = intval($_POST[$key] ?? 0);
            
            if ($count > 0) {
                $denominations[] = [
                    'denomination' => $denom,
                    'count' => $count,
                    'total_value' => $denom * $count
                ];
            }
        }
        
        // Calculate totals from denominations
        $denominationTotal = array_sum(array_column($denominations, 'total_value'));
        
        // Verify denomination total matches entered cash
        if (abs($denominationTotal - $actualCash) > 0.01) {
            $this->setFlash('Cash denominations total (' . formatCurrency($denominationTotal) . 
                          ') does not match entered cash amount (' . formatCurrency($actualCash) . ')', 'error');
            $this->redirect('cashup/create');
            return;
        }
        
        // Get expected totals from transactions
        $dailyTotals = $this->transactionModel->getDailyTotals($locationId, $businessDate);
        $paymentBreakdown = $this->transactionModel->getPaymentBreakdown($locationId, $businessDate);
        
        // Get opening balance
        $previousCashUp = $this->cashUpModel->getLatestCashUp($locationId, $businessDate);
        $openingBalance = $previousCashUp ? $previousCashUp['actual_cash'] : 0;
        
        // Calculate expected amounts
        $expectedCash = $openingBalance + ($paymentBreakdown['cash'] ?? 0);
        $expectedCard = $paymentBreakdown['card'] ?? 0;
        $expectedMobile = $paymentBreakdown['mobile_payment'] ?? 0;
        $expectedTotal = $dailyTotals['total_sales'] ?? 0;
        
        // Calculate variances
        $cashVariance = $actualCash - $expectedCash;
        $cardVariance = $actualCard - $expectedCard;
        $mobileVariance = $actualMobile - $expectedMobile;
        $actualTotal = $actualCash + $actualCard + $actualMobile;
        $totalVariance = $actualTotal - $expectedTotal;
        
        // Prepare cash-up data
        $cashUpData = [
            'location_id' => $locationId,
            'cashier_id' => $user['user_id'],
            'business_date' => $businessDate,
            'opening_balance' => $openingBalance,
            'expected_cash' => $expectedCash,
            'expected_card' => $expectedCard,
            'expected_mobile' => $expectedMobile,
            'expected_total' => $expectedTotal,
            'actual_cash' => $actualCash,
            'actual_card' => $actualCard,
            'actual_mobile' => $actualMobile,
            'actual_total' => $actualTotal,
            'cash_variance' => $cashVariance,
            'card_variance' => $cardVariance,
            'mobile_variance' => $mobileVariance,
            'total_variance' => $totalVariance,
            'variance_reason' => $varianceReason,
            'transaction_count' => $dailyTotals['transaction_count'] ?? 0,
            'cash_transaction_count' => $dailyTotals['cash_count'] ?? 0,
            'card_transaction_count' => $dailyTotals['card_count'] ?? 0,
            'mobile_transaction_count' => $dailyTotals['mobile_count'] ?? 0,
            'notes' => $notes,
            'status' => 'pending',
            'created_by' => $user['user_id']
        ];
        
        // Create cash-up session
        $cashUpId = $this->cashUpModel->createCashUp($cashUpData);
        
        if ($cashUpId) {
            // Save denominations
            if (!empty($denominations)) {
                foreach ($denominations as $denom) {
                    $denom['cash_up_id'] = $cashUpId;
                    $this->cashUpModel->saveDenomination($denom);
                }
            }
            
            // Log audit trail
            $this->logAudit('cash_up_created', 'cash_up_sessions', $cashUpId, null, $cashUpData);
            
            $this->setFlash('Cash-up completed successfully', 'success');
            $this->redirect('cashup/viewDetails/' . $cashUpId);
        } else {
            $this->setFlash('Failed to save cash-up. Please try again.', 'error');
            $this->redirect('cashup/create');
        }
    }
    
    /**
     * View cash-up details
     * Shows complete cash-up report
     */
    public function viewDetails($cashUpId) {
        $this->requireLogin();
        
        $cashUp = $this->cashUpModel->getCashUpById($cashUpId);
        
        if (!$cashUp) {
            $this->setFlash('Cash-up not found', 'error');
            $this->redirect('cashup');
            return;
        }
        
        $user = $this->getCurrentUser();

        // Check permissions: Can only view own location unless admin
        if (($_SESSION['role'] ?? '') === 'cashier' && $cashUp['location_id'] != $user['location_id']) {
            $this->setFlash('Access denied', 'error');
            $this->redirect('cashup');
            return;
        }
        
        // Get denominations
        $denominations = $this->cashUpModel->getDenominations($cashUpId);
        
        // Get location details
        $locationModel = $this->model('Location');
        $location = $locationModel->getLocationById($cashUp['location_id']);
        
        // Load business settings
        require_once __DIR__ . '/../helpers/settings_loader.php';
        $BUSINESS = loadBusinessSettings();
        
        $data = [
            'title' => 'Cash-Up Details',
            'cashUp' => $cashUp,
            'denominations' => $denominations,
            'location' => $location,
            'user' => $user,
	    'canVerify' => (($_SESSION['role_name'] ?? '') === 'admin' || ($_SESSION['role_name'] ?? '') === 'superuser') &&
              $cashUp['status'] === 'pending',
	     'canVoid' => ($_SESSION['role_name'] ?? '') === 'admin', 
	     'csrfToken' => $this->generateCsrfToken(),
            'BUSINESS' => $BUSINESS
        ];
        
        $this->view('cashup/view', $data);
    }
    
    /**
     * Verify cash-up (Manager/Admin approval)
     * Changes status from pending to verified/completed
     */
    public function verify($cashUpId) {
        $this->requireLogin();
        $this->requireRole(['admin', 'superuser']);
        
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            $this->redirect('cashup/viewDetails/' . $cashUpId);
            return;
        }
        
        if (!$this->validateCSRF($_POST['csrf_token'] ?? '')) {
            $this->setFlash('Invalid security token', 'error');
            $this->redirect('cashup/viewDetails/' . $cashUpId);
            return;
        }
        
        $user = $this->getCurrentUser();
        $notes = trim($_POST['verification_notes'] ?? '');
        
        $result = $this->cashUpModel->verifyCashUp($cashUpId, $user['user_id'], $notes);
        
        if ($result) {
            // Log audit trail
            $this->logAudit('cash_up_verified', 'cash_up_sessions', $cashUpId, 
                          ['status' => 'pending'], ['status' => 'verified']);
            
            $this->setFlash('Cash-up verified successfully', 'success');
        } else {
            $this->setFlash('Failed to verify cash-up', 'error');
        }
        
        $this->redirect('cashup/viewDetails/' . $cashUpId);
    }
    
    /**
     * Void cash-up (Admin only)
     * Marks cash-up as void and allows re-doing
     */
    public function void($cashUpId) {
        $this->requireLogin();
        $this->requireRole('admin');
        
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            $this->redirect('cashup/viewDetails/' . $cashUpId);
            return;
        }
        
        if (!$this->validateCSRF($_POST['csrf_token'] ?? '')) {
            $this->setFlash('Invalid security token', 'error');
            $this->redirect('cashup/viewDetails/' . $cashUpId);
            return;
        }
        
        $reason = trim($_POST['void_reason'] ?? '');
        
        if (empty($reason)) {
            $this->setFlash('Void reason is required', 'error');
            $this->redirect('cashup/viewDetails/' . $cashUpId);
            return;
        }
        
        $user = $this->getCurrentUser();
        
        $result = $this->cashUpModel->voidCashUp($cashUpId, $user['user_id'], $reason);
        
        if ($result) {
            // Log audit trail
            $this->logAudit('cash_up_voided', 'cash_up_sessions', $cashUpId, 
                          null, ['reason' => $reason]);
            
            $this->setFlash('Cash-up voided successfully', 'success');
            $this->redirect('cashup');
        } else {
            $this->setFlash('Failed to void cash-up', 'error');
            $this->redirect('cashup/viewDetails/' . $cashUpId);
        }
    }
    
    /**
     * Print cash-up report
     * Generates printable HTML report
     */
    public function print($cashUpId) {
        $this->requireLogin();
        
        $cashUp = $this->cashUpModel->getCashUpById($cashUpId);
        
        if (!$cashUp) {
            $this->setFlash('Cash-up not found', 'error');
            $this->redirect('cashup');
            return;
        }
        
        $user = $this->getCurrentUser();
        
        // Check permissions
        if (($_SESSION['role'] ?? '') === 'cashier' && $cashUp['location_id'] != $user['location_id']) {
            $this->setFlash('Access denied', 'error');
            $this->redirect('cashup');
            return;
        }
        
        // Get data
        $denominations = $this->cashUpModel->getDenominations($cashUpId);
        $locationModel = $this->model('Location');
        $location = $locationModel->getLocationById($cashUp['location_id']);
        
        // Load settings
        require_once __DIR__ . '/../helpers/settings_loader.php';
        $BUSINESS = loadBusinessSettings();
        
        $data = [
            'title' => 'Cash-Up Report - ' . $cashUp['business_date'],
            'cashUp' => $cashUp,
            'denominations' => $denominations,
            'location' => $location,
            'BUSINESS' => $BUSINESS,
            'printMode' => true
        ];
        
        // Load print view (simplified layout)
        $this->view('cashup/print', $data);
    }
    
    /**
     * Log audit trail for cash-up actions
     */
    protected function logAudit($action, $tableName = null, $recordId = null, $oldValues = null, $newValues = null) {
        require_once __DIR__ . '/../core/Database.php';
        $db = Database::getInstance()->getConnection();
        
        $userId = $_SESSION['user_id'] ?? null;
        $ipAddress = $_SERVER['REMOTE_ADDR'] ?? '';
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        
        $query = "INSERT INTO audit_log (user_id, action, table_name, record_id, old_values, new_values, ip_address, user_agent) 
                 VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
        
        $stmt = $db->prepare($query);
        $stmt->execute([
            $userId,
            $action,
            $tableName,
            $recordId,
            $oldValues ? json_encode($oldValues) : null,
            $newValues ? json_encode($newValues) : null,
            $ipAddress,
            $userAgent
        ]);
    }
}
