<?php

namespace App\Http\Controllers\Api\OLDLMS;

use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Resources\OLDLMS\MemberResource;
use App\Models\Corporate;
use App\Models\Member;
use App\Models\OLDLMS\User;
use App\Rules\NikRule;
use App\Services\ClaimService;
use Illuminate\Http\Request;

class MembershipController extends Controller
{
    //
    public function check(Request $request)
    {
        $request->validate([
            'member_id' => 'required',
            // 'birth_date' => 'required',
        ]);

        $member = Member::where('member_id', $request->member_id)->first();

        if (!$member) {
            return Helper::responseJson(statusCode: 404, message: 'Member not found.', status: 'error');
        }

        if (!$member->active) {
            return Helper::responseJson(statusCode: 406, message: 'The Member ' . $request->member_id . ' is Inactive.', status: 'error');
        }

        return Helper::responseJson(data: $member, message: 'Member Found');
    }

    public function checkLimit(Request $request)
    {
        $request->validate([
            'member_id' => 'required',
            'type' => 'required|in:consultation,teleconsultation,medicine',
            // 'speciality_code' => 'sometimes'
        ]);

        $member = Member::query()
            ->where('member_id', $request->member_id)
            ->with(['currentCorporate', 'currentPolicy', 'currentPlan', 'postponedClaims'])
            ->first();

        $corporateService = $member->currentCorporate->corporateServices()
            ->active()
            ->where('service_code', 'OP')
            ->with([
                'configs',
                'specialities' => function ($speciality) use ($request) {
                    $speciality->where('code', $request->speciality_code ?? null)
                        ->wherePivot('active', 1);
                }
            ])
            ->first();

        $currentSpeciality = $corporateService->specialities->first();

        if ($currentSpeciality) {
            $corporateService->load([
                'corporateServiceSpecialities' => function ($corporateServiceSpeciality) use ($currentSpeciality) {
                    $corporateServiceSpeciality->where('speciality_id', $currentSpeciality->id);
                },
                'corporateServiceSpecialities.exclusions' => function ($exclusion) {
                    $exclusion->where('service_code', 'OP');
                },
                'corporateServiceSpecialities.exclusions.rules'
            ]);
        }

        $corporateServiceSpeciality = $corporateService->corporateServiceSpecialities->first() ?? null;

        $serviceSpecialityRules = $corporateServiceSpeciality?->exclusions->first()->rules ?? collect([]);
        $serviceSpecialityRules = $serviceSpecialityRules->mapWithKeys(function ($rule) {
            return [$rule->name => $rule];
        });

        $configs = $corporateService->configs->mapWithKeys(function ($config) {
            return [$config->name => $config];
        });

        $gpSpecialityName = config('aso.general_practitioner_speciality_name', 'Umum');
        $isGp = $gpSpecialityName == ($currentSpeciality ? $currentSpeciality->name : false);

        if ($request->type == 'medicine') {
            $benefitCode = 'OPMEDI1';
        } else if ($isGp) {
            $benefitCode = 'OPCONS1';
        } else {
            $benefitCode = 'OPCONS2';
        }

        $limits = ClaimService::showMemberBenefitLimit($member, $benefitCode);
        $limits['postponed_claims'] = $member->postponedClaims;
        $limits['postponed_claims_payment_url'] = route('postpone-pay', $member->member_id);
        $limits['postponed_claims_unpaid_total'] = $member->postponedClaims->sum('total_claim');

        $coverage['medicine_benefit'] = false;
        if ($benefitCode = 'OPMEDI1') {
            $medicineBenefit = $member->currentPlan->benefits()->where('code', $benefitCode)->wherePivot('active', 1)->first();
            $coverage['medicine_benefit'] = !empty($medicineBenefit);
        }
        $coverage['medicine_delivery_fee'] = (($configs['delivery_fee']['value'] ?? 1) == 1);

        if ($currentSpeciality) {
            $xCoverage['sp_consultation_benefit'] = (($configs['sp_internal_doctor_offline']['value'] ?? 1) == 1);
            $xCoverage['sp_teleconsultation_benefit'] = (($configs['sp_internal_doctor_online']['value'] ?? 1) == 1);
            $xCoverage['gp_consultation_benefit'] = (($configs['gp_internal_doctor_offline']['value'] ?? 1) == 1);
            $xCoverage['gp_teleconsultation_benefit'] = (($configs['gp_internal_doctor_online']['value'] ?? 1) == 1);
            $coverage['consultation_benefit'] = ($isGp)
                ? $xCoverage['gp_consultation_benefit']
                : $xCoverage['sp_consultation_benefit'];
            $coverage['teleconsultation_benefit'] = ($isGp)
                ? $xCoverage['gp_teleconsultation_benefit']
                : $xCoverage['sp_teleconsultation_benefit'];

            $xCoverage['sp_admin_fee'] = (($configs['specialist_practitioner_fee']['value'] ?? 1) == 1);
            $xCoverage['gp_admin_fee'] = (($configs['general_practitioner_fee']['value'] ?? 1) == 1);
            $coverage['admin_fee'] = ($isGp)
                ? $xCoverage['gp_admin_fee']
                : $xCoverage['sp_admin_fee'];
        } else {
            // Not Supported
            $coverage['consultation_benefit'] = false;
            $coverage['teleconsultation_benefit'] = false;
            $coverage['admin_fee'] = false;
        }

        $limits['coverage'] = $coverage;

        // TODO THIS EXCLUSION IS USED AS INCLUSION NOW, MUST BE CHANGE TO USED AS EXCLUSION AND MAYBE MOVE THE TABLE
        $excluded = [];
        foreach ($serviceSpecialityRules as $ruleName => $rule) {
            if ($ruleName == 'msc') {
                $values = explode(',', $rule->values);
                if (!in_array(strtolower($member->marital_status), $values)) {
                    $excluded[] = $rule;
                }
            }

            if ($ruleName == 'gender') {
                $values = explode(',', $rule->values);
                if (!in_array(strtolower($member->gender), $values)) {
                    $excluded[] = $rule;
                }
            }

            if ($ruleName == 'min_age') {
                if (!empty($rule->values) && $member->age < $rule->values) {
                    $excluded[] = $rule;
                }
            }

            if ($ruleName == 'max_age') {
                if (!empty($rule->values) && $member->age > $rule->values) {
                    $excluded[] = $rule;
                }
            }

            if ($ruleName == 'plan') {
                $values = explode(',', $rule->values);
                if (!in_array($member->currentPlan->code, $values)) {
                    $excluded[] = $rule;
                }
            }
        }

        return Helper::responseJson(data: $limits);
    }

