<?php

namespace CouponsPlus\App\Conditions\BuiltIn\Conditions;

use Carbon\Carbon;
use CouponsPlus\App\Conditions\Condition;
use CouponsPlus\App\Time\WpDateTimeZone;
use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\Original\Collections\Mapper\Types;

#[\AllowDynamicProperties]
Class Date extends Condition
{
    const TYPE = 'Date';
    
    static public function getName() : string
    {
        return __('Date', 'coupons-plus-for-woocommerce');
    }

    static public function getDescription() : string
    {
        return '';
    }
    
    public static function getNotes() : array 
    { 
        return [
            __("This server's clock will be used instead of the customer's. Current timezone can be found in: Settings > General", 'coupons-plus-for-woocommerce')
        ]; 
    }

    static public function getUseCases(): Collection
    {
        return new Collection([
            __('Schedule offers in advance from a specific date range.', 'coupons-plus-for-woocommerce'),
            __('Apply different discounts based on a date (EG: From Dec 1st to Dec 7th -> 10% OFF, From Dec 8th to Dec 14th -> 20% OFF, ...).', 'coupons-plus-for-woocommerce'),
        ]);  
    } 

    public static function getOptions() : Collection
    {
        return new Collection([
            'type' => Types::STRING()->allowed([
                __('Specific Day', 'coupons-plus-for-woocommerce') => 'exact', 
                __('Range', 'coupons-plus-for-woocommerce') => 'range',
            ])->meta([
                'alternativeLabels' => [
                    'exact' => '',
                    'range' => __('Start - end', 'coupons-plus-for-woocommerce')
                ]
            ]),
            'date' => [
                'exact' => Types::STRING(), // hour is ignored
                'from' => Types::STRING()->withDefault(
                    Carbon::now(WpDateTimeZone::getWpTimezone())->startOfDay()->format('Y-m-d H:i:s')
                ), // hours are considered!
                'to' => Types::STRING()->withDefault(
                    Carbon::now(WpDateTimeZone::getWpTimezone())->addDay()->endOfDay()->format('Y-m-d H:i:s')
                )  // hours are considered!
            ],
            // only used when type is 'exact', because range already supports hours
            'exactHours' => [
                'enabled' => Types::STRING()->withDefault('no')->allowed([
                    __('All day', 'coupons-plus-for-woocommerce') => 'no',
                    __('Specific hours', 'coupons-plus-for-woocommerce') => 'yes',
                ]),
                'from' => Types::STRING()->withDefault('00:00'), // hours and minutes in the format: H:i (24-hour format) eg: 14:59
                'to' => Types::STRING()->withDefault('23:59') // same as above
            ]
        ]);
    }
    
    protected function test() : bool
    {
        if (method_exists(Carbon::class, 'useMicrosecondsFallback')) {
            Carbon::useMicrosecondsFallback(false);
        }
        
        (object) $todayWithWrongMicroseconds = Carbon::now(WpDateTimeZone::getWpTimezone());
        
        (object) $today = Carbon::createFromDate(
            $todayWithWrongMicroseconds->format('Y'), 
            $todayWithWrongMicroseconds->format('m'), 
            $todayWithWrongMicroseconds->format('d')
        );

        switch ($this->options->type) {
            case 'exact':
                return $this->matchExactDates($today);
                break;
            case 'range':
                return $this->matchDateInRange($today);
                break;
        }
    }

    protected function matchExactDates(Carbon $today) : bool
    {
        (object) $expectedDate = (new Carbon($this->options->date->exact->get()));

        return $today->startOfDay()->equalTo($expectedDate->startOfDay());
    }

    protected function matchDateInRange(Carbon $today) : bool
    {
        (object) $start = new Carbon($this->options->date->from->get());
        (object) $end = new Carbon($this->options->date->to->get());

        return $today->greaterThanOrEqualTo($start) &&
               $today->lessThanOrEqualTo($end);
    }
}