<?php

namespace Mtc\Plugins\Clinic\Http\Controllers\Admin;

use AdminUser;
use App\Models\EventLog;
use App\Src\Encryption;
use Carbon\Carbon;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\DB;
use Mtc\Modules\Members\Classes\Auth;
use Mtc\Modules\Members\Classes\MemberManager;
use Mtc\Modules\Members\Models\Member;
use Mtc\Modules\Members\Models\MemberAttribute;
use Mtc\Plugins\NewsletterSignup\Classes\Newsletter;

class PatientController extends ClinicController
{
    /**
     * List of patients
     */
    public function index(Request $request)
    {
        $page_meta['title'] = config('app.name') . ' | Manage Patients';

        $adminuser = new AdminUser();

        $patients = Member::query()
            ->orderByDesc('id')
            ->with('addressBilling');

        $patients = self::filterPatients($patients, $request->all())
            ->get()
            ->map(function (Member $member) {
                $member->stats = Member::getMemberStats($member->id);
                $member->dob = $member->getDob();
                $member->age = $member->getAge();
                return $member;
            });

        return template('admin/patients/index.twig', [
            'page_meta' => $page_meta,
            'title' => 'Manage Patients',
            'patients' => $patients,
            'request' => $request->all(),
            'showNewsletterFilter' => Newsletter::isDefaultDriver(),
        ]);
    }

    /**
     * Export patients CSV
     */
    public function export(Request $request): string
    {
        header('Content-type: application/octet-stream');
        header('Content-Disposition: attachment; filename="patients.csv"');

        $patients = Member::query()
            ->with('addressBilling');

        $patients = self::filterPatients($patients, $request->all())
            ->orderByDesc('id')
            ->get()
            ->map(function (Member $member) {
                $member->stats = Member::getMemberStats($member->id);
                return $member;
            });

        $header_row = [
            'Patient ID',
            'Firstname',
            'Lastname',
            'Email',
            'Contact No',
            'Allergies',
            'Medications',
            'Medical Conditions',
            'Address 1',
            'Address 2',
            'City',
            'Country',
            'Postcode',
        ];

        $data = implode(',', $header_row) . "\n";

        foreach ($patients as $patient) {
            $medications = json_decode($patient->medications);
            $conditions = json_decode($patient->conditions);
            $dataRow = [
                $patient->id,
                $patient->addressBilling->firstname,
                $patient->addressBilling->lastname,
                $patient->email,
                $patient->contact_no,
                $patient->allergies,
                !empty($medications) ?
                    str_replace('"', '\'', implode(', ', $medications)) :
                    '',
                !empty($conditions) ?
                    str_replace('"', '\'', implode(', ', $conditions)) :
                    '',
                str_replace(',', ".", $patient->addressBilling->address1),
                str_replace(',', ".", $patient->addressBilling->address2),
                str_replace(',', ".", $patient->addressBilling->city),
                str_replace(',', ".", $patient->addressBilling->country),
                str_replace(',', ".", $patient->addressBilling->postcode),
            ];
            $data .= '"' . implode('","', $dataRow) . '"' . "\n";
        }
        return $data;
    }

    /**
     * Add a patients
     */
    public function add(Request $request): string
    {
        $title = 'Create a patient';
        $page_meta['title'] = config('app.name') . ' | ' . $title;

        return template('admin/patients/add.twig', [
            'page_meta' => $page_meta,
            'title' => $title,
            'request' => $request->all(),
        ]);
    }

    /**
     * Add a patients
     */
    public function profile($id, Request $request): string
    {
        /** @var Member $patient */
        $patient = Member::query()
            ->with('addressBilling')
            ->with('addressShipping')
            ->findOrFail($id);

        $title = $patient->addressBilling->firstname . ' ' . $patient->addressBilling->lastname;
        $page_meta['title'] = config('app.name') . ' | ' . $title;

        $patient->dob = $patient->getDob();
        $patient->age = $patient->getAge();

        $patient->weight = '-';
        $patient->bmi = '-';
        $patient->progress = [];

        $patient->doctor_surgery = !empty($patient->doctor_surgery) ?
            json_decode($patient->doctor_surgery) :
            null;

        $weightTrack = $patient->weightTrack()
            ->orderByDesc('date_provided')
            ->first();

        if (!empty($weightTrack)) {
            $patient->weight = $weightTrack->weight;
            $patient->bmi = $weightTrack->bmi;

            $firstWeightTrack = $patient->weightTrack()
                ->orderBy('date_provided')
                ->first();

            if (!empty($firstWeightTrack)) {
                $difference = $patient->weight - $firstWeightTrack->weight;
                $patient->progress = [
                    'reduction' => $difference,
                    'reduction_percent' => round($difference / $firstWeightTrack->weight * 100),
                ];
            }
        }

        return template('admin/patients/profile.twig', [
            'page_meta' => $page_meta,
            'title' => $title,
            'patient' => $patient,
            'attributes' => MemberAttribute::getFields(),
            'routes' => $this->patientRoutes($id),
            'request' => $request->all(),
        ]);
    }

    /**
     * Search patients
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function search(Request $request): JsonResponse
    {
        return response()
            ->json([
                'patients' => Member::searchMembers($request->input('query')),
                'success' => '1',
            ]);
    }

    /**
     * Login as member
     *
     * @param $id
     * @return Application|RedirectResponse|Redirector
     */
    public function loginAs($id): Redirector|RedirectResponse|Application
    {
        MemberManager::loginAsMember($id);
        return redirect(route('members-dashboard'));
    }