    public function linkingRules(Request $request)
    {
        $corporates = Corporate::query()
            ->when($request->search, function ($q, $search) {
                $q->where('name', 'LIKE', '%'.$search.'%');
            })
            ->get();

        return Helper::responseJson(data: $corporates);
    }

    public function linkingValidate(Request $request)
    {
        $request->validate([
            'corporate_id' => 'required'
        ]);

        $corporate = Corporate::findOrFail($request->corporate_id);     
        // Make Validation from Linking Rules
        $linkingRulesArr = $corporate->linking_rules->toArray();
        $validationRules = [];
        foreach ($linkingRulesArr as $field) {
            $rules = ['required']; // Default is required if in the linking_rules
            if ($field == 'email') {
                $rules[] = 'email';
            }

            if ($field == 'nric') {
                $rules[] = new NikRule;
            }

            $validationRules[$field] = $rules;
        }
        $request->validate($validationRules);

        $member = Member::query()
            ->when(in_array('nric', $linkingRulesArr), function($q) use ($request) {
                $q->where('nric', $request->nric);
            })
            ->when(in_array('member_id', $linkingRulesArr), function($q) use ($request) {
                $q->where('member_id', $request->member_id);
            })
            ->when(in_array('name', $linkingRulesArr), function($q) use ($request) {
                $q->where('name', $request->name);
            })
            ->when(in_array('dob', $linkingRulesArr), function($q) use ($request) {
                $q->where('birth_date', $request->dob);
            })
            ->when(in_array('phone', $linkingRulesArr), function($q) use ($request) {
                $q->whereHas('person', function ($person) use ($request) {
                    $person->where('phone', $request->phone);
                });
            })
            ->when(in_array('email', $linkingRulesArr), function($q) use ($request) {
                $q->where('email', $request->email);
            })
            ->when(in_array('nik', $linkingRulesArr), function($q) use ($request) {
                $q->whereHas('employeds', function ($employed) use ($request) {
                    $employed->where('corporate_id', $request->corporate_id)
                        ->where('nik', $request->nik);
                });
            })

            ->with([
                'memberPlans' => function ($memberPlan) {
                    $memberPlan->latest();
                },
            ])

            ->first();
        if ($member) {
            $message = $member->currentPolicy->corporate->welcome_message;
            return Helper::responseJson(data: MemberResource::make($member), message: $message);
        }

        return Helper::responseJson(data: [], message: 'Member Tidak ditemukan', statusCode: 404, status: 'error');
    }

    public function show($member_id)
    {
        $member = Member::where('member_id', $member_id)->firstOrFail();
        $member->load(['currentPlan', 'memberPlans']);
        $member->totalUsage = ClaimService::getMemberTotalUsage($member);

        return Helper::responseJson(data: MemberResource::make($member));
    }

    public function automaticLinking(Request $request)
    {
        $member = Member::query()
        ->when(in_array('email', $linkingRulesArr), function($q) use ($request) {
            $q->where('email', $request->email);
        })
        ->with([
            'memberPlans' => function ($memberPlan) {
                $memberPlan->latest();
            },
        ])

        ->first();

        if ($member) {
            $message = $member->currentPolicy->corporate->welcome_message;
            return Helper::responseJson(data: MemberResource::make($member), message: $message);
        }

    }

    public function removeInsurance($email)
    {
        $user = User::where('sEmail', $email)->firstOrFail();

        if ($user) {
            echo 'Found User<br>';
            echo 'Deleting Insurance<br>';
        }

        if ($user->insurances()->delete()) {
            echo 'Insurance Deleted';
        } else {
            echo 'Failed Deleting Insurances';
        }
    }
}
