<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Expense;
use App\Models\PrePayment;
use App\Models\User;
use App\Services\Finance\FinanceDashboardStatsService;
use App\Services\Finance\FinanceNavService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class FinanceController extends Controller
{
    public function __construct(
        protected FinanceDashboardStatsService $stats,
        protected FinanceNavService $nav
    ) {}

    public function home(): JsonResponse
    {
        $user = Auth::user();
        abort_unless($user instanceof User && $this->nav->canAccessModule($user), 403);

        return response()->json([
            'zone' => $this->nav->zoneLabel($user),
            'home_path' => parse_url($this->nav->homeUrl($user), PHP_URL_PATH),
            'expense_scopes' => collect($this->nav->availableExpenseScopes($user))
                ->map(fn (string $scope) => [
                    'key' => $scope,
                    'label' => $this->nav->expenseScopeLabel($scope),
                ])
                ->values(),
            'tabs' => $this->nav->mobileTabs($user),
        ]);
    }

    public function self(): JsonResponse
    {
        $user = Auth::user();
        abort_unless($user instanceof User && $this->canAccessSelfFinance($user), 403);

        $stats = $this->stats->selfStats($user);

        return response()->json([
            'pending_claims' => $stats['pending_claims'],
            'pending_claims_amount' => $stats['pending_claims_amount'],
            'approved_mtd' => $stats['approved_mtd'],
            'paid_mtd' => $stats['paid_mtd'],
            'outstanding_advance' => $stats['outstanding_advance'],
            'next_deduction' => $this->formatDeduction($stats['next_deduction'] ?? null),
            'recent_claims' => collect($stats['recent_claims'] ?? [])
                ->map(fn (Expense $expense) => $this->formatExpense($expense))
                ->values(),
        ]);
    }

    public function team(): JsonResponse
    {
        $user = Auth::user();
        abort_unless($user instanceof User && $user->hasPermission('finance_team_view'), 403);

        $stats = $this->stats->teamStats($user);

        return response()->json([
            'pending_count' => $stats['pending_count'],
            'pending_amount' => $stats['pending_amount'],
            'team_size' => $stats['team_size'],
            'recent_pending' => collect($stats['recent_pending'] ?? [])
                ->map(fn (Expense $expense) => array_merge(
                    $this->formatExpense($expense),
                    ['employee' => $expense->claimant?->only(['id', 'name'])]
                ))
                ->values(),
        ]);
    }

    public function operational(): JsonResponse
    {
        $user = Auth::user();
        abort_unless($user instanceof User && $this->nav->hasOperationalOrTreasuryAccess($user), 403);

        $stats = $this->stats->operationalStats($user->company_id);

        return response()->json([
            'pending_expenses' => $stats['pending_expenses'],
            'pending_expenses_amount' => $stats['pending_expenses_amount'],
            'pending_advances' => $stats['pending_advances'],
            'fnf_awaiting_action' => $stats['fnf_awaiting_action'],
            'recent_pending_expenses' => collect($stats['recent_pending_expenses'] ?? [])
                ->map(fn (Expense $expense) => array_merge(
                    $this->formatExpense($expense),
                    ['employee' => $expense->claimant?->only(['id', 'name'])]
                ))
                ->values(),
        ]);
    }

    public function myAdvances(Request $request): JsonResponse
    {
        $user = Auth::user();
        abort_unless($user instanceof User && $this->canAccessSelfFinance($user), 403);

        $summary = $this->stats->myAdvanceSummary($user);
        $plans = $this->stats->groupedAdvancePlans($user);

        $query = PrePayment::query()
            ->where('user_id', $user->id)
            ->when($user->company_id, fn ($q) => $q->where('company_id', $user->company_id))
            ->orderByDesc('advance_date')
            ->orderByDesc('year')
            ->orderByDesc('month')
            ->orderBy('installment_number');

        if ($request->filled('status')) {
            $query->where('status', $request->string('status'));
        }

        $advances = $query->paginate($request->integer('per_page', 20));

        return response()->json([
            'summary' => [
                'outstanding' => $summary['outstanding'],
                'pending_installments' => $summary['pending_installments'],
                'next_deduction' => $this->formatDeduction($summary['next_deduction'] ?? null),
            ],
            'plans' => $plans->map(fn (object $plan) => [
                'group_id' => $plan->group_id,
                'advance_date' => $plan->advance_date?->toDateString(),
                'total_amount' => $plan->total_amount,
                'remaining' => $plan->remaining,
                'installments' => $plan->installments,
                'paid_of' => $plan->paid_of,
                'pending_of' => $plan->pending_of,
            ])->values(),
            'advances' => $advances->through(fn (PrePayment $advance) => $this->formatAdvance($advance)),
        ]);
    }

    protected function canAccessSelfFinance(User $user): bool
    {
        return $this->nav->userHasAnyPermission($user, ['finance_self_view', 'expenses_create_own']);
    }

    protected function formatExpense(Expense $expense): array
    {
        return [
            'id' => $expense->id,
            'category' => $expense->category,
            'amount' => (float) $expense->amount,
            'date' => $expense->date?->toDateString(),
            'status' => $expense->status,
            'description' => $expense->description,
        ];
    }

    protected function formatAdvance(PrePayment $advance): array
    {
        return [
            'id' => $advance->id,
            'advance_date' => $advance->advance_date?->toDateString(),
            'deduction_month' => $advance->month,
            'deduction_year' => $advance->year,
            'amount' => (float) $advance->amount,
            'total_amount' => $advance->total_amount !== null ? (float) $advance->total_amount : null,
            'installment_number' => $advance->installment_number,
            'installment_count' => $advance->installment_count,
            'installment_label' => $advance->installmentLabel(),
            'status' => $advance->status,
            'notes' => $advance->notes,
        ];
    }

    protected function formatDeduction(?PrePayment $deduction): ?array
    {
        if (! $deduction) {
            return null;
        }

        return [
            'id' => $deduction->id,
            'amount' => (float) $deduction->amount,
            'month' => $deduction->month,
            'year' => $deduction->year,
            'advance_date' => $deduction->advance_date?->toDateString(),
            'installment_label' => $deduction->installmentLabel(),
        ];
    }
}
