<?php

namespace App\Http\Controllers\Api;

use App\Models\Timezone;
use App\Models\Currency;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use App\Http\Controllers\Controller;
use App\Models\LicenseAuthentication;
use App\Models\LicenseDetail;
use App\Models\LicenseRegistered;
use App\Models\PlanModuleMapping;
use App\Models\TestCareContext;
use App\Models\Account;
use App\Models\LabBillingReport;
use Symfony\Component\Process\Process;
use Illuminate\Pagination\Paginator;
use App\Models\SaleInvoice;

class ApiController extends Controller
{
	public function getTimezones(Request $request)
	{
		return response()->json([
			'error'   => 0,
			'message' => 'Timezones are retrived successfully.',
			'data'    => Timezone::all()
		]);
	}

	public function getCurrencies(Request $request)
	{
		return response()->json([
			'error'   => 0,
			'message' => 'Currencies are retrieved successfully.',
			'data'    => Currency::select(['id','currency', 'country_id'])->with('countries')->get()
		]);
	}

    public function licenseValidation(Request $request)
    {
        $license = LicenseRegistered::select('id')
            ->where(['license_key' => $request->license_key, 'license_secret' => $request->license_secret])
            ->first();

        if (!$license) {
            return response()->json([
                'success' => 0,
                'message' => 'License Authentication Failed. Please contact administrator.',
                'data'    => []
            ]);
        }

        $account = Account::select('name')
            ->find($license->bill_to_account_id);

        $plan_ids = LicenseDetail::select('plan_and_packages_id')
            ->where('order_id', $license->id)->get()
            ->pluck('plan_and_packages_id');

        $moduleCodes = PlanModuleMapping::select('module_code')->whereIn('plan_id', $plan_ids)->get();

        $moduleCodes = $moduleCodes->pluck('module_code')->mapWithKeys(function ($module) {
            return [$module => $module];
        })->toArray();

        return response()->json([
            'success'     => 1,
            'message'     => 'License Authentication Retrieved Successfully.',
            'permissions' => $moduleCodes,
            'client'      => $account->name ?? ''
		]);
    }

    public function metaMintAPI(Request $request)
    {
        switch ($request->type) {
            case 'get-account-list':
                $current_page = empty($request->page_no) ? 1 : $request->page_no;
                $limit        = empty($request->limit) ? 10 : $request->limit;
                $search_text  = empty($request->search_text) ? '' : $request->search_text;

                return $this->getAccountList($current_page,$limit,$search_text);

                break;

            case 'get-report-list-for-linking':
                $current_page = empty($request->page_no) ? 1 : $request->page_no;
                $limit        = empty($request->limit) ? 10 : $request->limit;
                $search_text  = empty($request->search_text) ? '' : $request->search_text;
                $from_date    = empty($request->from_date) ? '' : $request->from_date;
                $to_date      = empty($request->to_date) ? '' : $request->to_date;

                return $this->getReportListForLinking($current_page,$limit,$search_text,$from_date,$to_date);

                break;

            case 'get-test-invoice-data':
                $validator = \Validator::make($request->all(), [
                    'test_invoice_id' => 'required',
                ]);

                if ($validator->fails()) {
                    return response()->json([
                        'status_code' => 400,
                        'message'     => $validator->getMessageBag()->first(),
                    ]);
                }
                $test_invoice_id = empty($request->test_invoice_id) ? '' : $request->test_invoice_id;

                return $this->getTestInvoiceData($test_invoice_id);

                break;

            case 'save-test-care-context':
                $validator = \Validator::make($request->all(), [
                    'test_invoice_id'   => 'required',
                    'care_context_uuid' => 'required',
                ]);

                if ($validator->fails()) {
                    return response()->json([
                        'status_code' => 400,
                        'message'     => $validator->getMessageBag()->first(),
                    ]);
                }

                $test_invoice_id = empty($request->test_invoice_id) ? '' : $request->test_invoice_id;
                $care_context_uuid = empty($request->care_context_uuid) ? '' : $request->care_context_uuid;

                return $this->saveTestCareContext($test_invoice_id,$care_context_uuid);

                break;

            case 'save-account-abha-address':
                $validator = \Validator::make($request->all(), [
                    'account_code'           => 'required',
                    'abha_number'            => 'required',
                    'preferred_abha_address' => 'required',
                ]);

                if ($validator->fails()) {
                    return response()->json([
                        'status_code' => 400,
                        'message'     => $validator->getMessageBag()->first(),
                    ]);
                }

                $account_code           = empty($request->account_code) ? '' : $request->account_code;
                $abha_number            = empty($request->abha_number) ? '' : $request->abha_number;
                $preferred_abha_address = empty($request->preferred_abha_address) ? '' : $request->preferred_abha_address;

                return $this->saveAccountABHAAddress($account_code,$abha_number,$preferred_abha_address);

                break;

            default:
                return response()->json([
                    'status_code' => 400,
                    'message'     => 'Invalid api type!',
                ]);
                break;
        }
    }

