<?php

namespace App\Livewire\Concerns;

use Illuminate\Support\Carbon;
use Livewire\Attributes\Url;

/**
 * Date filtering for reports and listings, with the presets shopkeepers
 * actually ask for ("aaj ka", "is mahine ka").
 */
trait WithDateRange
{
    #[Url(except: '')]
    public string $from = '';

    #[Url(except: '')]
    public string $to = '';

    public function mountWithDateRange(string $preset = 'this_month'): void
    {
        if ($this->from === '' && $this->to === '') {
            $this->applyPreset($preset);
        }
    }

    public function applyPreset(string $preset): void
    {
        [$from, $to] = match ($preset) {
            'today' => [now()->startOfDay(), now()->endOfDay()],
            'yesterday' => [now()->subDay()->startOfDay(), now()->subDay()->endOfDay()],
            'this_week' => [now()->startOfWeek(), now()->endOfWeek()],
            'last_week' => [now()->subWeek()->startOfWeek(), now()->subWeek()->endOfWeek()],
            'this_month' => [now()->startOfMonth(), now()->endOfMonth()],
            'last_month' => [now()->subMonthNoOverflow()->startOfMonth(), now()->subMonthNoOverflow()->endOfMonth()],
            'this_quarter' => [now()->startOfQuarter(), now()->endOfQuarter()],
            'this_year' => [now()->startOfYear(), now()->endOfYear()],
            'last_year' => [now()->subYear()->startOfYear(), now()->subYear()->endOfYear()],
            default => [now()->startOfMonth(), now()->endOfMonth()],
        };

        $this->from = $from->toDateString();
        $this->to = $to->toDateString();

        if (method_exists($this, 'resetPage')) {
            $this->resetPage();
        }
    }

    public function updatedFrom(): void
    {
        if (method_exists($this, 'resetPage')) {
            $this->resetPage();
        }
    }

    public function updatedTo(): void
    {
        if (method_exists($this, 'resetPage')) {
            $this->resetPage();
        }
    }

    protected function fromDate(): ?string
    {
        return $this->from !== '' ? $this->from : null;
    }

    protected function toDate(): ?string
    {
        return $this->to !== '' ? $this->to : null;
    }

    /** The equivalent window immediately before the current one. */
    protected function previousPeriod(): array
    {
        if ($this->from === '' || $this->to === '') {
            return [null, null];
        }

        $from = Carbon::parse($this->from);
        $to = Carbon::parse($this->to);
        $days = max(1, (int) $from->diffInDays($to) + 1);

        return [
            $from->copy()->subDays($days)->toDateString(),
            $from->copy()->subDay()->toDateString(),
        ];
    }

    public function rangeLabel(): string
    {
        if ($this->from === '' && $this->to === '') {
            return 'All time';
        }

        $formatter = app(\App\Services\Formatter::class);

        return trim($formatter->date($this->from ?: null).' — '.$formatter->date($this->to ?: null), ' —');
    }
}
