<?php

namespace App\Http\Controllers\Inquiry;

use App\Http\Actions\GetSupportedPriceIdsAction;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Inquiry\GetSupportedPlansRequest;
use App\Http\Resources\Inquiry\CompanyTranslationResource;
use App\Http\Resources\Inquiry\DeductibleTranslationResource;
use App\Http\Resources\Inquiry\PlanTranslationResource;
use App\Http\Resources\Inquiry\PriceResource;
use App\Models\CompanyTranslation;
use App\Models\DeductibleTranslation;
use App\Models\Language;
use App\Models\PlanTranslation;
use App\Models\Price;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Carbon;
use Throwable;

/**
 * @OA\Get(
 *   path="/api/inquiry",
 *   tags={"Inquiry"},
 *   summary="Get Supported Plans",
 *   operationId="inquiry_plans",
 *   security={{"auth":{}}},
 *
 *   @OA\Parameter(name="Accept-Language", in="header", description="Accept-Language", required=true, example="en", @OA\Schema(type="string")),
 *   @OA\Parameter(name="API-Key", in="header", description="API-Key", required=true, example="", @OA\Schema(type="string")),
 *   @OA\Parameter(name="insurance_cover", in="query", description="Insurance Cover", required=true, example="", @OA\Schema(type="string")),
 *   @OA\Parameter(name="is_entry", in="query", description="Is Entry (0|1)", required=true, example="", @OA\Schema(type="integer")),
 *   @OA\Parameter(name="birthdays", in="query", description="Birthdays YYYY-MM-DD (CSV)", required=true, example="", @OA\Schema(type="string")),
 *   @OA\Parameter(name="start_at", in="query", description="Start At YYYY-MM-DD", required=true, example="", @OA\Schema(type="string")),
 *   @OA\Parameter(name="end_at", in="query", description="End At YYYY-MM-DD", required=true, example="", @OA\Schema(type="string")),
 *
 *   @OA\Response(response=200, description="success")
 * )
 */
class GetSupportedPlansController extends ApiController
{
    public function __invoke(GetSupportedPlansRequest $request): JsonResponse
    {
        try {
            $data = $this->sanitize($request, [
                'birthdays'       => $request->validated('birthdays'),
                'end_at'          => $request->validated('end_at'),
                'insurance_cover' => $request->validated('insurance_cover'),
                'is_entry'        => $request->validated('is_entry'),
                'language'        => $request->validated('language'),
                'start_at'        => $request->validated('start_at'),
            ]);

            $priceIds = app(GetSupportedPriceIdsAction::class)->run(intval($data['is_entry']), intval($data['insurance_cover']), explode(',', $data['birthdays']));

            $languageId = Language::query()->where('code', $data['language'])->value('id');

            $days = ceil(abs((new Carbon($data['end_at']))->diffInDays(new Carbon($data['start_at'])))) + 1;

            $commulativeData = Price::query()
                ->select(['companies.id AS company_id', 'plans.id AS plan_id', 'prices.id AS price_id'])
                ->leftJoin('plans', 'prices.plan_id', '=', 'plans.id')
                ->leftJoin('companies', 'plans.company_id', '=', 'companies.id')
                ->whereIn('prices.id', $priceIds)
                ->where([
                    'prices.is_active'    => 1,
                    'plans.is_active'     => 1,
                    'companies.is_active' => 1,
                ])
                ->orderByRaw('companies.slug,plans.sort,plans.slug')
                ->get()
                ->toArray();
            $grouped = collect($commulativeData)->reduce(function ($carry, $item) {
                if (!isset($carry[$item['company_id']][$item['plan_id']])) {
                    $carry[$item['company_id']][$item['plan_id']] = [];
                }
                $carry[$item['company_id']][$item['plan_id']][] = $item['price_id'];
                return $carry;
            }, []);
            $result = [];
            foreach ($grouped as $companyId => $plans) {
                if ($companyTranslation = CompanyTranslation::query()->where([
                    'company_id'  => $companyId,
                    'language_id' => $languageId,
                    'is_active'   => 1,
                ])->first()) {
                    $deductibleTranslations = DeductibleTranslation::query()
                        ->select('deductible_translations.*')
                        ->leftJoin('deductibles', 'deductible_translations.deductible_id', '=', 'deductibles.id')
                        ->where([
                            'deductibles.company_id'              => $companyId,
                            'deductible_translations.language_id' => $languageId,
                            'deductible_translations.is_active'   => 1,
                            'deductibles.is_active'               => 1,
                        ])
                        ->get();
                    $companyRow = [
                        'company'     => new CompanyTranslationResource($companyTranslation),
                        'deductibles' => DeductibleTranslationResource::collection($deductibleTranslations)->toArray($request),
                        'plans'       => [],
                    ];
                    foreach ($plans as $planId => $prices) {
                        if ($planTranslation = PlanTranslation::query()->where([
                            'plan_id'     => $planId,
                            'language_id' => $languageId,
                            'is_active'   => 1,
                        ])->first()) {
                            $prices = Price::query()
                                ->whereIn('id', $prices)
                                ->where('is_active', 1)
                                ->get();
                            $planRow = [
                                'plan'   => new PlanTranslationResource($planTranslation),
                                'prices' => PriceResource::collection($prices)->toArray($request),
                            ];
                            foreach ($planRow['prices'] as &$price) {
                                $price['total'] = $price['daily_cost'] * $days;
                            }
                            $companyRow['plans'][] = $planRow;
                        }
                    }
                    $result[] = $companyRow;
                }
            }
            return $this->success($result);
        } catch (Throwable $e) {
            return $this->error($e->getMessage(), status: $e->getCode());
        }
    }
}
