<?php

namespace Yajny\Helpers\LoyaltyProgram;

use Yajny\Member\Models\LoyaltyProgram;

class TierCalculator extends LoyaltyProgramCalculator
{
    public function __construct()
    {
        $last_saturday = date('Y-m-d', strtotime('last saturday'));
        parent::__construct($last_saturday);
    }

    public function calculateTiers(array $user_ids = [])
    {
        $data = [];
        $user_sales_records = $this->getEligibleUserSales($user_ids);
        foreach ($user_sales_records as $user_id => $user_sales) {
            $old_bonus = $this->checkOldLoyaltyBonus($user_id);
            $data[$user_id] = $this->checkCurrentAndNextTiers($user_sales, $old_bonus);
        }

        $compiled_users = array_keys($data);
        foreach ($user_ids as $user_id) {
            if (!in_array($user_id, $compiled_users))
                $data[$user_id] = $this->checkCurrentAndNextTiers(collect());
        }

        return $data;
    }

    public function checkCurrentAndNextTiers($user_sales, $old_bonus = null)
    {
        if ($old_bonus) {
            $currentRank = $old_bonus->loyaltyProgram->rank;
            $maxRank = $this->loyalty_programs->max('rank');

            if ($old_bonus->status != 'declined') {
                if ($currentRank == $maxRank) {
                    $lastProgram = $this->loyalty_programs->first();
                    $data = $this->calculateForPrograms($user_sales, null, $lastProgram);
                } else {
                    $filteredPrograms = $this->loyalty_programs->filter(function ($program) use ($currentRank) {
                        return $program->rank == $currentRank || $program->rank == $currentRank + 1;
                    });

                    $currentProgram = $filteredPrograms->last();
                    $nextProgram = $filteredPrograms->first();
                    $data = $this->calculateForPrograms($user_sales, $nextProgram, $currentProgram);
                }
            } else {
                $nextProgram = $this->loyalty_programs->filter(function ($program) use ($currentRank) {
                    return $program->rank == $currentRank;
                })->first();

                $data = $this->calculateForPrograms($user_sales, $nextProgram);
            }
        } else {
            $firstProgram = $this->loyalty_programs->last();
            $data = $this->calculateForPrograms($user_sales, $firstProgram);
        }

        return $data;
    }

    public function calculateForPrograms($user_sales, $next_program = null, $current_program = null)
    {
        $current_tier_number_of_purchases = 0;
        $current_tier_total_amount = 0;
        $next_tier_number_of_purchases = 0;
        $next_tier_total_amount = 0;

        foreach ($user_sales as $user_sale) {
            if ($next_program && $user_sale->order_amount >= $next_program->min_sale_amount) {
                $next_tier_number_of_purchases++;
                $next_tier_total_amount += $user_sale->order_amount;
            }

            if ($current_program && $user_sale->order_amount >= $current_program->min_sale_amount) {
                $current_tier_number_of_purchases++;
                $current_tier_total_amount += $user_sale->order_amount;
            }
        }

        if ($next_program) {
            $data['next_program'] = [
                'number_of_purchases' => $next_tier_number_of_purchases,
                'total_amount' => $next_tier_total_amount,
                'program' => $next_program
            ];
        } else {
            $data['next_program'] = null;
        }

        if ($current_program) {
            $data['current_program'] = [
                'number_of_purchases' => $current_tier_number_of_purchases,
                'total_amount' => $current_tier_total_amount,
                'program' => $current_program
            ];
        } else {
            $data['current_program'] = null;
        }

        return $data;
    }
}