<?php
/**
 * Expense Controller for Zen Zone Spa API
 * Handles all expense operations
 */

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../utils/Response.php';

class ExpenseController {
    
    private $db;
    
    public function __construct() {
        $this->db = DatabaseConfig::getConnection();
    }
    
    /**
     * Get all expenses with optional filtering
     */
    public function getAllExpenses() {
        try {
            $startDate = $_GET['start_date'] ?? null;
            $endDate = $_GET['end_date'] ?? null;
            $categoryId = $_GET['category_id'] ?? null;
            
            $sql = "SELECT 
                        e.id,
                        e.description,
                        CAST(e.amount AS DECIMAL(10,2)) as amount,
                        e.expense_date as date,
                        e.expense_date,
                        e.payment_method,
                        e.receipt_number,
                        e.notes,
                        e.is_recurring,
                        e.created_at,
                        ec.name as category_name,
                        ec.name as category,
                        ec.color as category_color,
                        u.username as created_by_user
                    FROM expenses e
                    LEFT JOIN expense_categories ec ON e.category_id = ec.id
                    LEFT JOIN users u ON e.created_by = u.id
                    WHERE 1=1";
            
            $params = [];
            
            if ($startDate) {
                $sql .= " AND e.expense_date >= :start_date";
                $params['start_date'] = $startDate;
            }
            
            if ($endDate) {
                $sql .= " AND e.expense_date <= :end_date";
                $params['end_date'] = $endDate;
            }
            
            if ($categoryId) {
                $sql .= " AND e.category_id = :category_id";
                $params['category_id'] = $categoryId;
            }
            
            $sql .= " ORDER BY e.expense_date DESC, e.created_at DESC";
            
            $stmt = $this->db->prepare($sql);
            $stmt->execute($params);
            $expenses = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // Ensure numeric values are properly typed
            foreach ($expenses as &$expense) {
                $expense['amount'] = (float)$expense['amount'];
                $expense['id'] = (string)$expense['id'];
            }
            
            // Calculate totals
            $totalAmount = array_sum(array_column($expenses, 'amount'));
            
            Response::success([
                'expenses' => $expenses,
                'count' => count($expenses),
                'total_amount' => $totalAmount
            ], 'Expenses retrieved successfully');
            
        } catch (Exception $e) {
            error_log("Get expenses error: " . $e->getMessage());
            Response::serverError('Failed to fetch expenses');
        }
    }
    
