<?php

namespace Modules\Linksehat\Http\Controllers\Api;

use App\Helpers\Helper;
use App\Models\Organization;
use App\Models\Practitioner;
use App\Models\PractitionerRole;
use Carbon\Carbon;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Modules\Linksehat\Transformers\Doctor\DoctorResourceDetail;
use Modules\Linksehat\Transformers\PractitionerRoleToDoctorResource;

class DoctorController extends Controller
{
    /**
     * Display a listing of the resource.
     * @return Renderable
     */
    public function index(Request $request)
    {
        $doctors = PractitionerRole::query()
            ->with([
                'practitioner.person', 'speciality', 'practitioner.metas', 'metas',
                'organization' => function ($query) use ($request) {
                    if ($request->has('lat') && !empty($request->lat) && $request->has('lng') && !empty($request->lng)) {
                        return $query->leftJoin('addresses', function ($q) {
                            $q->on('organizations.main_address_id', '=', 'addresses.id');
                            $q->where('addresses.addressable_type', '=', Organization::class);
                        })
                            ->select([
                                "organizations.*",
                                "addresses.lat",
                                "addresses.lng",
                                // DB::raw("ST_Distance_Sphere(point(addresses.lng,addresses.lat), point(".$request->lng.",".$request->lat.")) /1000 as distance_km"),
                                DB::raw("6371 * acos (cos ( radians($request->lat) ) * cos( radians( addresses.lat ) ) * cos( radians( addresses.lng ) - radians($request->lng) ) + sin ( radians($request->lat) ) * sin( radians( addresses.lat ) )) as distance_km")
                            ]);
                    }
                },
            ])
            ->when($request->search ?? null, function ($query, $search) {
                $query->whereHas('practitioner.person', function ($person) use ($search) {
                    $person->where('name', 'LIKE', '%' . $search . '%');
                });
            });

        if ($request->has('speciality_id_in')) {
            $speciality_ids = explode(',', $request->speciality_id_in);
            $doctors->whereIn('speciality_id', $speciality_ids);
        } else if ($request->has('speciality_id')) {
            $doctors->where('speciality_id', $request->speciality_id);
        }
        
        if ($request->has('hospital_id_in')) {
            $hospital_ids = explode(',', $request->hospital_id_in);
            $doctors->whereIn('organization_id', $hospital_ids);
        } else if ($request->has('hospital_id')) {
            $doctors->where('organization_id', $request->hospital_id);
        }

        $limit = $request->limit ?? 6;
        if ($limit > 20) {
            $limit = 20;
        }

        $doctors = $doctors->paginate($limit);

        return Helper::responseJson(['doctors' => Helper::paginateResources(PractitionerRoleToDoctorResource::collection($doctors))]);
    }

    /**
     * Show the form for creating a new resource.
     * @return Renderable
     */
    public function create()
    {
        return view('linksehat::create');
    }

    /**
     * Store a newly created resource in storage.
     * @param Request $request
     * @return Renderable
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Show the specified resource.
     * @param int $id
     * @return Renderable
     */
    public function show(Request $request, $id)
    {
        $doctor = Practitioner::query()
            ->with([
                'practitionerRoles',
                'practitionerRoles.metas',
                'practitionerRoles.speciality',
                'practitionerRoles.organization' => function ($query) {
                    $query->leftJoin('addresses', function ($q) {
                        $q->on('organizations.main_address_id', '=', 'addresses.id');
                        $q->where('addresses.addressable_type', Organization::class);
                    });
                },
                'practitionerRoles.practices.prices',
                'practitionerRoles.availabilities',
                'person',
                'metas',
            ])
            ->findOrFail($id);

        return Helper::responseJson(DoctorResourceDetail::make($doctor));
    }

    /**
     * Show the form for editing the specified resource.
     * @param int $id
     * @return Renderable
     */
    public function edit($id)
    {
        return view('linksehat::edit');
    }