    public function getAccountList($current_page = '', $limit = '', $search_text = '')
    {

        Paginator::currentPageResolver(function () use ($current_page) {
            return $current_page;
        });

        $results = Account::select([
                'accounts.id',
                'accounts.name as account_name',
                'accounts.print_name',
                'accounts.code as account_code',
                'account_contacts.phone_no as mobile_no',
                'account_contacts.email',
                'account_addresses.address_line1 as address_line1',
                'account_addresses.address_line2 as address_line2',
                'cities.name as city',
            ])
            ->leftjoin('account_contacts','account_contacts.account_id','accounts.id')
            ->leftjoin('account_addresses','account_addresses.account_id','accounts.id')
            ->leftjoin('cities', 'cities.id', 'account_addresses.city_id')
            ->when(!empty($search_text), function($query) use ($search_text) {
                $query->where(function($q) use ($search_text) {
                    $q->where('accounts.name', 'LIKE', '%'.$search_text . '%')
                        ->orWhere('account_contacts.phone_no', 'LIKE', '%'.$search_text . '%');
                });
            })
            ->whereNull('accounts.abha_no')
            ->where('accounts.status', '1')
            ->orderby('accounts.name', 'ASC')
            ->paginate($limit);

        if (empty($results)) {
            return response()->json([
                'status_code'   => 404,
                'message' => 'No Data Found',
            ]);
        }
        $results = $results->toArray();

        $total_records = $results['total'];
        $total_pages   = $total_records / $limit;
        $offset        = $limit * $results['current_page'] - $limit;

        return response()->json([
            'status_code'   => 200,
            'message'       => 'Account List',
            'current_page'  => $results['current_page'],
            'total_pages'   => ceil($total_pages),
            'total_records' => $total_records,
            'limit'         => $limit,
            'offset'        => $offset,
            'data'          => $results['data']
        ]);
    }

    public function saveTestCareContext($test_invoice_id = '', $care_context_uuid = '')
    {
        $data['test_invoice_id']   = empty($test_invoice_id) ? '' : $test_invoice_id;
        $data['care_context_uuid'] = empty($care_context_uuid) ? '' : $care_context_uuid;

        $created = TestCareContext::create($data);

        if (!$created) {
            return response()->json([
                'status_code'   => 400,
                'message'       => 'Problem in Care Context Entry.'
            ]);
        }

        return response()->json([
            'status_code'   => 200,
            'message'       => 'New Care Context Entry Successfully.'
        ]);
    }

    public function saveAccountABHAAddress($account_code = '', $abha_number = '', $preferred_abha_address = '')
    {
        $data['abha_no']      = empty($abha_number) ? '' : $abha_number;
        $data['abha_address'] = empty($preferred_abha_address) ? '' : $preferred_abha_address;

        $updated = Account::where('code', $account_code)->update($data);

        if (!$updated) {
            return response()->json([
                'status_code'   => 400,
                'message'       => 'Problem in ABHA Address Entry.'
            ]);
        }

        return response()->json([
            'status_code'   => 200,
            'message'       => 'ABHA Address Entry Successfully Done.'
        ]);
    }

