<?php

namespace App\Http\Controllers\Admin\Api;

use App\Classes\Constant;
use App\Http\Controllers\Controller;
use App\Models\Appointment;
use App\Models\Cart;
use App\Models\Item;
use App\Models\ItemHistory;
use App\Models\LabkitOrderItem;
use App\Models\Patient;
use App\Models\PatientNote;
use App\Models\PatientPrescription;
use App\Models\Payment;
use App\Models\Permission;
use App\Models\Setting;
use App\Models\Subscription;
use Carbon\Carbon;
use Illuminate\Contracts\Routing\UrlGenerator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Yajra\DataTables\DataTables;
use Illuminate\Support\Facades\DB;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Support\Facades\Gate;

class OrderController extends Controller
{
    protected $url;
    protected $user;
    public function __construct(UrlGenerator $url)
    {
        $this->url = $url;
        $this->user = Auth::guard('admin')->user();
    }
    public function orderList(Request $request)
    {
        try {
            $this->authorizeForUser($this->user, 'view', new Cart);
            $fromDate = $request->get('from_date');
            $toDate = $request->get('to_date');
            $status = $request->get('status');
            $orderList = Cart::select(
                "appointments.*",
                'appointments.id as appointment_id',
                'carts.*',
                'carts.id as order_id',
                DB::raw("CONCAT(carts.first_name,' ',carts.last_name) as patient_name")
            )
                ->leftJoin('appointments', 'appointments.id', 'carts.appointment_id');


            if ($fromDate != "all") {
                $from_date = Carbon::createFromFormat('m-d-Y', $fromDate)->format('Y-m-d');
                $orderList->where('carts.created_at', ">=", $from_date . " 00:00:00");
            }
            if ($toDate != "all") {
                $to_date = Carbon::createFromFormat('m-d-Y', $toDate)->format('Y-m-d');
                $orderList->where('carts.created_at', "<=", $to_date . " 23:59:59");
            }
            if ($status != "all") {
                $orderList->where('carts.status', $status);
            }
            // dd(Constant::getFullSql($orderList));
            return Datatables::of($orderList)
                ->addColumn('order_total_amount', function ($order) {
                    $items = Item::where('cart_id', $order->id)->get();
                    return $items->sum(function ($item) {
                        return $item->quantity * $item->price;
                    });
                })
                ->addColumn('order_total_shipping', function ($order) {
                    $items = Item::where('cart_id', $order->id)->get();
                    return $items->sum('shipping_cost');
                })
                ->addColumn('appointment_status', function ($order) {
                    $appointment = Appointment::find($order->appointment_id);
                    return $appointment ? $appointment->status : 'null';
                })
                ->addColumn('total_items', function ($order) {
                    return Item::where('cart_id', $order->id)->sum('quantity');
                })
                ->addColumn('order_items', function ($order) {
                    $items = Item::with('plansV1')
                        ->where('cart_id', $order->id)
                        ->get()
                        ->map(function ($item) {
                            $planV1 = $item->plansV1;
                            if ($planV1) {
                                $planV1->qty = $item->quantity;
                                $planV1->status = $item->status;
                            }
                            return $planV1;
                        });
                    return $items;
                })
                ->make(true);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }
    public function orderListbyPatient(Patient $patient, Request $request)
    {

        $fromDate = $request->get('from_date');
        $toDate = $request->get('to_date');
        $orderList = Cart::where('carts.patient_id',  $patient->id);
        if ($fromDate != "") {
            $from_date = Carbon::createFromFormat('m-d-Y', $fromDate)->format('Y-m-d');
            $orderList->where('created_at', ">=", $from_date . " 00:00:00");
        }
        if ($toDate != "") {
            $to_date = Carbon::createFromFormat('m-d-Y', $toDate)->format('Y-m-d');
            $orderList->where('created_at', "<=", $to_date . " 23:59:59");
        }

        $orderListData = $orderList->get();
        $totalPrice = 0;
        $totalShippingCost = 0;
        foreach ($orderListData as $order) {
            $totalPrice = 0;
            $total_products = 0;
            $quantity = [];
            $totalShippingCost = 0;
            $order->order_total_amount = $totalPrice;
            $order->order_total_shipping = $totalShippingCost;
            $items = Item::leftJoin('plans_v1', 'items.plans_id', 'plans_v1.id')
                ->where('cart_id', $order->id)
                ->get();
            //$order->appointment_status = Appointment::where('id', $order->appointment_id)->first()->status;

            $orderItems = [];
            foreach ($items as $item) {
                array_push($orderItems, $item->plansV1);
                $totalShippingCost += $item->shipping_cost;
                $item->total_price = $item->quantity * $item->price;
                $totalPrice += $item->total_price;
                $order->order_total_amount = $totalPrice;
                $order->order_total_shipping = $totalShippingCost;
                $item->plansV1->qty = $item->quantity;
            }

            $order->total_items = $total_products;
            $order->order_items = $orderItems;
        }
        return response()
            ->json([
                'order_data' => $orderListData
            ]);
    }
    public function orderDetails($id)
    {
        try {
            $this->authorizeForUser($this->user, 'details', new Cart);

            $orderItems = $this->getOrderItems($id);
            $orderDetails = Cart::find($id);
            $items = Item::where('cart_id', $orderDetails->id)->get();
            $appointments = Appointment::select(
                'appointments.*',
                'telemed_pros.name as provider_name',
                'telemed_pros.email as provider_email',
                'telemed_pros.phone_number as provider_phone',
                'carts.total_amount',
                'carts.shipping_amount'
            )
                ->leftJoin('telemed_pros', 'telemed_pros.id', 'appointments.telemed_pros_id')
                ->leftJoin('carts', 'carts.appointment_id', 'appointments.id')

                ->where('appointments.id', $orderDetails->appointment_id)
                ->first();
            if (Gate::forUser($this->user)->allows('prescriptions', new Cart)) {
                $prescription = PatientPrescription::select(
                    'patient_prescription.id as patient_prescription_id',
                    'patient_prescription.id',
                    'patient_prescription.created_by_id',
                    'patient_prescription.created_by_type',
                    'patient_prescription.direction_quantity',
                    'patient_prescription.refill_quantity',
                    'patient_prescription.dosage',
                    'patient_prescription.status',
                    'patient_prescription.direction_one',
                    'patient_prescription.direction_two',
                    'patient_prescription.dont_substitute',
                    'patient_prescription.comments',
                    'patient_prescription.brand',
                    'patient_prescription.from',
                    'patient_prescription.quantity',
                    'patient_prescription.created_at as prescription_date',
                    'prescriptions.name as prescription_name',
                    'patient_prescription.prescription_id',
                    'telemed_pros.name as provide_name',
                    'telemed_pros.id as provider_id',
                )
                    ->where("appointment_id", $orderDetails->appointment_id)
                    ->leftJoin('appointments', 'appointments.id', 'patient_prescription.appointment_id')
                    ->leftJoin('prescriptions', 'prescriptions.id', 'patient_prescription.prescription_id')
                    ->leftJoin('telemed_pros', 'appointments.telemed_pros_id', 'telemed_pros.id')
                    ->get();
            } else {
                $prescription =  ['error' => "Access Denied!"];
            }
            if (Gate::forUser($this->user)->allows('detail_notes', new Cart)) {
                $patientNotes = PatientNote::where("appointment_id", $orderDetails->appointment_id)->get();
            } else {
                $patientNotes =  ['error' => "Access Denied!"];
            }

            if ($appointments)
                $appointments->provider_id = $appointments->telemed_pros_id;
            $patient = $orderDetails->patient;
            $patient->profile_picture = $this->url->to("storage/profile_pictures/" . $patient->profile_picture);

            return response()
                ->json([
                    'order_details' => $orderDetails,
                    'order_items' => $orderItems,
                    'patient_details' => $patient,
                    'appointment_details' => $appointments,
                    'items_activity' => $this->getShippingActivity($id),
                    'appointment_notes' => $patientNotes,
                    'prescription' => $prescription
                ]);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }
    public function getOrderItems($id)
    {
        $items = Item::select('plans_v1.*', 'items.*', 'items.id as item_id', 'plans_v1.id as plans_id')
            ->leftJoin('plans_v1', 'items.plans_id', 'plans_v1.id')
            ->where('cart_id', $id)
            ->get();

        $totalPrice = 0;
        $totalShippingCost = 0;
        $total_products = 0;

        $itemsWithFlags = $items->map(function ($item) {
            $subscription = Subscription::where('item_id', $item->item_id)->first();

            $item->subscription = $subscription ? true : false;
            $item->onetime = $subscription ? true : false;

            $item->total_price = $item->quantity * $item->price;
            $item->image_url = $this->url->to("product/" . $item->image_url);

            return $item;
        });

        foreach ($itemsWithFlags as $item) {
            $totalShippingCost += $item->shipping_cost;
            $totalPrice += $item->total_price;
            $total_products += $item->quantity;
        }

        return [
            'items' => $itemsWithFlags,
            'total_amount' => $totalPrice,
            'total_shipping_cost' => $totalShippingCost,
            'total_products' => $total_products,
            'total' => $totalPrice + $totalShippingCost
        ];
    }
    public function getShippingActivity($id)
    {
        $itemsHistory =  ItemHistory::select('items_history.*', 'plans_v1.title as item_name')
            ->where('items_history.cart_id', $id)
            ->leftJoin('items', 'items.id', 'items_history.item_id')
            ->leftJoin('plans_v1', 'plans_v1.id', 'items.plans_id')
            ->get();
        return $itemsHistory;
    }
    public function getPaymentDetail($id)
    {

        $orderDetails = Cart::find($id);
        $payment = Payment::where('order_id', $orderDetails->id)->first();

        return response()
            ->json([
                'payment' => $payment
            ]);
    }
    public function labkitOrderItemGet(Request $request)
    {
        $labkitOrderItems = LabkitOrderItem::where('labkit_order_items.cart_id', $request->input('cart_id'))
            ->leftJoin(
                'lab_kit',
                'labkit_order_items.lab_kit_id',
                '=',
                'lab_kit.id'
            )
            ->leftJoin(
                'items',
                'items.id',
                'labkit_order_items.item_id'
            )
            ->leftJoin(
                'plans_v1',
                'plans_v1.id',
                'items.plans_id'
            )
            ->select(
                'labkit_order_items.id',
                'labkit_order_items.status',
                'labkit_order_items.result',
                'lab_kit.name as lab_kit_name',
                'plans_v1.title as item_name'
            )
            ->get();
        foreach ($labkitOrderItems as $labKit) {

            if ($labKit->result != "")
                $labKit->result = $this->url->to('storage/lab_results/' . $labKit->result);
        }

        return response()->json([
            'data' => $labkitOrderItems,
        ]);
    }
    public function orderCount(Request $request)
    {

        $fromDate = $request->get('from_date');
        $toDate = $request->get('to_date');
        $total_order = Cart::select(
            "appointments.*",
            'appointments.id as appointment_id',
            'carts.*',
            'carts.id as order_id',
            DB::raw("CONCAT(carts.first_name,' ',carts.last_name) as patient_name"),
        )->leftJoin('appointments', 'appointments.id', 'carts.appointment_id');
        $total_order = $total_order->count();

        $total_appointment_order = Cart::select(
            "appointments.*",
            'appointments.id as appointment_id',
            'carts.*',
            'carts.id as order_id',
            DB::raw("CONCAT(carts.first_name,' ',carts.last_name) as patient_name"),
        )->join('appointments', 'appointments.id', 'carts.appointment_id')
            ->whereNotNull("appointments.id");
        $total_appointment_order = $total_appointment_order->count();

        $total_appointment_order_without = Cart::select(
            "appointments.*",
            'appointments.id as appointment_id',
            'carts.*',
            'carts.id as order_id',
            DB::raw("CONCAT(carts.first_name,' ',carts.last_name) as patient_name"),
        )->leftJoin('appointments', 'appointments.id', 'carts.appointment_id')
            ->whereNull("appointments.id");
        $total_appointment_order_without = $total_appointment_order_without->count();

        $upcomingMeetings = Cart::select(
            'carts.id as order_id',
            'appointments.id',
            'appointments.patient_id',
            'appointments.appointment_time',
            'appointments.appointment_date',
            DB::raw(
                'CONCAT(patients.first_name, " " , patients.last_name) as patient_name'
            )
        )
            ->join('appointments', 'appointments.id', 'carts.appointment_id')
            ->leftJoin('patients', 'patients.id', 'appointments.patient_id')
            ->where('appointments.appointment_date', ">=", Carbon::now()->format("Y-m-d"))
            ->where('appointments.start_time', null)
            ->count();

        $completedMeetings = Cart::select(
            'carts.id as order_id',
            'appointments.patient_id',
            'appointments.appointment_time',
            'appointments.appointment_date',
            'appointments.start_time',
            'appointments.end_time',
            'telemed_pros.name as provider_name',
            'appointments.telemed_pros_id as provider_id',

            DB::raw(
                'CONCAT(patients.first_name, " " , patients.last_name) as patient_name'
            )
        )
            ->join('appointments', 'appointments.id', 'carts.appointment_id')
            ->leftJoin('patients', 'patients.id', 'appointments.patient_id')
            ->leftJoin('telemed_pros', 'telemed_pros.id', 'appointments.telemed_pros_id')
            ->where('appointments.start_time', "!=", null)
            ->where('appointments.end_time', "!=", null)
            ->count();


        $prescribeOrderList = Cart::select(
            "appointments.*",
            'appointments.id as appointment_id',
            'carts.*',
            'carts.id as order_id',
            DB::raw("CONCAT(carts.first_name,' ',carts.last_name) as patient_name"),
        )
            ->leftJoin('appointments', 'appointments.id', 'carts.appointment_id');


        $prescribeOrderCount = $prescribeOrderList->where("prescription_status", 1)->count();
        return response()
            ->json([
                'total_appointment_order' => $total_appointment_order,
                'total_order' => $total_order,
                'total_appointment_order_without' => $total_appointment_order_without,
                'upcomingMeetings' => $upcomingMeetings,
                'completedMeetings' => $completedMeetings,
                'prescribeOrderCount' => $prescribeOrderCount,
            ]);
    }
    public function updateItemStatus($id, Request $request)
    {
        try {
            $this->authorizeForUser($this->user, 'edit', new Cart);
            Item::where('id', $id)
                ->update([
                    'status' => $request->get('status')
                ]);
            $itemsCount = Item::where('cart_id', $request->get('order_id'));
            $statusNeeded = $itemsCount->where('status', '!=', 'pending')
                ->where('status', '!=', 'canceled')
                ->where('status', '!=', 'failed')
                ->where('status', '!=', 'refunded')
                ->where('status', '!=', 'processing')
                ->count();

            if ($itemsCount->count() == $statusNeeded) {
                Cart::where('id', $request->get('order_id'))->update([
                    'status' => 'completed'
                ]);
            }
            return response()
                ->json([
                    'success' => "Updated !"
                ], 200);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }
    public function addNotePatient(Cart $cart, Request $request)
    {

        //$user = Auth::user();
        $appointment = Appointment::find($cart->appointment_id);
        $addNotePatient = PatientNote::create([
            'note' => $request->input('note'),
            'note_type' => $request->input('note_type'),
            'patient_id' => $cart->patient_id,
            'appointment_id' => $cart->appointment_id,
            'telemed_pros_id' => $appointment->telemed_pros_id ?? null,
            'admin_id' => Auth::guard('admin')->user()->id

        ]);
        $addNotePatient->file_url = "";
        if ($request->hasFile('file')) {
            $file = $request->file('file');

            $filename = $addNotePatient->id . '.' . $file->getClientOriginalExtension();

            $file->move(public_path('assets/files'), $filename);

            $addNotePatient->file_url = "assets/files" . $addNotePatient->id . '.' . $file->getClientOriginalExtension();
        }
        $patient = $addNotePatient->patient;
        $setting = Setting::find(1);
        /* Mail::send('emails.noteAdded', ['patient' => $patient, 'agent' => $user, 'setting' => $setting], function ($message) use ($patient, $user) {
            $message->to($patient->email, $patient->first_name)
                ->subject('You Have a New Note from ' . $user->name);
        }); */
        return response()->json([
            'message' => 'Note created',
            'data' => $addNotePatient
        ], 200);
    }
    public function editNotePatient($id, Request $request)
    {
        $note = PatientNote::findOrFail($id);
        $note->update([
            'note' => $request->input('note'),
            'note_type' => $request->input('note_type'),
            'admin_id' => Auth::guard('admin')->user()->id
        ]);

        if ($request->hasFile('file')) {
            // Delete old file if it exists
            if ($note->file_url) {
                $oldFilePath = public_path($note->file_url);
                if (file_exists($oldFilePath)) {
                    unlink($oldFilePath);
                }
            }

            $file = $request->file('file');
            $filename = $note->id . '.' . $file->getClientOriginalExtension();
            $file->move(public_path('assets/files'), $filename);
            $note->file_url = "assets/files" . $note->id . '.' . $file->getClientOriginalExtension();
            $note->save();
        }

        return response()->json([
            'message' => 'Note updated',
            'data' => $note
        ], 200);
    }

    public function deleteNotePatient($id)
    {
        $note = PatientNote::findOrFail($id);

        // Delete associated file if it exists
        if ($note->file_url) {
            $filePath = public_path($note->file_url);
            if (file_exists($filePath)) {
                unlink($filePath);
            }
        }

        $note->delete();

        return response()->json([
            'message' => 'Note deleted'
        ], 200);
    }
    public function getNotePatient($id)
    {
        $note = PatientNote::with(['admin'])->findOrFail($id);

        return response()->json([
            'note' => $note
        ], 200);
    }
}
