<?php

namespace App\Services;

use App\Enums\GenderEnum;
use App\Models\Client;
use App\Models\Provider;
use App\Models\Schedule;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class ClientCalendarService
{
    public function __construct() {}

    public function getCalendar(): array
    {
        $user = Auth::user();

        $client = Client::where('user_id', $user->id)->first();

        $selectFields = [
            'schedules.id',
            'schedules.provider_id',
            'schedules.date',
            'schedules.start_time',
            'schedules.end_time',
            'schedules.total_amount',
            'schedules.period_type',
            'schedules.schedule_type',
            'schedules.address_id',
            'schedules.status',
            'custom_schedules.offers_meal',
            'provider_user.name as provider_name',
            'providers.gender',
            'providers.average_rating',
            'providers.total_services',

            DB::raw("
                EXISTS (
                    SELECT 1
                    FROM reviews
                    WHERE reviews.schedule_id = schedules.id
                    AND reviews.origin = 'client'
                    AND reviews.origin_id = {$client->id}
                    AND reviews.deleted_at IS NULL
                ) AS client_reviewed
            "),

            DB::raw("
                (
                    SELECT reviews.stars
                    FROM reviews
                    WHERE reviews.schedule_id = schedules.id
                    AND reviews.origin = 'client'
                    AND reviews.origin_id = {$client->id}
                    AND reviews.deleted_at IS NULL
                    LIMIT 1
                ) AS client_stars
            "),
        ];

        $upcomingSchedules = Schedule::with('address:district,address,number,source_id,source,id')
            ->where('schedules.client_id', $client->id)
            ->whereIn('schedules.status', ['pending', 'accepted', 'paid', 'started'])
            ->whereDate('schedules.date', '>=', now()->toDateString())
            ->leftJoin('providers', 'providers.id', '=', 'schedules.provider_id')
            ->leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
            ->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
            ->select($selectFields)
            ->orderBy('schedules.date', 'asc')
            ->orderBy('schedules.start_time', 'asc')
            ->get();

        $completedSchedules = Schedule::with('address:district,address,number,source_id,source,id')
            ->where('schedules.client_id', $client->id)
            ->whereIn('schedules.status', ['finished', 'cancelled'])
            ->leftJoin('providers', 'providers.id', '=', 'schedules.provider_id')
            ->leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
            ->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
            ->select($selectFields)
            ->orderBy('schedules.date', 'desc')
            ->orderBy('schedules.start_time', 'desc')
            ->get();

        $providerPhotos = Provider::query()
            ->select('id', 'profile_media_id')
            ->with('profileMedia')
            ->whereIn(
                'id',
                $upcomingSchedules->pluck('provider_id')
                    ->merge($completedSchedules->pluck('provider_id'))
                    ->filter()
                    ->unique(),
            )
            ->get()
            ->mapWithKeys(fn (Provider $provider) => [
                $provider->id => $provider->profileMedia?->path,
            ]);

        $signPhoto = fn ($item) => tap($item, function ($i) use ($providerPhotos) {
            $i->gender_label = GenderEnum::labelFor($i->gender);

            $path = $providerPhotos->get($i->provider_id);

            $i->provider_photo = $path
                ? Storage::temporaryUrl($path, now()->addMinutes(60))
                : null;
        });

        $upcomingSchedules->transform($signPhoto);

        $completedSchedules->transform($signPhoto);

        return [
            'upcomingSchedules'  => $upcomingSchedules,
            'completedSchedules' => $completedSchedules,
        ];
    }
}
