<?php

namespace App\Http\Resources;

use App\Facades\Settings;
use App\Facades\Site;
use App\IntegrationRepository;
use App\Modules\Stock\AutoTraderStock;
use App\Services\RemoveBg;
use App\Traits\MakeAndModelList;
use App\VehicleStockSyncLogRepository;
use App\VehicleType;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\App;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\DrivetrainType;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\Services\FinanceServiceHelper;
use Mtc\MercuryDataModels\Traits\HasVehicleCustomAttributes;
use Mtc\MercuryDataModels\TransmissionType;
use Mtc\MercuryDataModels\VehicleAutoTraderData;

class VehicleViewResource extends JsonResource
{
    use ResourceMediaEntries;
    use HasVehicleCustomAttributes;
    use MakeAndModelList;
    use SeoDataForModel;

    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        $this->resource->load([
            'mediaUses.media',
            'features',
            'equipment',
            'make',
            'model',
            'specs',
            'financeExamples',
            'labels',
            'autoTraderData',
            'priceHistory',
        ]);

        $vehicle = $this->resource->toArray();
        $vehicle['dealership_name'] = $this->resource->dealership?->name;
        $vehicle = array_merge($vehicle, $this->getMediaEntries());
        $vehicle['seo'] = $this->getSeoData($this->resource);
        $vehicle['stats'] = $this->getStats();
        $vehicle['data'] = $this->resource->data ?? [];
        $vehicle['auto_trader_data'] = $this->resource->autoTraderData
            ?? collect((new VehicleAutoTraderData())->getFillable())->flip()->map(fn($item) => null);
        $vehicle['autotrader_data'] = $this->getAutoTraderData();
        $vehicle['autotrader_connect'] = Settings::get('auto-trader-hub-enabled');
        $vehicle['alerts'] = $this->getAlerts();
        $vehicle['has_finance_provider'] = FinanceServiceHelper::hasEnabledProvider();
        $vehicle['finance_defaults'] = [
            'term' => Settings::get('finance-term'),
            'annual_mileage' => Settings::get('finance-annual_mileage'),
            'deposit_percentage' => Settings::get('finance-deposit_percentage'),
            'credit_rating' => Settings::get('finance-credit_rating'),
        ];

        if (!empty($this->resource->slug)) {
            $vehicle['site_url'] = Site::vehicleUrl($this->resource, true);
        }

        $vehicle['extra'] = $this->getExtraData($this->resource);
        $vehicle['created_at'] = $this->resource->created_at->format('d/m/Y H:i');
        $vehicle['updated_at'] = $this->resource->updated_at->format('d/m/Y H:i');
        $vehicle['synced_at'] = $this->resource->stockSyncLogs()
            ->imports()
            ->last()
            ->first()?->synced_at?->format('d/m/Y H:i');

        $vehicle['price_history'] = $this->resource->priceHistory
            ->sortByDesc('created_at')
            ->map(fn($history) => [
                'price' => $history->price,
                'date' => $history->created_at->format('d/m/Y H:i'),
                'timestamp' => $history->created_at->toISOString(),
            ])
            ->values();

