<?php

namespace Modules\Accounting\Controllers;

use core\Controller;
use core\Auth;
use core\Database;
use core\Security;

class ExpenseController extends Controller
{
    public function __construct()
    {
        parent::__construct();
    }

    public function index(): void
    {
        $this->requirePermission('accounting_expenses_view');

        $db = Database::getInstance();
        $categoryId = $this->request->get('category_id', '');
        $fromDate = $this->request->get('from_date', '');
        $toDate = $this->request->get('to_date', '');
        $page = max(1, (int)$this->request->get('page', 1));
        $perPage = PAGINATION_LIMIT;

        $query = $db->table('expenses e')
            ->select('e.*, ec.name as category_name')
            ->leftJoin('expense_categories ec', 'e.category_id', '=', 'ec.id');

        if (!empty($categoryId)) {
            $query->where('e.category_id', $categoryId);
        }

        if (!empty($fromDate)) {
            $query->where('e.date', '>=', $fromDate);
        }

        if (!empty($toDate)) {
            $query->where('e.date', '<=', $toDate);
        }

        $expenses = $query->orderBy('e.date', 'DESC')->orderBy('e.created_at', 'DESC')->paginate($perPage, $page);

        $categories = $db->table('expense_categories')
            ->orderBy('name', 'ASC')
            ->get();

        $this->view('Accounting/expenses/index', [
            'title' => 'Expenses',
            'breadcrumb' => ['Expenses' => url('expenses')],
            'expenses' => $expenses,
            'categories' => $categories,
            'categoryId' => $categoryId,
            'fromDate' => $fromDate,
            'toDate' => $toDate,
        ]);
    }

    public function create(): void
    {
        $this->requirePermission('accounting_expenses_create');

        $db = Database::getInstance();
        $categories = $db->table('expense_categories')
            ->orderBy('name', 'ASC')
            ->get();

        $this->view('Accounting/expenses/create', [
            'title' => 'Add Expense',
            'breadcrumb' => [
                'Expenses' => url('expenses'),
                'Add New' => url('expenses/create'),
            ],
            'categories' => $categories,
        ]);
    }

    public function store(): void
    {
        $this->requirePermission('accounting_expenses_create');

        $validated = $this->validate([
            'category_id' => 'required|integer',
            'amount' => 'required|numeric|min:0',
            'description' => 'required|max_length:500',
            'date' => 'required|date',
            'payment_method' => 'required|in:cash,card,bank_transfer,cheque',
            'reference_number' => 'max_length:100',
        ]);

        $validated['amount'] = (float)$validated['amount'];
        $validated['created_by'] = Auth::id();

        if ($this->request->hasFile('receipt')) {
            $file = $this->request->file('receipt');
            $path = uploadFile($file, 'receipts', ['jpg', 'jpeg', 'png', 'gif', 'webp', 'pdf']);
            if ($path) {
                $validated['receipt'] = $path;
            }
        }

        $expenseId = $db = Database::getInstance()->table('expenses')->insert($validated);
        $this->logActivity('create', 'Created expense: ' . $validated['description']);
        $this->logAudit('create', 'expenses', $expenseId, null, $validated);

        $this->redirectWith(url('expenses'), 'success', 'Expense created successfully.');
    }

    public function edit(int $id): void
    {
        $this->requirePermission('accounting_expenses_edit');

        $db = Database::getInstance();
        $expense = $db->table('expenses')->find($id);
        if (!$expense) {
            $this->redirectWith(url('expenses'), 'error', 'Expense not found.');
        }

        $categories = $db->table('expense_categories')
            ->orderBy('name', 'ASC')
            ->get();

        $this->view('Accounting/expenses/edit', [
            'title' => 'Edit Expense',
            'breadcrumb' => [
                'Expenses' => url('expenses'),
                'Edit' => url('expenses/edit/' . $id),
            ],
            'expense' => $expense,
            'categories' => $categories,
        ]);
    }

    public function update(int $id): void
    {
        $this->requirePermission('accounting_expenses_edit');

        $db = Database::getInstance();
        $expense = $db->table('expenses')->find($id);
        if (!$expense) {
            $this->redirectWith(url('expenses'), 'error', 'Expense not found.');
        }

        $oldValues = (array)$expense;

        $validated = $this->validate([
            'category_id' => 'required|integer',
            'amount' => 'required|numeric|min:0',
            'description' => 'required|max_length:500',
            'date' => 'required|date',
            'payment_method' => 'required|in:cash,card,bank_transfer,cheque',
            'reference_number' => 'max_length:100',
        ]);

        $validated['amount'] = (float)$validated['amount'];

        if ($this->request->hasFile('receipt')) {
            $file = $this->request->file('receipt');
            $path = uploadFile($file, 'receipts', ['jpg', 'jpeg', 'png', 'gif', 'webp', 'pdf']);
            if ($path) {
                if (!empty($expense->receipt)) {
                    deleteFile($expense->receipt);
                }
                $validated['receipt'] = $path;
            }
        }

        $db->table('expenses')->where('id', $id)->update($validated);
        $this->logActivity('update', 'Updated expense: ' . $validated['description']);
        $this->logAudit('update', 'expenses', $id, $oldValues, $validated);

        $this->redirectWith(url('expenses'), 'success', 'Expense updated successfully.');
    }

    public function delete(int $id): void
    {
        $this->requirePermission('accounting_expenses_delete');

        $db = Database::getInstance();
        $expense = $db->table('expenses')->find($id);
        if (!$expense) {
            $this->redirectWith(url('expenses'), 'error', 'Expense not found.');
        }

        $db->table('expenses')->where('id', $id)->delete();
        if (!empty($expense->receipt)) {
            deleteFile($expense->receipt);
        }

        $this->logActivity('delete', 'Deleted expense: ' . $expense->description);
        $this->logAudit('delete', 'expenses', $id, (array)$expense, null);

        $this->redirectWith(url('expenses'), 'success', 'Expense deleted successfully.');
    }
}
