<?php

namespace Database\Seeders;

use App\Models\Address;
use App\Models\Meta;
use App\Models\Organization;
use App\Models\Person;
use App\Models\Practitioner;
use App\Models\PractitionerRole;
use App\Models\Speciality;
use App\Services\DoctorService;
use App\Services\PrimayaApi;
use Exception;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Http;
use Termwind\Components\Dd;

class PractitionerSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // Person::truncate();
        // Practitioner::truncate();
        // PractitionerRole::truncate();
        // Meta::query()->where('metaable_type', Practitioner::class)->forceDelete();
        // Meta::query()->where('metaable_type', PractitionerRole::class)->forceDelete();
        // Address::query()->where('addressable_type', Person::class)->forceDelete();

        $mapSpecialities = [
            'Akupunktur' => 'SP027',
            'Anak' => 'SP001',
            'Andrologi' => 'SP029',
            'Anastesia' => 'SP015',
            'Bedah Anak' => '',
            'Bedah Digestif' => '',
            'Bedah Mulut' => '',
            'Bedah Onkologi' => '',
            'Bedah Orthopedi' => 'SP007',
            'Bedah Plastik & Rekonstruksi' => 'SP005',
            'Bedah Saraf' => '',
            'Bedah Thorak & Kardiovaskuler' => '',
            'Bedah Umum' => 'SP004',
            'Bedah Vaskuler' => '',
            'Dokter Gigi' => 'SP026',
            'Fisik & Rehabilitasi' => 'SP014',
            'Gastroenterologi Hepatologi' => '',
            'Ginjal Hipertensi' => '',
            'Gizi Klinik' => 'SP019',
            'Hematologi Onkologi' => '',
            'Jantung & Pembuluh Darah' => 'SP008',
            'Kardio Vaskuler' => '',
            'Kebidanan & Kandungan' => 'SP003',
            'Kesehatan Jiwa' => 'SP018',
            'Kulit & Kelamin' => 'SP013',
            'Laboratorium' => '',
            'Mata' => 'SP011',
            'Okupasi' => 'SP016',
            'Paru' => 'SP009',
            'Patologi Klinik' => 'SP021',
            'Penyakit Dalam' => 'SP002',
            'Psikologi' => 'SP042',
            'Radiologi' => 'SP020',
            'Rehabilitasi Medik' => 'SP039',
            'Rheumatologi' => '',
            'Saraf' => 'SP012',
            'THT' => 'SP010',
            'Umum' => 'SP025',
            'Urologi' => 'SP006',
            'Lain-Lain' => '',
        ];

        $organizations = Organization::query()
            ->whereHas('metas', function ($meta) {
                $meta->where('type', 'KodeRS');
            })
            ->where('type', 'hospital')
            ->with('metas')
            ->get();

        foreach ($organizations as $organization) {
            $hisOrganizationCode =  $organization->meta->KodeRS ?? null;

            if (empty($hisOrganizationCode)) {
                $this->command->warn('NO ORGANIZATION CODE' . $organization->name);
                continue;
            }
            $primayaApiService = new PrimayaApi($hisOrganizationCode);

            $this->command->info('Getting RS ' . $hisOrganizationCode . '-' . $organization->name . ' PractitionerRole');

            try {
                $doctors = $primayaApiService->doctors();
                $this->processDoctors($doctors, $mapSpecialities, $organization);
            } catch (Exception $e) {
                $this->command->warn('Something Went Wrong :' . $hisOrganizationCode . ' - ' . $organization->name . ' - ' . $e->getMessage());
            }
        }
    }

    protected function processDoctors($doctors, $mapSpecialities, $organization)
    {
        foreach ($doctors['data'] as $doctor) {

            $DokterID = $doctor['DokterID'];

            // $practitionerRole = PractitionerRole::whereHas('metas', function ($meta) use ($DokterID) {
            //     $meta->where('type', 'DokterID')->where('value', $DokterID);
            // })->first();

            $SpesialisasiID = optional($doctor['spesialisasi'])['KodeSpesialisasiID'] ?? null;
            $mapping = array_search($SpesialisasiID, $mapSpecialities);
            if ($mapping == false) {
                $this->command->warn('Skip Doctor : ' . $DokterID . '-' . $doctor['Nama'] . ' (Tidak Punya Spesialisasi)');
                continue;
            }
            $findSpecialityId = Speciality::where('name', $mapping)->first()->id;

            $newPerson = Person::updateOrCreate([
                'name' => $doctor['Nama'],
            ], [
                'nik' => (!empty($doctor['NIK'])) ? $doctor['NIK'] : null,
                'name' => $doctor['Nama'],
                'birth_date' => (!empty($doctor['TanggalLahir']) && $doctor['TanggalLahir'] != '0000-00-00') ? $doctor['TanggalLahir'] : null,
                'gender' => !empty($doctor['Kelamin']) ? $doctor['Kelamin'] : null,
                'phone' => (!empty($doctor['Ponsel']) && $doctor['Ponsel'] != '-') ? $doctor['Ponsel'] : null,
                'email' => (!empty($doctor['Email']) && $doctor['Email'] != '-') ? $doctor['Email'] : null,
                'birth_place' => (!empty($doctor['TempatLahir']) && $doctor['TempatLahir'] != '-') ? $doctor['TempatLahir'] : null,
            ]);

            // $newPerson = Person::create([
            //     'name' => $doctor['Nama'],
            //     'birth_date' => (!empty($doctor['TanggalLahir']) && $doctor['TanggalLahir'] != '0000-00-00') ? $doctor['TanggalLahir'] : null,
            //     'gender' => !empty($doctor['Kelamin']) ? $doctor['Kelamin'] : null,
            // ]);

            $newAddress = $newPerson->addresses()->updateOrCreate([
                'use' => 'both',
                'type' => 'physical',
                'text' => (!empty($doctor['Alamat']) && $doctor['Alamat'] != '-') ? $doctor['Alamat'] : null,
            ]);

            $newPerson->main_address_id = $newAddress->id;
            $newPerson->save();

            $newPractitioner = Practitioner::updateOrCreate([
                'person_id' => $newPerson->id
            ], [
                'person_id' => $newPerson->id
            ]);


            $newPractitioner->metas()->updateOrCreate([
                'system' => 'primaya-his',
                'type' => 'education',
                'value' => (!empty($doctor['ProfilePendidikan']) && $doctor['ProfilePendidikan'] != '-') ? $doctor['ProfilePendidikan'] : null
            ]);
            $newPractitioner->metas()->updateOrCreate([
                'system' => 'primaya-his',
                'type' => 'award',
                'value' => (!empty($doctor['ProfileAward']) && $doctor['ProfileAward'] != '-') ? $doctor['ProfileAward'] : null
            ]);
            $newPractitioner->metas()->updateOrCreate([
                'system' => 'primaya-his',
                'type' => 'work_experience',
                'value' => (!empty($doctor['ProfilePengalamanKerja']) && $doctor['ProfilePengalamanKerja'] != '-') ? $doctor['ProfilePengalamanKerja'] : null
            ]);
            $newPractitioner->metas()->updateOrCreate([
                'system' => 'primaya-his',
                'type' => 'alias',
                'value' => (!empty($doctor['Sapaan']) && $doctor['Sapaan'] != '-') ? $doctor['Sapaan'] : null
            ]);
            $newPractitioner->metas()->updateOrCreate([
                'system' => 'primaya-his',
                'type' => 'Keilmuan',
                'value' => (!empty($doctor['Keilmuan']) && $doctor['Keilmuan'] != '-') ? $doctor['Keilmuan'] : null
            ]);

            $newPractitioner->metas()->updateOrCreate([
                'system' => 'primaya-his',
                'type' => 'tipeDokter',
                'value' => (!empty($doctor['Tipe']) && $doctor['Tipe'] != '-') ? $doctor['Tipe'] : null
            ]);
            // $newPractitioner->metas()->create([
            //     'system' => 'primaya-his',
            //     'type' => 'description',
            //     'value' => $doctor['Description']
            // ]);

            $ownedDepartemenIDs = $newPractitioner->practitionerRoles->pluck('meta.DepartemenID');

            $DepartemenIDs = $doctor['departementIDs'];
            foreach ($DepartemenIDs as $DepartemenID) {
                $updatePractitionerRole = $newPractitioner->practitionerRoles->where('meta.DepartemenID', $DepartemenID)->first();


                if (empty($updatePractitionerRole)) {
                    $updatePractitionerRole = $newPractitioner->practitionerRoles->where('meta.DokterID', $DokterID)->first();

                    if (!empty($updatePractitionerRole->meta->DepartemenID) && $updatePractitionerRole->meta->DepartemenID != $DepartemenID) {
                        $updatePractitionerRole = null;
                    }
                }

                if (
                    isset($updatePractitionerRole)
                ) {

                    $updatePractitionerRole->metas()->updateOrCreate([
                        'type' => 'DepartemenID',
                    ], [
                        'type' => 'DepartemenID',
                        'system' => 'his',
                        'value' => $DepartemenID
                    ]);

                    $newPractitioner->load('practitionerRoles');
                    $this->command->info('Updating Practitioner Role : ' . $updatePractitionerRole->id . '-' . $DokterID . '-' . $doctor['Nama'] . '-' . $DepartemenID);
                } else {

                    $newPractitionerRole = PractitionerRole::Create([
                        'practitioner_id' => $newPractitioner->id,
                        'organization_id' => $organization->id,
                        'speciality_id' => $findSpecialityId,
                        'active' => 1,
                    ]);

                    if (empty($newPractitionerRole->speciality_id)) {
                        $newPractitionerRole->metas()->updateOrCreate([
                            'type' => 'speciality_code',
                        ], [
                            'system' => 'primaya-his',
                            'type' => 'speciality_code',
                            'value' => (!empty($doctor['KodeSpesialisasiID']) && $doctor['KodeSpesialisasiID'] != '-') ? $doctor['KodeSpesialisasiID'] : null
                        ]);

                        $newPractitionerRole->metas()->updateOrCreate([
                            'type' => 'speciality',
                        ], [
                            'system' => 'primaya-his',
                            'type' => 'speciality',
                            'value' => (!empty($doctor['spesialisasi']['Nama']) && $doctor['spesialisasi']['Nama'] != '-') ? $doctor['spesialisasi']['Nama'] : null
                        ]);
                    }

                    $newPractitionerRole->metas()->updateOrCreate([
                        'type' => 'primaya-his',
                        'type' => 'DokterID',
                    ], [
                        'system' => 'primaya-his',
                        'type' => 'DokterID',
                        'value' =>  $DokterID
                    ]);

                    $newPractitionerRole->metas()->updateOrCreate([
                        'type' => 'primaya-his',
                        'type' => 'DepartemenID',
                    ], [
                        'system' => 'primaya-his',
                        'type' => 'DepartemenID',
                        'value' =>  $DepartemenID
                    ]);

                    $this->command->info('Creating Practitioner Role : ' . $newPractitionerRole->id . '-' . $DokterID . '-' . $doctor['Nama'] . '-' . $DepartemenID);
                }
            }
        }

        $hisOrganizationCode = $organization->meta->KodeRS  ?? null;
        // Recursive
        if ($doctors['current_page'] < $doctors['last_page']) {
            try {
                $primayaApiService = new PrimayaApi($hisOrganizationCode);

                $this->processDoctors($primayaApiService->doctors($doctors['current_page'] + 1), $mapSpecialities, $organization);
            } catch (Exception $e) {
                $this->command->info('Something Went Wrong :' . $hisOrganizationCode . ' - ' . $organization->name . ' - ' . $e->getMessage());
            }
        }
    }
}
