<?php

namespace App\Support;

use App\Models\Expense;
use App\Models\ExpenseDay;
use Carbon\Carbon;

class ExpensePayload
{
    /**
     * @return array<string, mixed>
     */
    public static function expenseDayListItem(ExpenseDay $day): array
    {
        $expenseDate = Carbon::parse($day->expense_date);
        $isToday = $expenseDate->isToday();

        return [
            'id' => $day->id,
            'expense_date' => $day->expense_date?->toDateString(),
            'day_label' => $expenseDate->format('l'),
            'formatted_date' => ExpenseDates::formatDate($expenseDate),
            'is_today' => $isToday,
            'notes' => $day->notes,
            'expenses_count' => $day->expenses_count ?? $day->activeExpensesCount(),
            'total_afn' => ExpenseReport::formatAmount($day->expenses_total ?? $day->activeExpensesTotal()),
            'created_by_name' => $day->creator?->name,
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function expenseDayShow(ExpenseDay $day): array
    {
        $expenseDate = Carbon::parse($day->expense_date);

        return [
            'id' => $day->id,
            'expense_date' => $day->expense_date?->toDateString(),
            'formatted_date' => ExpenseDates::formatDateLong($expenseDate),
            'is_today' => $expenseDate->isToday(),
            'notes' => $day->notes,
            'expenses_count' => $day->expenses->where('status', '!=', ExpenseStatus::CANCELLED)->count(),
            'total_afn' => ExpenseReport::formatAmount(
                (float) $day->expenses
                    ->filter(fn (Expense $expense): bool => $expense->countsTowardTotals())
                    ->sum('amount_original'),
            ),
        ];
    }

    /**
     * @return list<array<string, mixed>>
     */
    public static function categorySummaryForDay(ExpenseDay $day): array
    {
        $expenses = $day->expenses->filter(fn (Expense $expense): bool => $expense->countsTowardTotals());

        return $expenses
            ->groupBy('expense_category_id')
            ->map(function ($group): array {
                /** @var Expense $first */
                $first = $group->first();
                $amount = (float) $group->sum('amount_original');

                return [
                    'category_id' => $first->expense_category_id,
                    'category_slug' => $first->category?->slug,
                    'category_name' => $first->category?->displayName(),
                    'count' => $group->count(),
                    'amount_afn' => ExpenseReport::formatAmount($amount),
                ];
            })
            ->sortByDesc(fn (array $row): float => (float) str_replace(',', '', $row['amount_afn']))
            ->values()
            ->all();
    }

    /**
     * @return array<string, mixed>
     */
    public static function expenseDetail(Expense $expense): array
    {
        return [
            ...ExpenseReport::expensePayload($expense),
            'reference_number' => $expense->reference_number,
            'branch_id' => $expense->branch_id,
            'attachments' => $expense->attachments->map(fn ($attachment): array => [
                'id' => $attachment->id,
                'original_name' => $attachment->original_name,
                'file_url' => $attachment->fileUrl(),
                'mime_type' => $attachment->mime_type,
            ])->values()->all(),
            'transactions' => $expense->transactions->map(fn ($transaction): array => [
                'id' => $transaction->id,
                'action' => $transaction->action,
                'amount_afn' => ExpenseReport::formatAmount((float) $transaction->amount_original),
                'notes' => $transaction->notes,
                'performed_by_name' => $transaction->performer?->name,
                'created_at' => $transaction->created_at?->toDateTimeString(),
                'created_at_display' => ExpenseDates::formatDateTime($transaction->created_at),
            ])->values()->all(),
        ];
    }
}
