<?php

class Expense {
    public static function all($startDate = null, $endDate = null) {
        $db = Database::getInstance();

        $sql = "SELECT e.*, u.username as created_by_name
                FROM expenses e
                LEFT JOIN users u ON e.created_by = u.id";

        $params = [];

        if ($startDate && $endDate) {
            $sql .= " WHERE expense_date BETWEEN ? AND ?";
            $params[] = $startDate;
            $params[] = $endDate;
        }

        $sql .= " ORDER BY expense_date DESC";

        return $db->fetchAll($sql, $params);
    }

    public static function findById($id) {
        $db = Database::getInstance();
        return $db->fetchOne(
            "SELECT * FROM expenses WHERE id = ?",
            [$id]
        );
    }

    public static function create($data, $userId) {
        $db = Database::getInstance();

        $db->execute(
            "INSERT INTO expenses (description, amount, expense_date, category, receipt_path, notes, created_by)
             VALUES (?, ?, ?, ?, ?, ?, ?)",
            [
                $data['description'],
                $data['amount'],
                $data['expense_date'],
                $data['category'] ?? null,
                $data['receipt_path'] ?? null,
                $data['notes'] ?? null,
                $userId
            ]
        );

        return $db->lastInsertId();
    }

    public static function update($id, $data) {
        $db = Database::getInstance();

        $db->execute(
            "UPDATE expenses SET description = ?, amount = ?, expense_date = ?, category = ?, receipt_path = ?, notes = ? WHERE id = ?",
            [
                $data['description'],
                $data['amount'],
                $data['expense_date'],
                $data['category'] ?? null,
                $data['receipt_path'] ?? null,
                $data['notes'] ?? null,
                $id
            ]
        );

        return $id;
    }

    public static function save($data, $userId, $receiptFile = null, $allocations = []) {
        $db = Database::getInstance();
        $isUpdate = isset($data['id']) && !empty($data['id']);
        $expenseId = $data['id'] ?? null;

        // Handle receipt upload
        $receipt_path = $data['receipt_path'] ?? null; // Keep existing path if not new file
        if ($receiptFile && $receiptFile['error'] === UPLOAD_ERR_OK) {
            $uploadDir = __DIR__ . '/../uploads/expenses/';
            if (!is_dir($uploadDir)) {
                mkdir($uploadDir, 0777, true);
            }
            $filename = uniqid('receipt_') . '_' . basename($receiptFile['name']);
            $targetPath = $uploadDir . $filename;
            if (move_uploaded_file($receiptFile['tmp_name'], $targetPath)) {
                $receipt_path = '/uploads/expenses/' . $filename;
            } else {
                // Handle upload error, maybe return false or throw exception
                error_log("Failed to move uploaded file: " . $receiptFile['tmp_name'] . " to " . $targetPath);
                return false;
            }
        } elseif ($isUpdate && empty($data['existing_receipt'])) {
            // If it's an update and no new file, and existing_receipt is empty, clear the path
            $receipt_path = null;
        }

        $data['receipt_path'] = $receipt_path;

        if ($isUpdate) {
            self::update($expenseId, $data);
        } else {
            $expenseId = self::create($data, $userId);
        }

        // Save allocations
        if ($expenseId && !empty($allocations)) {
            self::saveAllocations($expenseId, $allocations);
        } else if ($expenseId && $isUpdate) {
             // If update and no allocations, clear existing ones
            $db->execute("DELETE FROM expense_concept_allocations WHERE expense_id = ?", [$expenseId]);
        }

        return $expenseId;
    }

    public static function saveAllocations($expenseId, $allocations) {
        $db = Database::getInstance();
        // Delete existing allocations for this expense
        $db->execute("DELETE FROM expense_concept_allocations WHERE expense_id = ?", [$expenseId]);

        foreach ($allocations as $allocation) {
            $db->execute(
                "INSERT INTO expense_concept_allocations (expense_id, concept_id, amount)
                 VALUES (?, ?, ?)",
                [$expenseId, $allocation['concept_id'], $allocation['amount']]
            );
        }
    }

    public static function delete($id) {
        $db = Database::getInstance();
        // Optionally delete associated receipt file
        $expense = self::findById($id);
        if ($expense && $expense['receipt_path']) {
            $filePath = __DIR__ . '/..' . $expense['receipt_path'];
            if (file_exists($filePath)) {
                unlink($filePath);
            }
        }
        // Delete allocations first
        $db->execute("DELETE FROM expense_concept_allocations WHERE expense_id = ?", [$id]);
        return $db->execute(
            "DELETE FROM expenses WHERE id = ?",
            [$id]
        );
    }

    public static function getTotalByDateRange($startDate, $endDate) {
        $db = Database::getInstance();
        $result = $db->fetchOne(
            "SELECT COALESCE(SUM(amount), 0) as total
             FROM expenses
             WHERE expense_date BETWEEN ? AND ?",
            [$startDate, $endDate]
        );
        return $result['total'] ?? 0;
    }

    public static function getTotalByCategory($category, $startDate = null, $endDate = null) {
        $db = Database::getInstance();

        $sql = "SELECT COALESCE(SUM(amount), 0) as total
                FROM expenses
                WHERE category = ?";
        $params = [$category];

        if ($startDate && $endDate) {
            $sql .= " AND expense_date BETWEEN ? AND ?";
            $params[] = $startDate;
            $params[] = $endDate;
        }

        $result = $db->fetchOne($sql, $params);
        return $result['total'] ?? 0;
    }

    public static function getConcepts($expenseId) {
        $db = Database::getInstance();
        return $db->fetchAll(
            "SELECT ec.*, c.name as concept_name
             FROM expense_concept_allocations ec
             JOIN finance_collection_concepts c ON ec.concept_id = c.id
             WHERE ec.expense_id = ?",
            [$expenseId]
        );
    }

    public static function getTotalByConcept($conceptId) {
        $db = Database::getInstance();
        $result = $db->fetchOne(
            "SELECT COALESCE(SUM(amount), 0) as total
             FROM expense_concept_allocations
             WHERE concept_id = ?",
            [$conceptId]
        );
        return $result['total'] ?? 0;
    }
}
