<?php

namespace App\Http\Controllers\Admin\Api;

use App\Classes\Constant;
use App\Http\Controllers\Controller;
use App\Models\Admin;
use App\Models\Appointment;
use App\Models\Cart;
use App\Models\Item;
use App\Models\Lab;
use App\Models\MedicalHistoryAnswer;
use App\Models\Patient;
use App\Models\PatientRegActivity;
use App\Models\Plan;
use App\Models\PlanV1;
use App\Models\ProfileAnswer;
use App\Models\QuestionBuilder;
use App\Models\Telemedpro;
use App\Permissions\Permissions;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use PhpOffice\PhpSpreadsheet\Writer\Ods\Settings;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Facades\DB;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Support\Facades\Storage;

class DashboardController extends Controller
{

    protected $url;
    protected $user;
    public function __construct(UrlGenerator $url)
    {
        $this->url = $url;
        $this->user = Auth::guard('admin')->user();
    }
    public function getStats()
    {


        $date = Carbon::now();
        $startOfWeek = $date->startOfWeek(Carbon::MONDAY)->format("Y-m-d");
        $endDate = Carbon::now()->format('Y-m-d');
        $newPatients = self::getNewPatients($startOfWeek, $endDate);
        $newProviders = self::getNewProviders($newPatients, $endDate);
        $analytics = self::getAnalytics();
        $upcomingMeetings = Appointment::where('appointment_date', '>=', $date->toDateString())->count();
        return response()->json([
            'upcoming_meetings' => $upcomingMeetings,
            'new_customers' => $newPatients,
            'new_providers' => $newProviders,
            'analytics' => $analytics
        ]);
    }
    protected function getNewPatients($newPatients, $endOfWeek)
    {
        $upcomingMeetings = Patient::where('created_at', '>=', $newPatients)
            ->where('created_at', '<=', $endOfWeek)
            ->count();
        return $upcomingMeetings;
    }
    protected function getNewProviders($newPatients, $endOfWeek)
    {
        $upcomingMeetings = Telemedpro::where('created_at', '>=', $newPatients)
            ->where('created_at', '<=', $endOfWeek)
            ->count();
        return $upcomingMeetings;
    }
    protected function getAnalytics($filter = '12_months')
    {
        $currentMonth = Carbon::now();

        // Filter logic
        switch ($filter) {
            case 'current_month':
                $startDate = $currentMonth->copy()->startOfMonth();
                break;
            case '1_month':
                $startDate = $currentMonth->copy()->subMonth()->startOfMonth();
                break;
            case '2_months':
                $startDate = $currentMonth->copy()->subMonths(2)->startOfMonth();
                break;
            case '3_months':
                $startDate = $currentMonth->copy()->subMonths(3)->startOfMonth();
                break;
            case '6_months':
                $startDate = $currentMonth->copy()->subMonths(6)->startOfMonth();
                break;
            default: // Default to 12 months
                $startDate = $currentMonth->copy()->subMonths(12)->startOfMonth();
        }

        $endDate = $currentMonth->endOfMonth();


        $appointments = Appointment::with('patient')
            ->whereBetween('created_at', [$startDate, $endDate])
            ->get();

        $totalSessions = $appointments->count();
        $totalCallTime = 10; // Assuming you have some logic to calculate this
        if ($totalSessions != 0) {
            $avgSessionTime = $totalCallTime / $totalSessions;
            $avgSessionTime = round(($avgSessionTime / 60), 2);
        } else
            $avgSessionTime = '';


        $monthlyData = [];

        // Loop through each month in the last 12 months
        for ($date = $startDate->copy(); $date->lte($endDate); $date->addMonth()) {
            $monthStart = $date->startOfMonth()->format('Y-m-d');
            $monthEnd = $date->copy()->endOfMonth()->format('Y-m-d'); // Key change here!

            $monthAppointments = Appointment::with('patient')
                ->whereBetween('created_at', [$monthStart, $monthEnd])
                ->get();


            // Calculate any metrics you need from $monthAppointments
            $monthlyData[] = [
                'month' => $date->format('M'), // Example: Jan 2024
                'appointment_count' => $monthAppointments->count()
                // Add other metrics as needed
            ];
        }
        $monthsList = [];
        $monthlySessionCount = [];

        foreach ($monthlyData as $dataPoint) {
            $monthsList[] = $dataPoint['month'];
            $monthlySessionCount[] = $dataPoint['appointment_count'];
        }


        return [
            // 'total_sessions' => $totalSessions,
            'total_call_time' => $totalCallTime,
            // 'avg_session_time' => $avgSessionTime,
            'data' => array_values($monthlySessionCount),
            'months_list' => $monthsList,
        ];
    }
    public function getAdminDetails(Request $request)
    {
        $user = Auth::guard('admin')->user();
        $permissionManager = new  Permissions($user->role->permissions);
        $permissions = $permissionManager->permissionsApi();
        if (isset($user->image_path))
            $user->image_path = $this->url->to('/storage/profile_pictures/' . $user->image_path);
        else
            $user->image_path = Null;
        return response()->json([
            'admin_details' => $user,
            'permissions'=>$permissions
        ]);
    }
    public function updateAdminDetails(Request $request)
    {
        $userId = Auth::guard('admin')->user()->id;
        $user = Admin::find($userId);

        if($request->get('image'))
        {
            $image = $request->get('image');
            $fileName = 'profile-' . time();

            $logo = base64_decode($image);
            $ext = (explode('/', finfo_buffer(finfo_open(), $logo, FILEINFO_MIME_TYPE))[1]);

            $imageName =  $fileName . '.' . $ext;
            Storage::disk('local')->put("/public/profile_pictures/" . $imageName, $logo);
        }

        $user->name = $request->get('first_name');
        $user->last_name = $request->get('last_name');
        $user->phone_no = $request->get('phone_no');
        if ($request->get('image'))
            $user->image_path = $imageName;
        $user->save();
        return response()->json([
            'admin_details' => $user
        ]);
    }
    public function uploadImage($image, $fileName, $path)
    {
        $logo = base64_decode($image);
        $filename = (explode('/', finfo_buffer(finfo_open(), $logo, FILEINFO_MIME_TYPE))[0]);
        $ext = (explode('/', finfo_buffer(finfo_open(), $logo, FILEINFO_MIME_TYPE))[1]);
        $imageName =  $fileName . '.' . $ext;
        $path =  $path . $imageName;
        file_put_contents($path, $logo);
        return $imageName;
    }
    public function index(Request $request){

        try{
            $this->authorizeForUser($this->user,'DashboardData', new Admin);
            $start_date = $request->get('start_date');
            $end_date = $request->get('end_date');
            $totalPatients = $this->getTotals($start_date,$end_date);
            $graphData = $this->graphData($start_date,$end_date);
            $patientActivity = $this->patientActivit($start_date,$end_date);
            $ordersData = $this->ordersData($start_date,$end_date);
            $completedMeetings = $this->completedMeetings($start_date,$end_date);
            $orders = $this->productsData($start_date,$end_date);
            return response()->json([
                'totals' =>$totalPatients,
                'graph_data'=>$graphData,
                'patient_reg_activity'=>$patientActivity,
                'orders_data'=>$ordersData,
                'completed_meetings'=>$completedMeetings,
                'products'=>$orders
            ]);
        } catch (AuthorizationException $e) {
            return  $e->getMessage();
        }
    }
    public function getTotals($start_date,$end_date)
    {
        $totalPatients = Patient::
                            where('created_at', '>=', $start_date." 00:00:00")
                            ->where('created_at', '<=', $end_date." 23:59:59")
                            ->count();
        $totalOrders = Cart::select(
                                    DB::raw("count(carts.id) as total_sales"),
                                    DB::raw("sum(carts.total_amount ) as sales_amount"),
                                    DB::raw("count(items.id) as products_sold")
                                )
                        ->leftJoin('items','items.cart_id','carts.id')
                        ->where('carts.created_at', '>=', $start_date." 00:00:00")
                        ->where('carts.created_at', '<=', $end_date." 23:59:59")
                        ->where('carts.status','completed')
                        ->first();

        return [
            'total_patints'=>$totalPatients,
            'total_orders'=>$totalOrders->total_sales,
            'total_amount'=>$totalOrders->sales_amount,
            'total_products_sold'=>$totalOrders->products_sold
        ];
    }
    public function graphData($start_date,$end_date)
    {
        $dates = [];
        $sales =[];
        $totalMeetingsData =[];
        $startDate = Carbon::parse($start_date);
        $endDate = Carbon::parse($end_date);
        for ($date = $startDate; $date->lte($endDate); $date->addDay()) {
            //get total sales data
            $values = Cart::select(
                                        DB::raw('DATE(created_at) as date'),
                                        DB::raw("SUM(case when carts.status = 'completed' then carts.total_amount else 0 end) as amount"))
                                        ->where('carts.created_at', '>=', $date->format("Y-m-d")." 00:00:00")
                                        ->where('carts.created_at', '<=', $date->format("Y-m-d")." 23:59:59")
                                        ->groupBy(DB::raw('DATE(created_at)'));
                                        $graphsValues = $values->first();
            // get total meetings
            $totalMeetings = Appointment::
                                    where('start_time', '>=', $date->format("Y-m-d")." 00:00:00")
                                    ->where('start_time', '<=', $date->format("Y-m-d")." 23:59:59")
                                    ->where('status', 'completed')
                                    ->count();
            $dates[] = $date->format("M d/y");
            if($graphsValues)
                $sales[] = round($graphsValues->amount,2);
            else
                $sales[] = 0.00;

            $totalMeetingsData[] = round($totalMeetings,2);
        }
        return [
                'dates'=>$dates,
                'data'=>
                    [
                        'total_sales'=>$sales,
                        'total_meetings'=>$totalMeetingsData
                    ]
                ];
    }
    public function patientActivit($start_date,$end_date){
        $patientActivity = PatientRegActivity::
                            where('created_at', '>=', $start_date." 00:00:00")
                            ->where('created_at', '<=', $end_date." 23:59:59")
                            ->get();

        $activity = $patientActivity->map(function ($query,$key){
            $patient = Patient::find($query->patient_id);
            if($query->activity=='patient_registered')
            {
                $query->activity = $patient->first_name. " ". $patient->last_name. " Singed Up";
            }
            if($query->activity=='patient_appointment_booked')
            {
                $query->activity = $patient->first_name. " ". $patient->last_name. " Booked an appointment ";
            }
        return $query;

        });

        return $patientActivity;
    }
    public function ordersData($start_date,$end_date){
       return Cart::select('carts.id as order_id','carts.total_amount as amount',
                        DB::raw("CONCAT(first_name,' ',last_name) as patient_name"),
                        'created_at as date')
                        ->where('created_at', '>=', $start_date." 00:00:00")
                        ->where('created_at', '<=', $end_date." 23:59:59")
                        ->get();
    }
    public function completedMeetings($start_date,$end_date){
        return Appointment::select(
            'appointments.patient_id',
            'appointments.appointment_time',
            'appointments.appointment_date',
            'appointments.start_time',
            'appointments.end_time',
            'appointments.timezone',
            'telemed_pros.name as provider_name',
            'telemed_pros_id as provider_id',
            'carts.id as order_id',
            'appointments.patient_name'
        )
            ->Join('telemed_pros', 'telemed_pros.id', 'appointments.telemed_pros_id')
            ->Join("carts", "appointments.id","carts.appointment_id")
            ->where('appointments.status', "completed")
            ->where('appointments.end_time', '>=', $start_date." 00:00:00")
            ->where('appointments.end_time', '<=', $end_date." 23:59:59")
            ->get();
    }
    public function productsData($start_date,$end_date)
    {
        return Item::select(
                                DB::raw("sum(case when items.status='delivered' then items.quantity else 0 end) as total_orders"),
                                DB::raw("sum(case when items.status='delivered' then (items.quantity*plans_v1.price) else 0 end) as total_amount"),
                                'plans_v1.title as product_name',
                                'items.plans_id as product_id'
                                )
                        ->leftJoin('plans_v1','plans_v1.id','items.plans_id')
                        ->where('items.created_at', '>=', $start_date." 00:00:00")
                        ->where('items.created_at', '<=', $end_date." 23:59:59")
                        ->groupby('plans_v1.title', 'items.plans_id')
                        ->get();
                        // dd(Constant::getFullSql($products));
    }
}