    /**
     * Apply filter
     *
     * @param Builder $query
     * @param array $filters
     * @return Builder
     */
    public static function filterPatients(Builder $query, array $filters): Builder
    {
        if (!empty($filters['id'])) {
            $query->where('id', $filters['id']);
        }

        if (!empty($filters['email'])) {
            $query->where('email_hash', Encryption::makeHash($filters['email']));
        }

        if (!empty($filters['newsletter'])) {

            if ($filters['newsletter'] === 'yes') {
                $query->whereExists(function ($query) {
                    $query->select(DB::raw(1))
                        ->from('emails_lists_mails')
                        ->whereRaw('emails_lists_mails.email = members.email');
                });
            }
            if ($filters['newsletter'] === 'no') {
                $query->whereNotExists(function ($query) {
                    $query->select(DB::raw(1))
                        ->from('emails_lists_mails')
                        ->whereRaw('emails_lists_mails.email = members.email');
                });
            }
        }

        if (!empty($filters['contact_no'])) {
            $query->where('contact_no_hash', Encryption::makeHash($filters['contact_no']));
        }

        if (!empty($filters['date_of_birth'])) {
            try {
                $date_of_birth = Carbon::createFromFormat('d/m/Y', $filters['date_of_birth']);
                $query->where('dob_hash', Encryption::makeHash($date_of_birth->format('Y-m-d')));
            } catch (Exception) {}
        }

        if (!empty($filters['firstname'])) {
            $query->whereHas('addresses', function (Builder $query) use ($filters) {
                $query->where('firstname_hash', Encryption::makeHash($filters['firstname']));
            });
        }

        if (!empty($filters['lastname'])) {
            $query->whereHas('addresses', function (Builder $query) use ($filters) {
                $query->where('lastname_hash', Encryption::makeHash($filters['lastname']));
            });
        }
        return $query;
    }

    /**
     * Get patient routes
     *
     * @param $id
     * @return array
     */
    protected function patientRoutes($id): array
    {
        return [
            'admin-member-attributes-load' => route('admin-member-attributes-load', [
                'id' => $id,
            ]),
            'admin-member-attributes-store' => route('admin-member-attributes-store', [
                'id' => $id,
            ]),
            'admin-member-notes-load' => route('admin-member-notes-load', [
                'id' => $id,
            ]),
            'admin-member-notes-store' => route('admin-member-notes-store', [
                'id' => $id,
            ]),
            'admin-member-notes-load-flags' => route('admin-member-notes-load-flags', [
                'id' => $id,
            ]),
            'admin-member-notes-delete-flag' => route('admin-member-notes-delete-flag', [
                'id' => $id,
            ]),
            'admin-member-notes-toggle-flag-status' => route('admin-member-notes-toggle-flag-status', [
                'id' => $id,
            ]),
            'admin-member-orders-load' => route('admin-member-orders-load', [
                'id' => $id,
            ]),
            'admin-reviews-load' => route('admin-reviews-load', [
                'member_id' => $id,
            ]),
            'admin-reviews-load-review' => route('admin-reviews-load-review'),
            'admin-member-orders-add' => '/plugins/BasketBuilder/admin/add.php?' . http_build_query([
                'member_id' => $id,
                ]),
            'admin-patient-treatments-load' => route('admin-patient-treatments-load', [
                'id' => $id,
            ]),
            'admin-patient-treatments-store' => route('admin-patient-treatments-store', [
                'id' => $id,
            ]),
            'admin-patient-treatments-delete' => route('admin-patient-treatments-delete', [
                'id' => $id,
            ]),
            'admin-products-search' => route('admin-products-search'),
            'admin-patient-bp-track-load' => route('admin-patient-bp-track-load', [
                'id' => $id,
            ]),
            'admin-patient-bp-track-store' => route('admin-patient-bp-track-store', [
                'id' => $id,
            ]),
            'admin-patient-bp-track-delete' => route('admin-patient-bp-track-delete', [
                'id' => $id,
            ]),
            'admin-patient-weight-track-load' => route('admin-patient-weight-track-load', [
                'id' => $id,
            ]),
            'admin-patient-weight-track-store' => route('admin-patient-weight-track-store', [
                'id' => $id,
            ]),
            'admin-patient-weight-track-delete' => route('admin-patient-weight-track-delete', [
                'id' => $id,
            ]),
            'admin-patient-files-load' => route('admin-patient-files-load', [
                'id' => $id,
            ]),
            'admin-patient-files-store' => route('admin-patient-files-store', [
                'id' => $id,
            ]),
            'admin-patient-files-delete' => route('admin-patient-files-delete', [
                'id' => $id,
            ]),
            'admin-patient-consultations-load' => route('admin-patient-consultations-load', [
                'id' => $id,
            ]),
            'admin-patient-messages-load' => route('admin-patient-messages-load', [
                'id' => $id,
            ]),
            'admin-patient-event-log-load' => route('admin-patient-event-log-load', [
                'id' => $id,
            ]),
            'admin-reviews-store' => route('admin-reviews-store'),
            'admin-patients-profile' => route('admin-patients-profile', [
                'id' => '---id---',
            ]),
            'edit-patient' => '/modules/Members/admin/manage_member.php?id=' . $id,
            'admin-patient-messages-create-thread' => '/plugins/MembersMessaging/admin/view_member_thread.php?act=request_info&member_id=' . $id,
        ];
    }
}