    /**
     * Update the specified resource in storage.
     * @param Request $request
     * @param int $id
     * @return Renderable
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     * @param int $id
     * @return Renderable
     */
    public function destroy($id)
    {
        //
    }

    public function schedule(Request $request, $id)
    {
        $request->validate([
            'speciality_id' => 'required',
            'type' => 'required',
            'hospital_id' => 'required_if:type,walkin',
            'start_date' => ['required', 'date']
        ]);
        
        $schedules = [
            'Senin' => [],
            'Selasa' => [],
            'Rabu' => [],
            'Kamis' => [],
            'Jumat' => [],
            'Sabtu' => [],
            'Minggu' => []
        ];

        if ($request->type == 'walkin') {

            $practitionerRole = PractitionerRole::query()
                ->where('practitioner_id', $id)
                ->where('organization_id', $request->hospital_id)
                ->where('speciality_id', $request->speciality_id)
                ->with(['availabilities', 'availabilities.days'])
                ->first();

            if ($practitionerRole) {


                $practitionerRole->availabilities->sortBy('start_time')
                    ->each(function ($availability) use (&$schedules) {
                        $availability_days = $availability->days->pluck('day')->toArray();

                        foreach ($schedules as $day => $schedule) {

                            if (!count($availability->days) || in_array($day, $availability_days)) {

                                if (Carbon::parse($availability->start_time) < Carbon::parse("10:00")) {
                                    $schedules[$day]['Pagi'][] = [
                                        "start" => $availability->start_time,
                                        'end' => $availability->end_time
                                    ];
                                }

                                else if (Carbon::parse($availability->start_time) < Carbon::parse("15:00")) {
                                    $schedules[$day]['Siang'][] = [
                                        "start" => $availability->start_time,
                                        'end' => $availability->end_time
                                    ];
                                }

                                else {
                                    $schedules[$day]['Malam'][] = [
                                        "start" => $availability->start_time,
                                        'end' => $availability->end_time
                                    ];
                                }

                            }

                        }

                    });
            }
        } else if ($request->type == 'chat' || $request->type == 'video') {

            $practitioner = Practitioner::query()
                ->with([
                    'practitionerRoles' => function ($practitionerRole) use ($request) {
                        if (!empty($request->hospital_id)) {
                            $practitionerRole->where('organization_id', $request->hospital_id);
                        }
                    },
                    'practitionerRoles.availabilities',
                    'practitionerRoles.availabilities.days'
                ])
                ->where('id', $id)
                ->first();

            foreach ($practitioner->practitionerRoles as $role) {

                $role->availabilities->sortBy('start_time')
                    ->each(function ($availability) use (&$schedules) {
                        $availability_days = $availability->days->pluck('day')->toArray();

                        foreach ($schedules as $day => $schedule) {

                            if (!count($availability->days) || in_array($day, $availability_days)) {

                                if (Carbon::parse($availability->start_time) < Carbon::parse("10:00")) {
                                    $schedules[$day]['Pagi'][] = [
                                        "start" => $availability->start_time,
                                        'end' => $availability->end_time
                                    ];
                                }

                                else if (Carbon::parse($availability->start_time) < Carbon::parse("15:00")) {
                                    $schedules[$day]['Siang'][] = [
                                        "start" => $availability->start_time,
                                        'end' => $availability->end_time
                                    ];
                                }

                                else {
                                    $schedules[$day]['Malam'][] = [
                                        "start" => $availability->start_time,
                                        'end' => $availability->end_time
                                    ];
                                }

                            }

                        }

                    });
                
                    continue; // TODO Fix This
            }
        }


        $datesAvailabilities = Helper::dailyAvailabilitiesToDate($schedules, $request->start_date, $request->end_date ?? null);

        return Helper::responseJson(data: $datesAvailabilities);

        return response()->json([
            'message' => 'Jadwal praktek dokter tidak ditemukan'
        ], 404);
    }
}
