<?php

namespace App\Repositories\Core;

use Carbon\Carbon;
use League\Period\Period;

class DateRange
{
    public static function today()
    {
        return self::previousDay(0);
    }

    public static function currentWeek()
    {
        return self::previousWeek(0);
    }

    public static function currentMonth()
    {
        return self::previousMonth(0);
    }

    public static function currentYear()
    {
        return self::previousYear(0);
    }

    public static function previousDay($nb = 1)
    {
        return [
            'start' => Carbon::now()->subDays($nb)->startOfDay(),
            'end' => Carbon::now()->subDays($nb)->endOfDay(),
        ];
    }

    public static function previousWeek($nb = 1)
    {
        return [
            'start' => Carbon::now()->subWeeks($nb)->startOfWeek(),
            'end' => Carbon::now()->subWeeks($nb)->endOfWeek(),
        ];
    }

    public static function previousMonth($nb = 1)
    {
        return [
            'start' => Carbon::now()->subMonths($nb)->startOfMonth(),
            'end' => Carbon::now()->subMonths($nb)->endOfMonth(),
        ];
    }

    public static function previousYear($nb = 1)
    {
        return [
            'start' => Carbon::now()->subYear($nb)->startOfYear(),
            'end' => Carbon::now()->subYear($nb)->endOfYear(),
        ];
    }

    public static function getPeriodsLastMonthWithLabels($nb, $withActual = true)
    {
        $data = [];
        $periods = DateRange::PeriodsToCarbon(DateRange::getPeriodsLastMonth($nb, $withActual));
        $labels = DateRange::getMonthNames($periods);
        foreach ($labels as $label) {
            $data[$label] = $periods;
        }

        return $data;
    }

    public static function getAllMonthNames()
    {
        return self::getMonthNames(self::PeriodsToCarbon(self::getPeriodsLastMonth(12)));
    }

    public static function getPeriodsLastMonth($nb = 1, $withActual = true)
    {
        $end = $withActual ? Carbon::now()->endOfMonth() : self::lastMonth();
        $begin = $nb === 1 ? $end->copy()->startOfMonth() : $end->copy()->subMonths($nb)->startOfMonth();

        return self::getPeriodsByMonth($begin, $end);
    }

    public static function getMonthNamesByPeriods($periods)
    {
        $months = [];
        foreach ($periods as $period) {
            $date = self::DatePointToCarbon($period->getStartDate());
            $months[] = DateTime::getMonthName($date);
        }

        return $months;
    }

    public static function getMonthNames($periods)
    {
        $months = [];
        foreach ($periods as $period) {
            $months[] = DateTime::getMonthName($period['start']);
        }

        return $months;
    }

    public static function getPeriodsLastWeek($nb = 1, $withActual = true)
    {
        $end = $withActual ? Carbon::now()->endOfWeek() : self::lastWeek();
        $begin = $end->copy()->subWeeks($nb);

        return static::getPeriodsByWeek($begin, $end);
    }

    public static function getPeriodsLastDay($nb = 1, $withActual = true)
    {
        $end = $withActual ? Carbon::now()->endOfDay() : static::lastDay();
        $begin = $end->copy()->subDays($nb);

        return static::getPeriodsByDay($begin, $end);
    }

    public static function byDay()
    {
        return [Carbon::now()->startOfDay(), Carbon::now()->endOfDay()];
    }

    public static function byWeek()
    {
        return [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()];
    }

    public static function byMonth()
    {
        return [Carbon::now()->startOfMonth(), Carbon::now()->endOfMonth()];
    }

    public static function byQuarter()
    {
        return [Carbon::now()->startOfQuarter(), Carbon::now()->endOfQuarter()];
    }

    public static function bySemester()
    {
        $quarter = Carbon::now()->quarter;
        switch ($quarter) {
            case 1:
            case 2:
                $date = Carbon::now()->startOfYear();
                break;
            case 3:
                $date = Carbon::now()->startOfQuarter();
                break;
            case 4:
                $date = Carbon::now()->subMonths(3)->startOfQuarter();
                break;
            default:
                return false;
        }

        return [$date, $date->addMonth(6)];
    }

    public static function byYear()
    {
        return [Carbon::now()->startOfYear(), Carbon::now()->endOfYear()];
    }

    public static function lastMonth()
    {
        return Carbon::now()->subMonths()->startOfMonth();
    }

    public static function lastWeek()
    {
        return Carbon::now()->subWeeks()->startOfWeek();
    }

    public static function lastDay()
    {
        return Carbon::now()->subDays()->startOfDay();
    }

    public static function getPeriodsByMonth($begin, $end, $interval = 1)
    {
        return self::getPeriods($begin, $end, "{$interval} MONTH");
    }

    public static function getPeriodsByWeek($begin, $end, $interval = 1)
    {
        return self::getPeriods($begin, $end, "{$interval} WEEK");
    }

    public static function getPeriodsByDay($begin, $end, $interval = 1)
    {
        return self::getPeriods($begin, $end, "{$interval} DAY");
    }

    public static function getPeriods($begin, $end, $duration)
    {
        $range = [];
        $interval = Period::fromDate($begin, $end);
        foreach ($interval->splitForward($duration) as $day) {
            $range[] = $day;
        }

        return $range;
    }

    public static function periodsToCarbon($periods)
    {
        $data = [];
        foreach ($periods as $period) {
            $data[] = self::PeriodToCarbon($period);
        }

        return $data;
    }

    public static function periodToCarbon($period)
    {
        return [
            'start' => self::DatePointToCarbon($period->startDate),
            'end' => self::DatePointToCarbon($period->endDate),
        ];
    }

    public static function datePointToCarbon($date)
    {
        return Carbon::createFromFormat('Y-m-d H:i:s', $date->format('Y-m-d H:i:s'));
    }

    public static function convertPeriod($txt)
    {
        return array_values(self::convertDaterange($txt));
    }

    public static function convertDaterange($txt)
    {
        $dates = explode('-', $txt);

        return [
            'start' => DateTime::convert(trim($dates[0])),
            'end' => DateTime::convert(trim($dates[1])),
        ];
    }

    public static function getPeriodByLocale($start, $end)
    {
        return [
            'start' => DateTime::convert($start),
            'end' => DateTime::convert($end),
        ];
    }
}
