<?php

namespace App\Http\Controllers;

use App\Enums\InvestmentTransactionType;
use App\Models\InvestmentTransaction;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Inertia\Inertia;
use Inertia\Response;

class ReferralController extends Controller
{
    public function index(Request $request): Response
    {
        /** @var User $user */
        $user = $request->user();

        if (! $user->referral_program_enabled) {
            return Inertia::render('referrals/index', [
                'referral_program_enabled' => false,
            ]);
        }

        $directReferrals = $user->directReferrals()
            ->orderByDesc('created_at')
            ->get(['id', 'first_name', 'last_name', 'email', 'created_at']);

        $directIds = $directReferrals->pluck('id');

        $indirectReferrals = User::query()
            ->whereIn('referred_by_user_id', $directIds)
            ->with('referrer:id,first_name,last_name,email')
            ->orderByDesc('created_at')
            ->get(['id', 'first_name', 'last_name', 'email', 'referred_by_user_id', 'created_at']);

        $earnings = InvestmentTransaction::query()
            ->where('beneficiary_user_id', $user->id)
            ->whereIn('type', [
                InvestmentTransactionType::ReferralDirectBonus->value,
                InvestmentTransactionType::ReferralIndirectBonus->value,
            ])
            ->with(['investment.user:id,first_name,last_name,email'])
            ->orderByDesc('id')
            ->get();

        return Inertia::render('referrals/index', [
            'referral_program_enabled' => true,
            'referral' => [
                'code' => $user->referral_code,
                'link' => route('register', ['ref' => $user->referral_code]),
                'direct_count' => $directReferrals->count(),
                'indirect_count' => $indirectReferrals->count(),
                'total_earnings_usd' => number_format((float) $earnings->sum('amount'), 2, '.', ''),
                'direct_earnings_usd' => number_format((float) $earnings->where('type', InvestmentTransactionType::ReferralDirectBonus)->sum('amount'), 2, '.', ''),
                'indirect_earnings_usd' => number_format((float) $earnings->where('type', InvestmentTransactionType::ReferralIndirectBonus)->sum('amount'), 2, '.', ''),
            ],
            'direct_referrals' => $this->mapReferralRows($directReferrals, $earnings, 1),
            'indirect_referrals' => $this->mapReferralRows($indirectReferrals, $earnings, 2),
            'earnings' => $earnings->take(25)->map(fn (InvestmentTransaction $transaction): array => [
                'id' => $transaction->id,
                'level' => $transaction->referral_level,
                'type' => $transaction->type->value,
                'amount_usd' => number_format((float) $transaction->amount, 2, '.', ''),
                'base_percent' => $transaction->applied_percent !== null
                    ? number_format((float) $transaction->applied_percent, 4, '.', '')
                    : null,
                'source_investor' => $transaction->investment?->user?->name ?? '—',
                'source_investor_email' => $transaction->investment?->user?->email,
                'source_investment_txid' => $transaction->investment?->txid ?? '—',
                'created_at' => $transaction->created_at?->toIso8601String(),
            ])->values()->all(),
        ]);
    }

    /**
     * @param  Collection<int, User>  $referrals
     * @param  Collection<int, InvestmentTransaction>  $earnings
     * @return list<array<string, mixed>>
     */
    private function mapReferralRows(Collection $referrals, Collection $earnings, int $level): array
    {
        return $referrals->map(function (User $referral) use ($earnings, $level): array {
            $rowEarnings = $earnings->filter(fn (InvestmentTransaction $transaction): bool => (
                $transaction->referral_level === $level
                && $transaction->investment?->user_id === $referral->id
            ));

            return [
                'id' => $referral->id,
                'name' => $referral->name,
                'email' => $referral->email,
                'via' => $level === 2 ? ($referral->referrer?->name ?? '—') : null,
                'created_at' => $referral->created_at?->toIso8601String(),
                'earnings_usd' => number_format((float) $rowEarnings->sum('amount'), 2, '.', ''),
                'earnings_count' => $rowEarnings->count(),
            ];
        })->values()->all();
    }
}
