<?php

namespace Ignite\Core\Http\ViewComposers;

use Ignite\Core\Models\Summary\Metric;
use Illuminate\Support\Collection;
use Illuminate\View\View;

class TransactionSummaryComposer
{
    /**
     * Bind data to the view.
     *
     * @param  View $view
     * @return void
     */
    public function compose(View $view)
    {
        $view->with('summary', $summary = $this->decorate($this->query()->map(function ($metric) {
            return app(Metric::class, (array) $metric);
        })->keyBy(function ($metric) {
            return $metric->name();
        })));

        $view->with('summaryTotal', $summary->sum(function ($metric) {
            return (int) $metric->count();
        }));

        $view->with('transactionSummaryCards', $this->getTransactionSummaryCards($summary));
    }

    /**
     * Query the metrics from the database.
     *
     * @return Collection
     */
    protected function query()
    {
        $earnedQuery = app('db')->table('core_transaction')
            ->selectRaw('"earned" as name, COUNT(*) AS count, SUM(value) as total')
            ->where('user_id', '=', auth()->id())
            ->whereIn('type', [
                'EARNED', 'MANUAL-RECEIVE', 'RESET', 'RETURN', 'REFUND', 'EXPIRED', 'CANCELLED'
            ]);

        $redeemedQuery = app('db')->table('core_transaction')
            ->selectRaw('"redeemed" as name, COUNT(*) AS count, SUM(value) as total')
            ->where('user_id', '=', auth()->id())
            ->whereIn('type', [
                'REDEEMED', 'MANUAL-REDEEM'
            ]);

        return app('db')->table('core_transaction')
            ->selectRaw('"balance" as name, COUNT(*) as count, SUM(value) as total')
            ->where('user_id', '=', auth()->id())
            ->union($earnedQuery)
            ->union($redeemedQuery)
            ->get();
    }

    /**
     * Decorate the summary collection.
     *
     * @param  Collection $collection
     * @return Collection
     */
    protected function decorate(Collection $collection)
    {
        $allowedTypes = ['earned', 'redeemed', 'balance'];

        foreach ($allowedTypes as $allowedType) {
            if (! $collection->has($allowedType)) {
                $collection->push(app(Metric::class, [
                    'name' => $allowedType,
                    'count' => 0,
                    'total' => 0
                ]));
            }
        };

        return $collection->keyBy(function ($metric) {
            return $metric->name();
        });
    }

    /**
     * Build the summary cards for the transaction view.
     *
     * @param Collection $summary
     *
     * @return array<int, array<string, string>>
     */
    protected function getTransactionSummaryCards(Collection $summary): array
    {
        return [
            [
                'label' => 'Available Points',
                'value' => $summary->has('balance') ? $summary->get('balance')->total() : app(Metric::class, [
                    'name' => 'balance',
                    'count' => 0,
                    'total' => 0,
                ])->total(),
                'icon' => 'fa-dollar-sign',
            ],
            [
                'label' => 'Points Earned',
                'value' => $summary->has('earned') ? $summary->get('earned')->total() : app(Metric::class, [
                    'name' => 'earned',
                    'count' => 0,
                    'total' => 0,
                ])->total(),
                'icon' => 'fa-arrow-trend-up',
            ],
            [
                'label' => 'Points Redeemed',
                'value' => $summary->has('redeemed') ? $summary->get('redeemed')->total() : app(Metric::class, [
                    'name' => 'redeemed',
                    'count' => 0,
                    'total' => 0,
                ])->total(),
                'icon' => 'fa-arrow-trend-down',
            ],
        ];
    }
}
