<?php

namespace App\Components\Report;

use App\Models\LeadSource\LeadSource;
use App\Models\Solicitor\Solicitor;
use App\Services\Dashboard\ProductivityMetrics;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Carbon;
use Livewire\Attributes\Url;
use Livewire\Component;

/**
 * Productivity report — a period-scoped pipeline funnel (leads → contact →
 * contracts → redress → APP number) plus live status snapshots. Replaces the old
 * Throughput Trends / Pipeline KPIs views. All figures come from
 * App\Services\Dashboard\ProductivityMetrics and are segmentable by lead source.
 */
class ProductivityReport extends Component
{
    use AuthorizesRequests;

    #[Url]
    public ?string $from = null;

    #[Url]
    public ?string $to = null;

    #[Url]
    public ?int $leadSourceId = null;

    public function mount(): void
    {
        $this->authorize('reports.productivity.view');

        $this->from ??= Carbon::now()->startOfMonth()->toDateString();
        $this->to ??= Carbon::now()->toDateString();
    }

    public function render()
    {
        [$from, $to] = $this->window();

        $solicitorId = (int) app(Solicitor::class)->getKey();

        $metrics = new ProductivityMetrics(
            $solicitorId,
            $this->leadSourceId ?: null,
        );

        return view('components.report.productivity-report', [
            'report'      => $metrics->report($from, $to),
            'fromLabel'   => $from->format('j M Y'),
            'toLabel'     => $to->format('j M Y'),
            'days'        => (int) $from->diffInDays($to) + 1,
            'leadSources' => LeadSource::query()
                ->where('solicitor_id', $solicitorId)
                ->orderBy('display_name')
                ->get(['id', 'display_name']),
        ]);
    }

    /**
     * Parsed, sane [from, to] Carbon range. Falls back to month-to-date on bad
     * input and swaps the bounds if entered the wrong way round.
     */
    private function window(): array
    {
        try {
            $from = Carbon::parse($this->from)->startOfDay();
        } catch (\Throwable) {
            $from = Carbon::now()->startOfMonth();
        }

        try {
            $to = Carbon::parse($this->to)->endOfDay();
        } catch (\Throwable) {
            $to = Carbon::now()->endOfDay();
        }

        return $from->greaterThan($to)
            ? [$to->copy()->startOfDay(), $from->copy()->endOfDay()]
            : [$from, $to];
    }
}