        return [
            'vehicle' => $vehicle,
            'types' => collect(VehicleType::cases())
                ->map(fn(VehicleType $type) => [
                    'name' => ucwords(strtolower($type->name)),
                    'id' => $type->value,
                ]),
            'makes' => $this->getMakeList(),
            'models' => $this->getModelList($this->resource->make_id),
            'fuel_types' => FuelType::all(),
            'drivetrains' => DrivetrainType::all(),
            'body_styles' => BodyStyleType::all(),
            'transmissions' => TransmissionType::all(),
            'sales_channels' => (new IntegrationRepository())->getAllForType('sales-channels', true)
                ->map(fn($channel, $id) => [
                    'id' => $id,
                    'name' => $channel['image']['alt'],
                    'active' => $channel['active'] ?? false,
                ])->values(),
            'monthly_cost_types' => config('automotive.monthly_cost_types', []),
            'settings' => $this->getSettings(),
        ];
    }


    private function getStats(): array
    {
        $views = $this->resource->views()
            ->where('date', '>=', Carbon::now()->subWeek()->format('Y-m-d'))
            ->orderBy('date')
            ->get();

        $conversions = $this->resource->conversions()
            ->where('date', '>=', Carbon::now()->subWeek()->format('Y-m-d'))
            ->orderBy('date')
            ->get()
            ->groupBy('type');

        return [
            'days_in_stock' => $this->resource->days_in_stock,
            'days_since_update' => $this->resource->days_since_update,
            'enquiries' => $this->resource->allEnquiries()->count(),
            'views_today' => $views
                    ->where('date', Carbon::now()->format('Y-m-d'))
                    ->pluck('hits')
                    ->first() ?? 0,
            'views_week' => $views
                    ->where('date', '>=', Carbon::now()->subWeek()->format('Y-m-d'))
                    ->sum('hits') ?? 0,
            'views_month' => $views
                    ->where('date', '>=', Carbon::now()->subMonth()->format('Y-m-d'))
                    ->sum('hits') ?? 0,
            'filter_views_today' => $views
                    ->where('date', Carbon::now()->format('Y-m-d'))
                    ->pluck('filter_views')
                    ->first() ?? 0,
            'filter_views_week' => $views
                    ->where('date', '>=', Carbon::now()->subWeek()->format('Y-m-d'))
                    ->sum('filter_views') ?? 0,
            'filter_views_month' => $views
                    ->where('date', '>=', Carbon::now()->subMonth()->format('Y-m-d'))
                    ->sum('filter_views') ?? 0,

            'graph' => [
                'labels' => $views->pluck('date')->unique()->map(fn($date) => Carbon::parse($date)->format('dS M')),
                'datasets' => [
                    [
                        'label' => 'Full page advert views',
                        'yAxisID' => 'y1',
                        'backgroundColor' => '#600000',
                        'data' => $views->pluck('hits'),
                        'tension' => 0.5
                    ],
                    [
                        'label' => 'Views in search results',
                        'yAxisID' => 'y',
                        'backgroundColor' => '#000060',
                        'data' => $views->pluck('filter_views'),
                        'tension' => 0.5
                    ],
                ],
            ],
            'conversions' => $conversions
                ->map(fn($data, $type) => [
                    'name' => __('vehicles.conversions.' . $type),
                    'today' => $data
                            ->where('date', Carbon::now()->format('Y-m-d'))
                            ->pluck('hits')
                            ->first() ?? 0,
                    'week' => $data
                        ->where('date', Carbon::now()->format('Y-m-d'))
                        ->sum('hits'),
                ])
                ->values()
        ];
    }

    private function getAutoTraderData(): ?array
    {
        return $this->resource->autoTraderData
            ?->getDisplayAttributes()
            ->map(fn($attribute, $key) => [
                'id' => $key,
                'name' => __("vehicles.auto-trader.$key"),
                'value' => $attribute . ($key === 'price_position' ? '%' : ''),
            ])
            ->values()
            ->toArray();
    }

    private function getAlerts(): array
    {
        $alerts = [];
        if ($this->hasExternalSync()) {
            $alerts[] = [
                'type' => 'warning',
                'errors' => [__('vehicles.external_sync_warning', ['provider' => $this->stockProviderName()])],
            ];
        }

        return $alerts;
    }

    private function hasExternalSync(): bool
    {
        return !empty($this->resource->uuid)
            && (new IntegrationRepository())->getEnabledForType('stock')->has($this->resource->stock_provider);
    }

    private function stockProviderName(): ?string
    {
        return collect((new IntegrationRepository())->getEnabledForType('stock'))
            ->filter(fn($object, $name) => $name == $this->resource->stock_provider)
            ->map(fn($provider) => App::make($provider['class']))
            ->first()
            ?->name();
    }

    private function getSettings(): array
    {
        return [
            'distance_measurement' => Settings::get('automotive-distance_measurement'),
            'show_ai_button' => (new IntegrationRepository())
                ->getEnabledForType('ai-content')
                ->isNotEmpty(),
            'show_remove_background_button' => RemoveBg::enabled(),
            'show_cap_id_field' => Settings::get('vehicle-spec-providers-cap-enabled'),
            'show_recommended_image_management' => (new IntegrationRepository())
                ->getEnabledForType('smart-image-management')
                ->isNotEmpty(),
            'show_auto_trader_id_field' => App::make(AutoTraderStock::class)->enabled(),
            'show_stock_sync_log' => App::make(VehicleStockSyncLogRepository::class)->enabled(),
            'show_is_preg_reg_field' => Settings::get('vehicles-pre-reg-condition-enabled')
        ];
    }
}