    public function getReportListForLinking($current_page = '', $limit = '', $search_text = '', $from_date = '', $to_date = '')
    {
        Paginator::currentPageResolver(function () use ($current_page) {
            return $current_page;
        });

        $results = SaleInvoice::select([
                'sale_invoices.id as test_invoice_id',
                'sale_invoices.main_invoice_no as test_invoice_no',
                'sale_invoices.branch_invoice_no as test_invoice_no_branch',
                'sale_invoices.invoice_date as test_invoice_date',
                'sale_invoices.status as test_invoice_details_status',
                \DB::raw('DATE(sale_invoices.created_at) as test_invoice_entry_date'),
                \DB::raw('TIME(sale_invoices.created_at) as test_invoice_entry_time'),
                'sale_invoice_batches.sample_receive_date as test_sample_date',
                'sale_invoice_batches.sample_receive_time as test_sample_time',
                \DB::raw('DATE(sale_invoices.invoice_date) as test_report_date'),
                \DB::raw('TIME(sale_invoices.invoice_date) as test_report_time'),
                \DB::raw('MONTH(sale_invoices.invoice_date) as test_invoice_month'),
                \DB::raw('Year(sale_invoices.invoice_date) as test_invoice_year'),

                'accounts.name AS patient_name',
                'genders.name as ac_sex',
                'account_titles.name as patient_title',

                \DB::raw('TIMESTAMPDIFF(YEAR, account_contacts.date_of_birth, CURDATE()) as ac_age_years'),
                \DB::raw('TIMESTAMPDIFF(MONTH, account_contacts.date_of_birth, CURDATE()) % 12 as ac_age_months'),
                \DB::raw('TIMESTAMPDIFF(DAY, account_contacts.date_of_birth, CURDATE()) % 30 as ac_age_days'),
            ])
            ->leftjoin('sale_invoice_batches', 'sale_invoice_batches.invoice_id','sale_invoices.id')

            ->leftjoin('accounts','accounts.id','sale_invoices.patient_id')
            ->leftjoin('account_contacts','accounts.id','account_contacts.account_id')
            ->leftjoin('genders','genders.id','account_contacts.account_gender_id')
            ->leftjoin('account_titles','account_titles.id','accounts.account_title_id')

            ->when(!empty($search_text), function($query) use ($search_text) {
                $query->where(function($q) use ($search_text) {
                    $q->where('accounts.name', 'LIKE', '%'.$search_text . '%')
                        ->orWhere('sale_invoices.main_invoice_no', 'LIKE', '%'.$search_text . '%');
                });
            })
            ->when(!empty($from_date) && !empty($to_date), function($query) use ($from_date, $to_date) {
                $query->whereBetween('sale_invoices.invoice_date', [$from_date, $to_date]);
            })
            ->paginate($limit);

        if (empty($results)) {
            return response()->json([
                'status_code'   => 404,
                'message' => 'No Data Found',
            ]);
        }

        $results = $results->toArray();

        $total_records = $results['total'];
        $total_pages   = $total_records / $limit;
        $offset        = $limit * $results['current_page'] - $limit;

        return response()->json([
            'status_code'   => 200,
            'message'       => 'Report List',
            'current_page'  => $results['current_page'],
            'total_pages'   => ceil($total_pages),
            'total_records' => $total_records,
            'limit'         => $limit,
            'offset'        => $offset,
            'data'          => $results['data']
        ]);
    }

