<?php

/**
 * @var \Slim\App $app
 */

use ChurchCRM\Authentication\AuthenticationManager;
use ChurchCRM\Service\ExpenseService;
use ChurchCRM\Slim\Middleware\InputSanitizationMiddleware;
use ChurchCRM\Slim\Middleware\Request\Auth\FinanceRoleAuthMiddleware;
use ChurchCRM\Slim\SlimUtils;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Routing\RouteCollectorProxy;

$app->group('/expenses', function (RouteCollectorProxy $group): void {
    
    /**
     * @OA\Get(
     *     path="/expenses",
     *     summary="Get all expenses (Finance role required)",
     *     tags={"Finance"},
     *     security={{"ApiKeyAuth":{}}},
     *     @OA\Parameter(name="category", in="query", @OA\Schema(type="integer")),
     *     @OA\Parameter(name="status", in="query", @OA\Schema(type="string", enum={"Pending","Approved","Rejected","Paid"})),
     *     @OA\Parameter(name="fund", in="query", @OA\Schema(type="integer")),
     *     @OA\Parameter(name="start_date", in="query", @OA\Schema(type="string", format="date")),
     *     @OA\Parameter(name="end_date", in="query", @OA\Schema(type="string", format="date")),
     *     @OA\Response(response=200, description="Array of expenses"),
     *     @OA\Response(response=401, description="Unauthorized"),
     *     @OA\Response(response=403, description="Finance role required")
     * )
     */
    $group->get('', function (Request $request, Response $response): Response {
        $expenseService = new ExpenseService();
        $params = $request->getQueryParams();
        
        $filters = [
            'category' => $params['category'] ?? null,
            'status' => $params['status'] ?? null,
            'fund' => $params['fund'] ?? null,
            'start_date' => $params['start_date'] ?? null,
            'end_date' => $params['end_date'] ?? null
        ];
        
        $expenses = $expenseService->getExpenses(array_filter($filters));
        return SlimUtils::renderJSON($response, $expenses);
    })->add(new FinanceRoleAuthMiddleware());

    /**
     * @OA\Get(
     *     path="/expenses/categories",
     *     summary="Get all expense categories (Finance role required)",
     *     tags={"Finance"},
     *     security={{"ApiKeyAuth":{}}},
     *     @OA\Response(response=200, description="Array of categories")
     * )
     */
    $group->get('/categories', function (Request $request, Response $response): Response {
        $expenseService = new ExpenseService();
        $categories = $expenseService->getCategories();
        return SlimUtils::renderJSON($response, $categories);
    })->add(new FinanceRoleAuthMiddleware());

    /**
     * @OA\Get(
     *     path="/expenses/dashboard/summary",
     *     summary="Get dashboard summary (Finance role required)",
     *     tags={"Finance"},
     *     security={{"ApiKeyAuth":{}}},
     *     @OA\Parameter(name="start_date", in="query", @OA\Schema(type="string", format="date")),
     *     @OA\Parameter(name="end_date", in="query", @OA\Schema(type="string", format="date")),
     *     @OA\Response(response=200, description="Dashboard summary data")
     * )
     */
    $group->get('/dashboard/summary', function (Request $request, Response $response): Response {
        $expenseService = new ExpenseService();
        $params = $request->getQueryParams();
        
        $summary = $expenseService->getDashboardSummary(
            $params['start_date'] ?? null,
            $params['end_date'] ?? null
        );
        
        return SlimUtils::renderJSON($response, $summary);
    })->add(new FinanceRoleAuthMiddleware());

    /**
     * @OA\Get(
     *     path="/expenses/{id}",
     *     summary="Get a single expense (Finance role required)",
     *     tags={"Finance"},
     *     security={{"ApiKeyAuth":{}}},
     *     @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
     *     @OA\Response(response=200, description="Expense object"),
     *     @OA\Response(response=404, description="Expense not found")
     * )
     */
    $group->get('/{id}', function (Request $request, Response $response, array $args): Response {
        $expenseService = new ExpenseService();
        $expense = $expenseService->getExpenseById($args['id']);
        
        if (!$expense) {
            return SlimUtils::renderJSON($response, ['error' => 'Expense not found'], 404);
        }
        
        return SlimUtils::renderJSON($response, $expense);
    })->add(new FinanceRoleAuthMiddleware());

    /**
     * @OA\Post(
     *     path="/expenses",
     *     summary="Create a new expense (Finance role required)",
     *     tags={"Finance"},
     *     security={{"ApiKeyAuth":{}}},
     *     @OA\RequestBody(required=true,
     *         @OA\JsonContent(
     *             required={"date","amount","category"},
     *             @OA\Property(property="date", type="string", format="date"),
     *             @OA\Property(property="amount", type="number", format="decimal"),
     *             @OA\Property(property="category", type="integer"),
     *             @OA\Property(property="fund", type="integer"),
     *             @OA\Property(property="vendor", type="string"),
     *             @OA\Property(property="description", type="string"),
     *             @OA\Property(property="reference", type="string"),
     *             @OA\Property(property="payment_method", type="string", enum={"Check","Cash","Credit Card","Bank Transfer","Other"}),
     *             @OA\Property(property="notes", type="string")
     *         )
     *     ),
     *     @OA\Response(response=201, description="Expense created"),
     *     @OA\Response(response=400, description="Invalid input")
     * )
     */
    $group->post('', function (Request $request, Response $response): Response {
        $expenseService = new ExpenseService();
        $input = $request->getParsedBody();
        
        // Validate required fields
        if (empty($input['date']) || empty($input['amount']) || empty($input['category'])) {
            return SlimUtils::renderJSON($response, ['error' => 'Missing required fields'], 400);
        }
        
        $user = AuthenticationManager::getCurrentUser();
        if ($user === null) {
            return SlimUtils::renderJSON($response, ['error' => 'Unauthorized'], 401);
        }
        $input['entered_by'] = $user->getId();
        
        if ($expenseService->createExpense($input)) {
            return SlimUtils::renderJSON($response, ['success' => true, 'message' => 'Expense created'], 201);
        }
        
        return SlimUtils::renderJSON($response, ['error' => 'Failed to create expense'], 500);
    })->add(new InputSanitizationMiddleware(['description' => 'text', 'notes' => 'text']))
      ->add(new FinanceRoleAuthMiddleware());

    /**
     * @OA\Put(
     *     path="/expenses/{id}",
     *     summary="Update an expense (Finance role required)",
     *     tags={"Finance"},
     *     security={{"ApiKeyAuth":{}}},
     *     @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
     *     @OA\RequestBody(required=true, @OA\JsonContent())
     * )
     */
    $group->put('/{id}', function (Request $request, Response $response, array $args): Response {
        $expenseService = new ExpenseService();
        $input = $request->getParsedBody();
        
        $user = AuthenticationManager::getCurrentUser();
        if ($user === null) {
            return SlimUtils::renderJSON($response, ['error' => 'Unauthorized'], 401);
        }
        $input['updated_by'] = $user->getId();
        
        if ($expenseService->updateExpense($args['id'], $input)) {
            return SlimUtils::renderJSON($response, ['success' => true, 'message' => 'Expense updated']);
        }
        
        return SlimUtils::renderJSON($response, ['error' => 'Failed to update expense'], 500);
    })->add(new InputSanitizationMiddleware(['description' => 'text', 'notes' => 'text']))
      ->add(new FinanceRoleAuthMiddleware());

    /**
     * @OA\Delete(
     *     path="/expenses/{id}",
     *     summary="Delete an expense (Finance role required)",
     *     tags={"Finance"},
     *     security={{"ApiKeyAuth":{}}},
     *     @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"))
     * )
     */
    $group->delete('/{id}', function (Request $request, Response $response, array $args): Response {
        $expenseService = new ExpenseService();
        
        if ($expenseService->deleteExpense($args['id'])) {
            return SlimUtils::renderJSON($response, ['success' => true, 'message' => 'Expense deleted']);
        }
        
        return SlimUtils::renderJSON($response, ['error' => 'Failed to delete expense'], 500);
    })->add(new FinanceRoleAuthMiddleware());

    /**
     * Approve an expense
     */
    $group->post('/{id}/approve', function (Request $request, Response $response, array $args): Response {
        $expenseService = new ExpenseService();
        $input = $request->getParsedBody();
        
        $user = AuthenticationManager::getCurrentUser();
        if ($user === null) {
            return SlimUtils::renderJSON($response, ['error' => 'Unauthorized'], 401);
        }
        if ($expenseService->approveExpense($args['id'], $user->getId(), $input['notes'] ?? '')) {
            return SlimUtils::renderJSON($response, ['success' => true, 'message' => 'Expense approved']);
        }
        
        return SlimUtils::renderJSON($response, ['error' => 'Failed to approve expense'], 500);
    })->add(new FinanceRoleAuthMiddleware());

    /**
     * Reject an expense
     */
    $group->post('/{id}/reject', function (Request $request, Response $response, array $args): Response {
        $expenseService = new ExpenseService();
        $input = $request->getParsedBody();
        
        $user = AuthenticationManager::getCurrentUser();
        if ($user === null) {
            return SlimUtils::renderJSON($response, ['error' => 'Unauthorized'], 401);
        }
        if ($expenseService->rejectExpense($args['id'], $user->getId(), $input['notes'] ?? '')) {
            return SlimUtils::renderJSON($response, ['success' => true, 'message' => 'Expense rejected']);
        }
        
        return SlimUtils::renderJSON($response, ['error' => 'Failed to reject expense'], 500);
    })->add(new FinanceRoleAuthMiddleware());

    /**
     * Mark expense as paid
     */
    $group->post('/{id}/pay', function (Request $request, Response $response, array $args): Response {
        $expenseService = new ExpenseService();
        $input = $request->getParsedBody();
        
        $user = AuthenticationManager::getCurrentUser();
        if ($user === null) {
            return SlimUtils::renderJSON($response, ['error' => 'Unauthorized'], 401);
        }
        if ($expenseService->markAsPaid($args['id'], $user->getId(), $input['notes'] ?? '')) {
            return SlimUtils::renderJSON($response, ['success' => true, 'message' => 'Expense marked as paid']);
        }
        
        return SlimUtils::renderJSON($response, ['error' => 'Failed to mark expense as paid'], 500);
    })->add(new FinanceRoleAuthMiddleware());

})->add(new FinanceRoleAuthMiddleware());
