<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Expense;
use App\Notifications\ExpenseReviewedNotification;
use App\Notifications\ExpenseSubmittedNotification;
use App\Services\Finance\ExpenseScopeService;
use App\Services\Finance\FinanceNavService;
use App\Services\HrmsNotificationService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;

class ExpenseController extends Controller
{
    public function index(Request $request, ExpenseScopeService $scopes): JsonResponse
    {
        $this->authorize('viewAny', Expense::class);

        $user = Auth::user();
        $scope = $scopes->resolveScope($user, $request->input('scope'));
        $query = Expense::with(['account', 'claimant'])->orderByDesc('date');

        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        $scopes->applyScope($query, $user, $scope);

        return response()->json($query->paginate($request->integer('per_page', 15)));
    }

    public function store(Request $request, HrmsNotificationService $notifier, FinanceNavService $nav): JsonResponse
    {
        $this->authorize('create', Expense::class);

        $user = Auth::user();
        $showTreasuryFields = $nav->canUseTreasuryMasters($user);

        $rules = [
            'vendor_id' => 'nullable|exists:vendors,id',
            'category' => 'required|string|max:191',
            'amount' => 'required|numeric|min:0',
            'date' => 'required|date',
            'description' => 'nullable|string|max:1000',
        ];

        if ($showTreasuryFields) {
            $rules['account_id'] = 'nullable|exists:accounts,id';
        }

        $validated = $request->validate($rules);

        $expense = Expense::create([
            'company_id' => $user->company_id,
            'user_id' => $user->id,
            'submitted_by' => $user->id,
            'account_id' => $showTreasuryFields ? ($validated['account_id'] ?? null) : null,
            'vendor_id' => $showTreasuryFields ? ($validated['vendor_id'] ?? null) : null,
            'category' => $validated['category'],
            'amount' => $validated['amount'],
            'date' => $validated['date'],
            'description' => $validated['description'] ?? null,
            'status' => 'pending',
        ]);

        $expense->load('claimant');
        $notifier->notifyExpenseApprovers(
            (int) $user->company_id,
            new ExpenseSubmittedNotification($expense),
            [(int) $user->id]
        );

        return response()->json($expense->load(['account', 'claimant']), 201);
    }

    public function show(Expense $expense): JsonResponse
    {
        $this->authorize('view', $expense);

        return response()->json($expense->load(['account', 'claimant']));
    }

    public function updateStatus(Request $request, Expense $expense): JsonResponse
    {
        $this->authorize('review', $expense);

        $validated = $request->validate([
            'status' => ['required', Rule::in(['approved', 'rejected', 'paid'])],
            'review_remarks' => 'nullable|string|max:1000',
        ]);

        $previousStatus = $expense->status;
        $expense->update([
            'status' => $validated['status'],
            'review_remarks' => $validated['review_remarks'] ?? null,
            'reviewed_by' => Auth::id(),
            'reviewed_at' => now(),
        ]);

        $expense->load('claimant');
        if ($previousStatus !== $expense->status) {
            $expense->claimant?->notify(new ExpenseReviewedNotification($expense, $expense->status));
        }

        return response()->json($expense->load(['account', 'claimant']));
    }
}