    public function getTestInvoiceData($test_invoice_id = '')
    {
        $results = SaleInvoice::select([
                'sale_invoices.id as test_invoice_id',
                'sale_invoices.main_invoice_no as test_invoice_no',
                'sale_invoices.branch_invoice_no as test_invoice_no_branch',
                'sale_invoices.invoice_date as test_invoice_date',
                'sale_invoices.status as test_invoice_details_status',
                \DB::raw('DATE(sale_invoices.created_at) as test_invoice_entry_date'),
                \DB::raw('TIME(sale_invoices.created_at) as test_invoice_entry_time'),
                'sale_invoice_batches.sample_receive_date as test_sample_date',
                'sale_invoice_batches.sample_receive_time as test_sample_time',
                \DB::raw('DATE(sale_invoices.invoice_date) as test_report_date'),
                \DB::raw('TIME(sale_invoices.invoice_date) as test_report_time'),
                \DB::raw('MONTH(sale_invoices.invoice_date) as test_invoice_month'),
                \DB::raw('Year(sale_invoices.invoice_date) as test_invoice_year'),

                'accounts.name AS patient_name',
                'genders.name as patient_gender',
                'accounts.abha_address as account_abha_addresses',
                'accounts.abha_no as abha_number',
                'accounts.abha_address as preferred_abha_address',
                'account_titles.name as patient_title',
                'account_contacts.date_of_birth as date_of_birth',
                'doctor.name AS doctor_name',
                'doctor_genders.name as doctor_gender',
                'account_licenses.license_number as practitioner_id',
                'companies.name as company_name',
                'companies.id as organization_id',
                'test_packages.name as test_package_name',
                'test_departments.name as test_profile_name',
            ])
            ->leftjoin('sale_invoice_batches', 'sale_invoice_batches.invoice_id','sale_invoices.id')
            ->leftjoin('sale_invoice_details', 'sale_invoice_details.sale_invoice_id','sale_invoices.id')
            ->leftjoin('products', 'sale_invoice_details.product_id','products.id')
            ->leftjoin('product_test_packages', 'product_test_packages.product_id','products.id')
            ->leftjoin('test_packages', 'product_test_packages.test_package_id','test_packages.id')
            ->leftjoin('test_departments', 'test_departments.id','test_packages.department_id')

            ->leftjoin('accounts','accounts.id','sale_invoices.patient_id')
            ->leftjoin('account_contacts','accounts.id','account_contacts.account_id')
            ->leftjoin('genders','genders.id','account_contacts.account_gender_id')
            ->leftjoin('account_titles','account_titles.id','accounts.account_title_id')


            ->leftjoin('accounts as doctor','doctor.id','sale_invoices.doctor_id')
            ->leftjoin('account_contacts as doctor_contact','doctor.id','doctor_contact.account_id')
            ->leftjoin('genders as doctor_genders','doctor_genders.id','doctor_contact.account_gender_id')
            ->leftjoin('account_licenses','account_licenses.account_id','doctor.id')

            ->leftjoin('companies','companies.id','sale_invoices.company_id')

            ->where('sale_invoices.id', $test_invoice_id)
            ->first();

        if (!$results) {
            return response()->json([
                'status_code'   => 404,
                'message' => 'No Data Found',
            ]);
        }

        $billing_report = LabBillingReport::select([
            'lab_billing_reports.result',
            'lab_report_result_big_texts.result as long_result',
            'test_items.name as test_item_name',
            'test_methods.name as test_item_method',
            'test_item_normal_ranges.low_value as low',
            'test_item_normal_ranges.high_value as high',
            'test_units.name as unit_measurement_name',
        ])
            ->leftjoin('lab_report_result_big_texts', 'lab_report_result_big_texts.lab_billing_report_id', 'lab_billing_reports.id')
            ->leftjoin('test_items', 'lab_billing_reports.test_item_id', 'test_items.id')
            ->leftjoin('test_methods', 'test_methods.id', 'test_items.test_method_id')
            ->leftjoin('test_item_normal_ranges', 'test_item_normal_ranges.test_item_id', 'test_items.id')
            ->leftjoin('test_units', 'test_units.id', 'test_items.primary_unit_id')
            ->where(['lab_billing_reports.sale_invoice_id' => $test_invoice_id])
            ->get();

        $observations = [];

        foreach ($billing_report as $observation) {
            $observations[] = [
                "observation_name"  => $observation['test_item_name'],
                "observation_value" => $observation['result'] ?? $observation['long_result'],
                "observation_unit"  => $observation['unit_measurement_name'],
                "ref_low"           => $observation['low'],
                "ref_high"          => $observation['high'],
            ];
        }

        $test_invoice_data = $results->toArray();

        $context_request_data = [
            'abhaNumber'  => $test_invoice_data['abha_number'],
            'abhaAddress' => $test_invoice_data['preferred_abha_address'],
            'name'        => $test_invoice_data['patient_name'],
            'gender'      => '',
            'yearOfBirth' => ''
        ];

        $context_data = [
            "patient" => [
                "name"       => $test_invoice_data['patient_name'],
                "patient_id" => "",
                "gender"     => strtolower($test_invoice_data['patient_gender'])
            ],
            "practitioner" => [
                "name"            => $test_invoice_data['doctor_name'],
                "practitioner_id" => $test_invoice_data['practitioner_id'],
                "gender"          => strtolower($test_invoice_data['doctor_gender'])
            ],
            "performer" => [
                "name"            => $test_invoice_data['company_name'],
                "organization_id" => $test_invoice_data['organization_id']
            ],
            "report_date" => $test_invoice_data['test_report_date'],
            "request"     => [
                "service_name" => $test_invoice_data['test_package_name'],
                "request_date" => $test_invoice_data['test_invoice_date']
            ],
            "report_name"  => $test_invoice_data['test_package_name']." Report",
            "report_title" => $test_invoice_data['test_profile_name'],
            "conclusion"   => "",
            "observations" => $observations
        ];

        $data = [
            'context_request_data' => $context_request_data,
            'context_data'         => $context_data
        ];

        return response()->json([
            'status_code'   => 200,
            'message'       => 'Context Data',
            'data'        => $data,
        ]);
    }
}
