<?php

namespace App\Services\Dashboard;

use App\Models\Solicitor\Solicitor;
use Carbon\CarbonInterface;
use Illuminate\Support\Carbon;

class DailyManagementReportService
{
    public function build(CarbonInterface $cutoff): array
    {
        $to = Carbon::instance($cutoff)->copy()->timezone(config('app.timezone'));
        $periods = [
            'day' => $to->copy()->startOfDay(),
            'week' => $to->copy()->startOfWeek(Carbon::MONDAY),
            'month' => $to->copy()->startOfMonth(),
        ];

        $rows = [
            ['label' => 'Leads In', 'key' => 'leads_in'],
            ['label' => 'Contracts Sent', 'key' => 'contracts_sent'],
            ['label' => 'Sent To Redress', 'key' => 'sent_to_redress'],
            ['label' => 'APP Number Received', 'key' => 'app_number_received'],
        ];
        $values = collect($periods)->mapWithKeys(fn ($from, $period) => [
            $period => collect($rows)->mapWithKeys(fn ($row) => [$row['key'] => 0])->all(),
        ])->all();
        $breakdown = collect($periods)->mapWithKeys(fn ($from, $period) => [
            $period => collect($rows)->mapWithKeys(fn ($row) => [$row['key'] => []])->all(),
        ])->all();

        $solicitors = Solicitor::query()->orderBy('name')->get(['id', 'name']);
        foreach ($solicitors as $solicitor) {
            $metrics = new ProductivityMetrics((int) $solicitor->id);

            foreach ($periods as $period => $from) {
                $firmValues = [
                    'leads_in' => $metrics->leadsIn($from, $to),
                    'contracts_sent' => $metrics->contractsSent($from, $to),
                    'sent_to_redress' => $metrics->sentToRedress($from, $to),
                    'app_number_received' => $metrics->appNumberReceived($from, $to),
                ];

                foreach ($firmValues as $key => $value) {
                    $values[$period][$key] += $value;
                    $breakdown[$period][$key][$solicitor->name] = $value;
                }
            }
        }

        return [
            'cutoff' => $to,
            'rows' => $rows,
            'values' => $values,
            'breakdown' => $breakdown,
        ];
    }

    public function text(array $report): string
    {
        $lines = [
            'Daily Management Report',
            'Reporting date: '.$report['cutoff']->format('l j F Y'),
            '',
            str_pad('Metric', 28).str_pad('Day', 34).str_pad('Week', 34).'Month',
        ];

        foreach ($report['rows'] as $row) {
            $key = $row['key'];
            $lines[] = str_pad($row['label'], 28)
                .str_pad($this->textValue($report, 'day', $key), 34)
                .str_pad($this->textValue($report, 'week', $key), 34)
                .$this->textValue($report, 'month', $key);
        }

        $lines[] = '';
        $lines[] = 'Day, week and month figures are measured up to '.$report['cutoff']->format('H:i').'.';

        return implode("\n", $lines);
    }

    private function textValue(array $report, string $period, string $key): string
    {
        $firms = collect($report['breakdown'][$period][$key])
            ->map(fn ($value, $name) => "{$name}: {$value}")
            ->implode(', ');

        return $report['values'][$period][$key].($firms ? " ({$firms})" : '');
    }
}