    /**
     * Get a specific expense by ID
     */
    public function getExpense($id) {
        try {
            $sql = "SELECT 
                        e.*,
                        ec.name as category_name,
                        ec.description as category_description,
                        ec.color as category_color,
                        u.username as created_by_user,
                        u.name as created_by_name
                    FROM expenses e
                    LEFT JOIN expense_categories ec ON e.category_id = ec.id
                    LEFT JOIN users u ON e.created_by = u.id
                    WHERE e.id = ?";
            
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$id]);
            $expense = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$expense) {
                Response::notFound('Expense not found');
            }
            
            // Ensure numeric values are properly typed
            $expense['amount'] = (float)$expense['amount'];
            $expense['id'] = (string)$expense['id'];
            
            Response::success($expense, 'Expense retrieved successfully');
            
        } catch (Exception $e) {
            error_log("Get expense error: " . $e->getMessage());
            Response::serverError('Failed to fetch expense');
        }
    }
    
    /**
     * Create a new expense
     */
    public function createExpense($input) {
        try {
            // Validate required fields
            $errors = Response::validateRequired($input, [
                'category_id', 'description', 'amount', 'expense_date'
            ]);
            if ($errors) {
                Response::validationError($errors);
            }
            
            $sql = "INSERT INTO expenses (
                        category_id, description, amount, expense_date,
                        payment_method, receipt_number, notes, is_recurring,
                        created_by
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
            
            $params = [
                $input['category_id'],
                $input['description'],
                $input['amount'],
                $input['expense_date'],
                $input['payment_method'] ?? 'cash',
                $input['receipt_number'] ?? null,
                $input['notes'] ?? null,
                isset($input['is_recurring']) ? ($input['is_recurring'] ? 1 : 0) : 0,
                1 // Default user ID - should get from JWT token
            ];
            
            $stmt = $this->db->prepare($sql);
            $result = $stmt->execute($params);
            
            if ($result) {
                $expenseId = $this->db->lastInsertId();
                $this->getExpense($expenseId);
            } else {
                $errorInfo = $stmt->errorInfo();
                Response::error('Failed to create expense - SQL Error: ' . $errorInfo[2], 500);
            }
            
        } catch (Exception $e) {
            error_log("Create expense error: " . $e->getMessage());
            Response::serverError('Failed to create expense');
        }
    }
    
    /**
     * Update an existing expense
     */
    public function updateExpense($id, $input) {
        try {
            // Check if expense exists
            $stmt = $this->db->prepare("SELECT id FROM expenses WHERE id = ?");
            $stmt->execute([$id]);
            if (!$stmt->fetch()) {
                Response::notFound('Expense not found');
            }
            
            // Build update query dynamically
            $updateFields = [];
            $params = [];
            
            $allowedFields = [
                'category_id', 'description', 'amount', 'expense_date',
                'payment_method', 'receipt_number', 'notes', 'is_recurring'
            ];
            
            foreach ($allowedFields as $field) {
                if (isset($input[$field])) {
                    $updateFields[] = "$field = ?";
                    $params[] = $input[$field];
                }
            }
            
            if (empty($updateFields)) {
                Response::error('No valid fields to update', 400);
            }
            
            $params[] = $id; // Add ID for WHERE clause
            $sql = "UPDATE expenses SET " . implode(', ', $updateFields) . " WHERE id = ?";
            
            $stmt = $this->db->prepare($sql);
            $result = $stmt->execute($params);
            
            if ($result) {
                $this->getExpense($id);
            } else {
                Response::serverError('Failed to update expense');
            }
            
        } catch (Exception $e) {
            error_log("Update expense error: " . $e->getMessage());
            Response::serverError('Failed to update expense');
        }
    }
    
    /**
     * Delete an expense
     */
    public function deleteExpense($id) {
        try {
            // Check if expense exists
            $stmt = $this->db->prepare("SELECT id FROM expenses WHERE id = ?");
            $stmt->execute([$id]);
            if (!$stmt->fetch()) {
                Response::notFound('Expense not found');
            }
            
            // Delete the expense
            $stmt = $this->db->prepare("DELETE FROM expenses WHERE id = ?");
            $result = $stmt->execute([$id]);
            
            if ($result) {
                Response::success(null, 'Expense deleted successfully');
            } else {
                Response::serverError('Failed to delete expense');
            }
            
        } catch (Exception $e) {
            error_log("Delete expense error: " . $e->getMessage());
            Response::serverError('Failed to delete expense');
        }
    }
    
    /**
     * Get expense categories
     */
    public function getExpenseCategories() {
        try {
            $sql = "SELECT id, name, description, color, is_active 
                    FROM expense_categories 
                    WHERE is_active = 1 
                    ORDER BY name ASC";
            
            $stmt = $this->db->prepare($sql);
            $stmt->execute();
            $categories = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            Response::success($categories, 'Expense categories retrieved successfully');
            
        } catch (Exception $e) {
            error_log("Get expense categories error: " . $e->getMessage());
            Response::serverError('Failed to fetch expense categories');
        }
    }
    
    /**
     * Get expense statistics
     */
    public function getExpenseStats() {
        try {
            // Get total expenses for current month
            $currentMonth = date('Y-m');
            $previousMonth = date('Y-m', strtotime('-1 month'));
            
            $sql = "SELECT 
                        COUNT(*) as total_expenses,
                        SUM(amount) as total_amount,
                        AVG(amount) as average_amount,
                        (SELECT COUNT(*) FROM expenses WHERE DATE_FORMAT(expense_date, '%Y-%m') = ?) as current_month_count,
                        (SELECT SUM(amount) FROM expenses WHERE DATE_FORMAT(expense_date, '%Y-%m') = ?) as current_month_total,
                        (SELECT COUNT(*) FROM expenses WHERE DATE_FORMAT(expense_date, '%Y-%m') = ?) as previous_month_count,
                        (SELECT SUM(amount) FROM expenses WHERE DATE_FORMAT(expense_date, '%Y-%m') = ?) as previous_month_total
                    FROM expenses";
            
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$currentMonth, $currentMonth, $previousMonth, $previousMonth]);
            $stats = $stmt->fetch(PDO::FETCH_ASSOC);
            
            // Calculate month-over-month growth
            $monthGrowth = 0;
            if ($stats['previous_month_total'] > 0) {
                $monthGrowth = (($stats['current_month_total'] - $stats['previous_month_total']) / $stats['previous_month_total']) * 100;
            }
            
            $stats['month_over_month_growth'] = round($monthGrowth, 2);
            
            Response::success($stats, 'Expense statistics retrieved successfully');
            
        } catch (Exception $e) {
            error_log("Get expense stats error: " . $e->getMessage());
            Response::serverError('Failed to fetch expense statistics');
        }
    }
} 