<?php

namespace App\Reporting\Repositories;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleMake;

class VehicleReportRepository
{
    public function performanceReport(array $filters = [])
    {
        $period = match ($filters['timeframe'] ?? 'all') {
            '1d' => 1,
            '7d' => 7,
            '30d' => 30,
            default => null
        };
        $query = Vehicle::query()
            ->with([
                'make',
                'model',
            ])
            ->withImageCount()
            ->withEnquiryCount($period)
            ->withReservationCount($period)
            ->withViewCount($period);
        foreach ($filters as $filter => $value) {
            $this->applyConditionToQuery($query, $filter, $value);
        }

        return $query->get()
            ->map(fn(Vehicle $vehicle) => [
                'id' => $vehicle->id,
                'VRM' => $vehicle->vrm_condensed,
                'Make' => $vehicle->make?->name,
                'Model' => $vehicle->model?->name,
                'Title' => $vehicle->title,
                'Price' => $vehicle->price,
                'Image Count' => $vehicle->image_count,
                'Days In Stock' => $vehicle->days_in_stock,
                'View Count' => $vehicle->view_count ?? 0,
                'Enquiries' => $vehicle->enquiry_count,
                'Reservations' => $vehicle->reservation_count,
            ]);
    }

    public function segmentReport(array $input): array
    {
        return [
            'breakdown_graph' => $this->breakdownGraph($input['breakdown_type'] ?? 'body_type'),
            'average_graph' => $this->averageGraph($input['average_type'] ?? 'price'),
            'car_pool_size' => $this->carPoolSize(),
        ];
    }

    public function breakdownGraph(string $type): array
    {
        $data = match ($type) {
            'body_type' => BodyStyleType::all()
                ->map(fn(BodyStyleType $type) => [
                    'name' => $type->name,
                    'count' => $type->vehicles()->count()
                ])
                ->filter(fn($value) => $value['count'] > 0)
                ->sortByDesc(fn($value) => $value['count'])
                ->values(),
            'fuel_type' => FuelType::all()
                ->map(fn(FuelType $type) => [
                    'name' => $type->name,
                    'count' => $type->vehicles()->count()
                ])
                ->filter(fn($value) => $value['count'] > 0)
                ->sortByDesc(fn($value) => $value['count'])
                ->values(),
            'make' => VehicleMake::query()
                ->whereHas('vehicles')
                ->get()
                ->map(fn(VehicleMake $type) => [
                    'name' => $type->name,
                    'count' => $type->vehicles()->count()
                ])
                ->sortByDesc(fn($value) => $value['count'])
                ->values(),
            'age' => Vehicle::query()
                ->distinct()
                ->select('manufacture_year')
                ->get()
                ->map(fn($entry) => [
                    'name' => $entry->manufacture_year ?? 'Unspecified',
                    'count' => Vehicle::query()->where('manufacture_year', $entry->manufacture_year)->count(),
                ])
                ->sortBy(fn($value) => $value['name'])
                ->values(),
            'price' => $this->priceRanges()
                ->map(fn($range) => [
                    'name' => $range['name'],
                    'count' => Vehicle::query()
                        ->where('price', '>=', $range['min'])
                        ->where('price', '<', $range['max'])
                        ->count(),
                ])
                ->filter(fn($value) => $value['count'] > 0)
                ->values(),
            default => collect(),
        };

        return [
            'datasets' => [
                [
                    'backgroundColor' => '#00236C',
                    'data' => $data->pluck('count'),
                ]
            ],
            'status' => 'ok',
            'labels' => $data->pluck('name'),
            'type' => $type,
        ];
    }

    public function averageGraph(string $type): array
    {
        return [];
    }

    public function carPoolSize(): array
    {
        return [
            'total_count' => Vehicle::query()->count(),
            'total_used' => Vehicle::query()->used()->count(),
            'total_demo' => Vehicle::query()->where('is_demo', 1)->count(),
            'total_new' => Vehicle::query()->where('is_new', 1)->count(),
            'total_published' => Vehicle::query()->active()->count(),
            'total_published_used' => Vehicle::query()->active()->used()->count(),
            'total_published_demo' => Vehicle::query()->active()->where('is_demo', 1)->count(),
            'total_published_new' => Vehicle::query()->active()->where('is_new', 1)->count(),
            'sum_count' => Vehicle::query()->sum('price'),
            'sum_used' => Vehicle::query()->used()->sum('price'),
            'sum_demo' => Vehicle::query()->where('is_demo', 1)->sum('price'),
            'sum_new' => Vehicle::query()->where('is_new', 1)->sum('price'),
            'sum_published' => Vehicle::query()->active()->sum('price'),
            'sum_published_used' => Vehicle::query()->active()->used()->sum('price'),
            'sum_published_demo' => Vehicle::query()->active()->where('is_demo', 1)->sum('price'),
            'sum_published_new' => Vehicle::query()->active()->where('is_new', 1)->sum('price'),
        ];
    }

    private function applyConditionToQuery(Builder $query, int|string $filter, mixed $value)
    {
        switch ($filter) {
            case 'status':
                match ($value) {
                    'published' => $query->where('is_published', 1),
                    'unpublished' => $query->where('is_published', 0),
                    default => $query,
                };
                break;
            case 'type':
                if ($value !== 'all') {
                    $query->where('type', $value);
                }
                break;
            case 'condition':
                match ($value) {
                    'used' => $query->used(),
                    'new' => $query->where('is_new', 1),
                    'ex-demo' => $query->where('is_demo', 1),
                    default => $query,
                };
                break;
        }
    }

    private function priceRanges(): Collection
    {
        return collect([
            [
                'name' => '0 - 10k',
                'min' => 0,
                'max' => 10000,
            ],
            [
                'name' => '10k - 25k',
                'min' => 10000,
                'max' => 25000,
            ],
            [
                'name' => '25k - 40k',
                'min' => 25000,
                'max' => 40000,
            ],
            [
                'name' => '60k - 80k',
                'min' => 60000,
                'max' => 80000,
            ],
            [
                'name' => '80k - 100k',
                'min' => 80000,
                'max' => 100000,
            ],
            [
                'name' => '100k - 150k',
                'min' => 100000,
                'max' => 150000,
            ],
            [
                'name' => '150k - 300k',
                'min' => 150000,
                'max' => 300000,
            ],
            [
                'name' => '300k+',
                'min' => 300000,
                'max' => 10000000,
            ],
        ]);
    }
}
