<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Country;
use App\Models\Emirate;
use App\Models\Nationality;
use App\Models\PricingPlan;
use App\Models\Sect;
use App\Models\User;
use App\Models\UserDetail;
use App\Models\UserMatch;
use App\Models\UserRequest;
use Illuminate\Support\Facades\DB;
use Exception;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use Yajra\DataTables\Facades\DataTables;
use Illuminate\Support\Facades\Artisan;

class UserController extends Controller
{
    public function indexMale()
    {
        
        $users = [];
        $today = date("Y-m-d");
        $nationalities = Nationality::where('status', 1)->get();
        $emirates = Emirate::where('status', 1)->get();
        $sects = Sect::where('status', 1)->get();
        $plans = PricingPlan::where('status', 1)->get();
        
        return view('admin.user.indexmale', compact('users', 'today', 'nationalities', 'emirates', 'sects', 'plans'));

    }

    public function indexFemale()
    {
        
        $users = [];
        $today = date("Y-m-d");
        $nationalities = Nationality::where('status', 1)->get();
        $emirates = Emirate::where('status', 1)->get();
        $sects = Sect::where('status', 1)->get();
        $plans = PricingPlan::where('status', 1)->get();
        
        return view('admin.user.indexfemale', compact('users', 'today', 'nationalities', 'emirates', 'sects', 'plans'));

    }

    public function createMale(){
        $today = date("Y-m-d");
        $user = "";
        $title       = "";
        $countries            = Country::where('status', 1)->orderBy("name", "asc")->get(); 
        $nationalities            = Nationality::where('status', 1)->orderBy("name", "asc")->get(); 
        
        return view('admin.user.createmale', compact('today', 'user','title','countries','nationalities'));

    }

    public function createFemale(){
        $today = date("Y-m-d");
        $user = "";
        $title       = "";
        $countries            = Country::where('status', 1)->orderBy("name", "asc")->get(); 
        $nationalities            = Nationality::where('status', 1)->orderBy("name", "asc")->get(); 
        
        return view('admin.user.createfemale', compact('today', 'user','title','countries','nationalities'));

    }

    public function getUserList(Request $request) {
        $sqlBuilder = User::select([
            'users.id',
            'users.name',
            'users.nick_name',
            'users.dial_code',
            'users.phone',
            'users.email',
            'users.status',
            'users.gender',
            'users.parent_approval',
            'users.created_at',
            'users.profile_image',
            'users.user_number',
            'sects.name as sect_name',
            'nationalities.name as nationality_name',
            'user_plans.name as plan_name',
        ])
        ->distinct()
        ->leftJoin('nationalities', 'users.nationality_id', '=', 'nationalities.id')
        ->leftJoin('user_details', 'users.id', '=', 'user_details.user_id')
        ->leftJoin('sects', 'user_details.sect_id', '=', 'sects.id')
        ->leftJoin('user_plans', function($join) {
            $join->on('users.id', '=', 'user_plans.user_id')
             ->where('user_plans.status', 1);
        })
        ->where(['role_id' => 2, 'deleted' => 0]);

        if ($request->has('gender') && $request->gender != 'all') {
            $sqlBuilder->where('users.gender', $request->gender);
        }

        $sqlBuilder->orderBy('id', 'desc');

        return DataTables::of($sqlBuilder)
            ->filter(function ($query) use ($request) {
                if ($request->has('search') && !empty($request->search['value'])) {
                    $query->where(function ($query) use ($request) {
                        $query->where('users.name', 'ilike', "%{$request->search['value']}%")
                        ->orWhere('users.nick_name', 'ilike', "%{$request->search['value']}%")
                        ->orWhere('users.dial_code', 'ilike', "%{$request->search['value']}%")
                        ->orWhere('users.phone', 'ilike', "%{$request->search['value']}%")
                        ->orWhere('users.email', 'ilike', "%{$request->search['value']}%")
                        ->orWhere('users.user_number', 'ilike', "%{$request->search['value']}%");
                    });
                }

                if ($request->has('nationality_id') && $request->nationality_id != 'all') {
                    $query->where('users.nationality_id', $request->nationality_id);
                }

                if($request->has('emirates_id') && $request->emirates_id != 'all'){
                    $query->where('users.emirates_id', $request->emirates_id);
                }

                if ($request->has('sect_id') && $request->sect_id != 'all') {
                    $query->where('user_details.sect_id', $request->sect_id);
                }

                if ($request->has('plan_id') && $request->plan_id != 'all') {
                    $query->where('user_plans.plan_id', $request->plan_id)->where('user_plans.status', 1);
                }

                if ($request->has('status') && $request->status != 'all') {
                    $query->where('users.status', $request->status);
                }

                if ($request->has('parent_approval') && $request->parent_approval != 'all') {
                    $query->where('users.parent_approval', $request->parent_approval);
                }

                if ($request->has('start_date') && !empty($request->start_date)) {
                    $query->whereDate('users.created_at', '>=', date('Y-m-d', strtotime($request->start_date)));
                }

                if ($request->has('end_date') && !empty($request->end_date)) {
                    $query->whereDate('users.created_at', '<=', date('Y-m-d', strtotime($request->end_date)));
                }
            })
            ->editColumn('user_image', function ($data) {
                $profileImage = !empty($data->profile_image_url) ? $data->profile_image_url : asset('assets/images/camera_placeholder.png');
                return '<div style="text-align:center;"><img src="' . $profileImage . '" class="rounded-circle avatar-xs" alt="profile-image"></div>';
                
            })
            ->editColumn('subscription_plan', function ($data) {
                return $data->plan_name ?? 'N/A';
            })
            ->editColumn('phone', function ($data) {
                return $data->dial_code . ' ' . $data->phone;
            })
            ->editColumn('status', function ($data) {
            return '<div class="status">
                        <div class="form-check form-switch ">
                            <input class="form-check-input status-checkbox" type="checkbox" role="switch" id="SwitchCheck4" data-url="'. route('admin.users.status', ['id' => $data->id]) .'" data-id="'.$data->id.'" '.(!empty($data->status) && $data->status == 1 ? 'checked' : '').' />
                        </div>
                    </div>';
            })
            ->editColumn('parent_approval', function ($data) {
                switch ($data->parent_approval) {
                    case 0:
                        return '<span class="badge bg-warning">Not Approved</span>';
                        break;
                    case 1:
                        return '<span class="badge bg-success">Approved</span>';
                        break;
                    case 2:
                        return '<span class="badge bg-danger">Rejected</span>';
                        break;
                    default:
                    return '<span class="badge bg-warning">Not Approved</span>';
                        break;
                }
            })
            ->editColumn('created_at', function ($data) {
            return $data->created_at->format('d/m/y H:i A');
            })
            ->addColumn('action', function ($data) {
                if($data->gender == GENDER_MALE){
                    $url = route('admin.users.editmale', ['id' => $data->id]);
                } else{
                    $url = route('admin.users.editfemale', ['id' => $data->id]);
                }

                $detailsUrl = route('admin.users.details', ['id' => $data->id]);
                $matchUrl = route('admin.user_matches.index', ['id' => $data->id]);
                $sentUrl = route('admin.user_requests.sent', ['id' => $data->id]);
                $receivedUrl = route('admin.user_requests.received', ['id' => $data->id]);
                $matchesCount = UserMatch::where('user_id', $data->id)->count();
                $sentCount = UserRequest::where('sender_id', $data->id)->count();
                $receivedCount = UserRequest::where('receiver_id', $data->id)->count();
                $rejecturl = route('admin.users.reject', ['id' => $data->id]);
                $accept_reject="";
                if( $data->is_pending_from_admin==1){
                $accept_reject='<li><a class="dropdown-item approve-btn" data-url="' . route('admin.users.approve', ['id' => $data->id]) . '">Approve</a></li>
                                            <li><a class="dropdown-item" href="' . $rejecturl . '">Reject</a></li>';
                }
                $html = '<div class="dropdown">
                                        <a href="#" class="btn btn-soft-secondary btn-sm" role="button" id="dropdownMenuLink5" data-bs-toggle="dropdown" aria-expanded="false">
                                            <i class="ri-more-2-fill"></i>
                                        </a>

                                        <ul class="dropdown-menu" aria-labelledby="dropdownMenuLink5">
                                            <li><a class="dropdown-item" href="' . $url . '">Edit</a></li>
                                            <li><a class="dropdown-item" href="' . $detailsUrl . '">Details</a></li>
                                            <li><a class="dropdown-item" href="' . $matchUrl . '">Match List('.$matchesCount.')</a></li>
                                            <li><a class="dropdown-item" href="' . $sentUrl . '">Request Sent('.$sentCount.')</a></li>
                                            <li><a class="dropdown-item" href="' . $receivedUrl . '">Request Received('.$receivedCount.')</a></li>
                                            <li><a class="dropdown-item delete-btn" data-url="' . route('admin.users.destroy', ['id' => $data->id]) . '">Delete</a></li>
                                            '.$accept_reject.'
                                            
                                            
                                        </ul>
                                    </div>';
            return $html;
            })
            ->rawColumns(['parent_approval','user_image','status','action'])
            ->make(true);
    }

    
    public function store(Request $request) { 

        $userID = $request->get('id');

        $rules = [
            'name' => 'required|string|max:255',
            'nick_name' => 'required|max:255',
            'email'      => [
                'required',
                'email',
                'unique:users,email,' . ($userID ?? 'NULL'),
                function ($attribute, $value, $fail) {
                    $domain = substr(strrchr($value, "@"), 1);
                    if (!checkdnsrr($domain, 'MX')) {
                        $fail('The email domain is invalid or does not exist.');
                    }
                },
            ],
            'password' => 'required|confirmed|min:8',
            'password_confirmation' => 'required|min:8',
            'dial_code'=> 'required',
            'phone' => 'required|integer',
            'country_id' => 'required',
            'gender' => 'nullable',
            'dob' => 'nullable',
            'status' => 'required|in:0,1',
            'profile_image' => 'nullable|image|mimes:jpeg,png,jpg',
        ];

        if(!empty($userID)){
            $rules['password']      = 'nullable|confirmed|min:9';
            $rules['password_confirmation'] = 'nullable|min:9';
        }

        // Run validation
        $validator = Validator::make($request->all(), $rules);

        // If validation fails, return JSON response
        if ($validator->fails()) {
            return response()->json([
                'status' => 'error',
                'errors' => $validator->errors(),
            ], 422);
        }


        try {
            DB::transaction(function ()use($userID, $request) {
                $user               = $userID? User::findOrFail($userID) : new User();
                $user->name         = $request->input('name');
                $user->nick_name         = $request->input('nick_name');
                $user->email        = $request->input('email');
                $user->dial_code    = $request->input('dial_code');
                $user->phone        = $request->input('phone');
                $user->country_id   = $request->input('country_id');
                $user->gender   = $request->input('gender');
                $user->dob   = $request->input('dob');
                $user->status       = $request->input('status');
                $user->role_id       = 2; //for only customers
                if($request->gender == GENDER_FEMALE){
                    $user->parent_approval = 0;
                } else {
                    $user->parent_approval = 1;
                }
                if($request->filled('password')) {
                    $user->password  = bcrypt($request->input('password'));
                }
                $user->save();
                if($request->file("profile_image")){
                    $response = image_upload($request,config('global.user_image_upload_dir'),'profile_image');
                    if($response['status']){
                        $user->profile_image = $response['link'];
                        $user->save();
                    }
                }
                if (!$user->hasRole('Customer')) {
                    $user->assignRole('Customer');
                }
                
                $user->user_number  = 'LQ' . str_pad($user->id, 6, '0', STR_PAD_LEFT);
                $user->save();
                
            });

            $message = $userID ? 'User updated successfully' : 'User added successfully';

            return response()->json(['status'=>'success', 'message' => $message]);
        } catch (Exception $e) {
            echo $e->getMessage();
            return response()->json(['message' => 'Unable to save the user. Please try later.', "status"=> "error"], 500);
        }
    }
    


  
    public function editMale($id) {
        $user = User::findOrFail($id);
        $countries            = Country::where('status', 1)->orderBy("name", "asc")->get();
        $nationalities            = Nationality::where('status', 1)->orderBy("name", "asc")->get(); 
        
        return view('admin.user.createmale', compact('user','countries','nationalities'));
    }
    
    public function reject($id) {
        $user = User::findOrFail($id);
        
        return view('admin.user.reject', compact('user'));
    }
    public function rejectreason(Request $request) { 

        $userID =( $request->input('id')) ?$request->input('id'):$request->get('id');

        $rules = [
            'rejectreason' => 'required|string|max:255',
            
        ];

       
        // Run validation
        $validator = Validator::make($request->all(), $rules);

        // If validation fails, return JSON response
        if ($validator->fails()) {
            return response()->json([
                'status' => 'error',
                'errors' => $validator->errors(),
            ], 422);
        }


        try {
            DB::transaction(function ()use($userID, $request) {
                $user               = $userID? User::findOrFail($userID) : new User();
                $user->reject_reason         = $request->input('rejectreason');
                $user->is_pending_from_admin         = 2;
                $user->save();
                
            });

            $message ='Reason added successfully';

            return response()->json(['status'=>'success', 'message' => $message]);
        } catch (Exception $e) {
            echo $e->getMessage();
            return response()->json(['message' => 'Unable to save the user. Please try later.', "status"=> "error"], 500);
        }
    }
    public function editFemale($id) {
        $user = User::findOrFail($id);
        $countries            = Country::where('status', 1)->orderBy("name", "asc")->get();
        $nationalities            = Nationality::where('status', 1)->orderBy("name", "asc")->get(); 
        
        return view('admin.user.createfemale', compact('user','countries','nationalities'));
    }

    public function show($id)
    {
        $user = User::with(['preference.sect', 'preference.education', 'preference.profession', 'dressCodes.dressCode', 'maritalStatuses.maritalStatus', 'sects.sect', 'professions.profession', 'educations.education', 'preference.city_emirate','details','children'])->findOrFail($id);
        if($user->gender == GENDER_MALE){
            $back = route('admin.users.male');
        } else {
            $back = route('admin.users.female');
        }
        return view('admin.user.details', compact('user','back'));
    }

    public function destroy($id): JsonResponse
    {
        try {
            $user = User::findOrFail($id);    
            $user->email = $user->email."__deleted_acount".$user->id;
            $user->phone = $user->phone."__deleted_acount".$user->id;
            $user->user_access_token = '';
            $user->user_device_token = '';
            $user->deleted = 1;
            $user->status = 0;
            $user->updated_at = gmdate('Y-m-d H:i:s');
                
                $user->save();
            return response()->json([
                'status' => 'success',
                'message' => 'User deleted successfully.'
            ], 200);
        } catch (ModelNotFoundException $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'User not found.'
            ], 404);
        } catch (Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'An error occurred while deleting the company.'
            ], 500);
        }
    }
    
    public function approve($id): JsonResponse
    {
        try {
            $user = User::findOrFail($id);    
            $user->is_pending_from_admin = '0';
                $user->save();
            return response()->json([
                'status' => 'success',
                'message' => 'User Approved successfully.'
            ], 200);
        } catch (ModelNotFoundException $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'User not found.'
            ], 404);
        } catch (Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'An error occurred while approving the user.'
            ], 500);
        }
    }

    public function statusChange(Request $request, $id) {
        $user = User::find($id);

        if (!$user) {
            return response()->json([
                'status' => 'error',
                'message' => 'User not found.'
            ], 404);
        }
    
        $user->status = $request->status;
        $user->save();
    
        return response()->json([
            'status' => 'success',
            'message' => 'User status updated successfully.'
        ]);
    }

    public function changePassword(Request $request)
    {
        $rules = [
            'password' => 'required|min:8|confirmed',
        ];

        $validator = Validator::make($request->all(), $rules);

        if ($validator->fails()) {
            return response()->json([
                'status' => 'error',
                'errors' => $validator->errors(),
            ], 422);
        }

        try {
            $user = User::findOrFail(Auth::user()->id);

            $user->password = bcrypt($request->input('password'));
            $user->save();

            return response()->json([
                'status' => 'success',
                'message' => 'Password changed successfully.',
            ]);
        } catch (ModelNotFoundException $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'User not found.',
            ], 404);
        } catch (Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'An error occurred while changing the password.',
            ], 500);
        }
    }


    public function exportUsers()
    {
        $users = User::where('role_id', 3)->orderBy('id', 'desc')->get()->all();  

        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle('Users');

        // Setting headers for the Excel sheet
        $sheet->setCellValue('A1', 'No');
        $sheet->setCellValue('B1', 'First Name');
        $sheet->setCellValue('C1', 'Last Name');
        $sheet->setCellValue('D1', 'Phone');
        $sheet->setCellValue('E1', 'Email');
        $sheet->setCellValue('F1', 'Country ID');
        $sheet->setCellValue('G1', 'Emirates ID');
        $sheet->setCellValue('H1', 'City ID');
        $sheet->setCellValue('I1', 'Company ID');
        $sheet->setCellValue('J1', 'Status');
        $sheet->setCellValue('K1', 'Created At');

        // Add user data to the sheet
        $row = 2; 
        foreach ($users as $index => $user) {
            $sheet->setCellValue('A' . $row, $index + 1); 
            $sheet->setCellValue('B' . $row, $user->first_name); 
            $sheet->setCellValue('C' . $row, $user->last_name); 
            $sheet->setCellValue('D' . $row, $user->phone); 
            $sheet->setCellValue('E' . $row, $user->email); 
            $sheet->setCellValue('F' . $row, $user->country_id); 
            $sheet->setCellValue('G' . $row, $user->emirates_id); 
            $sheet->setCellValue('H' . $row, $user->city_id); 
            $sheet->setCellValue('I' . $row, $user->company_id); 
            $sheet->setCellValue('J' . $row, $user->status ? 'Active' : 'Inactive'); 
            $sheet->setCellValue('K' . $row, $user->created_at->format('d M, Y - h:i A')); 
            $row++;
        }

        // Apply styling to header row
        $sheet->getStyle('A1:K1')->getFont()->setBold(true);
        $sheet->getStyle('A1:K1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
        $sheet->getStyle('A1:K1')->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);

        // Generate the Excel file for download
        $writer = new Xlsx($spreadsheet);
        $fileName = "Users_Export_" . date('Y_m_d_H_i_s') . ".xlsx";

        header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        header("Content-Disposition: attachment;filename=\"$fileName\"");
        header('Cache-Control: max-age=0');

        $writer->save('php://output');
        exit();
    }

    public function getMinimalUserList(Request $request)
    {
        if($request->has('type') && $request->type == 'email'){
            $select = 'email as text';
        } else {
            $select = DB::raw("name as text");
        }
        $user = User::select([
            'id',
            $select,
        ])->where('role_id', 2)
        ->where('deleted',0)
        ->whereIn('gender',[GENDER_MALE,GENDER_FEMALE]);

        if ($request->has('term') && !empty($request->term)) {
            $user->where(function ($q) use ($request) {
            $q->where('name', 'ilike', "%{$request->term}%")
                ->orWhere('nick_name', 'ilike', "%{$request->term}%")
                ->orWhere('email', 'ilike', "%{$request->term}%");
            });
        }

        if ($request->has('country_id') && !empty($request->country_id)) {
            $user->where('country_id', $request->country_id);
        }

        if ($request->has('limit') && !empty($request->limit)) {
            $user->limit($request->limit);
        }

        if ($request->has('page') && !empty($request->page)) {
            $user->offset($request->page);
        }

        if ($request->has('offset') && !empty($request->offset)) {
            $user->offset($request->offset);
        }

        $user = $user->get();

        return response()->json($user);
    }

    public function chats()
    { 
        $chats = [];
        return view('admin.user.chats', compact('chats'));
    }

    public function chat()
    { 
        $chat = [];
        return view('admin.user.chat', compact('chat'));
    }

    public function motherCertificateVerificationList()
    {
        $today = date("Y-m-d");
        $nationalities = Nationality::where('status', 1)->get();
        $emirates = Emirate::where('status', 1)->get();
        $sects = Sect::where('status', 1)->get();
        $plans = PricingPlan::where('status', 1)->get();
        
        return view('admin.user.mother_certificate_verification', compact('today', 'nationalities', 'emirates', 'sects', 'plans'));
    }

    public function getMotherCertificateVerificationList(Request $request)
    {
        $sqlBuilder = User::select([
            'users.id',
            'users.name',
            'users.nick_name',
            'users.dial_code',
            'users.phone',
            'users.email',
            'users.status',
            'users.gender',
            'users.created_at',
            'users.profile_image',
            'users.user_number',
            'users.mother_certificate_verified ',
            'users.is_pending_from_admin',
            'users.is_mother_uae_national',
            'sects.name as sect_name',
            'nationalities.name as nationality_name',
        ])
        ->distinct()
        ->leftJoin('nationalities', 'users.nationality_id', '=', 'nationalities.id')
        ->leftJoin('user_details', 'users.id', '=', 'user_details.user_id')
        ->leftJoin('sects', 'user_details.sect_id', '=', 'sects.id')
        ->where([
            'role_id' => 2,
            'deleted' => 0,
            'mother_certificate_verified ' => 0,
            'is_pending_from_admin' => 1,
            'is_mother_uae_national' => 1
        ]);

        $sqlBuilder->orderBy('users.id', 'desc');

        return DataTables::of($sqlBuilder)
            ->editColumn('user_image', function ($data) {
                $profileImage = !empty($data->profile_image_url) ? $data->profile_image_url : asset('assets/images/camera_placeholder.png');
                return '<div style="text-align:center;"><img src="' . $profileImage . '" class="rounded-circle avatar-xs" alt="profile-image"></div>';
            })
            ->editColumn('phone', function ($data) {
                return $data->dial_code . ' ' . $data->phone;
            })
            ->editColumn('mother_certificate_verified ', function ($data) {
                return '<div class="status">
                            <div class="form-check form-switch ">
                                <input class="form-check-input verify-mother-cert" type="checkbox" role="switch" data-url="' . route('admin.users.verify_mother_certificate', ['id' => $data->id]) . '" data-id="' . $data->id . '" ' . ($data->{'mother_certificate_verified '} == 1 ? 'checked' : '') . ' />
                            </div>
                        </div>';
            })
            ->editColumn('created_at', function ($data) {
                return $data->created_at->format('d/m/y H:i A');
            })
            ->addColumn('action', function ($data) {
                $detailsUrl = route('admin.users.details', ['id' => $data->id]);
                return '<a href="' . $detailsUrl . '" class="btn btn-soft-primary btn-sm">Details</a>';
            })
            ->rawColumns(['user_image', 'mother_certificate_verified ', 'action'])
            ->make(true);
    }

    public function verifyMotherCertificate($id): JsonResponse
    {
        try {
            $user = User::findOrFail($id);
            $user->{'mother_certificate_verified '} = 1;
            $user->status = 1;
            $user->is_pending_from_admin = 0;
            $user->save();
            Artisan::call('app:send-mother-verified-push', ['user_id' => $user->id]);
            return response()->json([
                'status' => 'success',
                'message' => 'Mother certificate verified successfully.'
            ], 200);
        } catch (ModelNotFoundException $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'User not found.'
            ], 404);
        } catch (Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'An error occurred while verifying.'
            ], 500);
        }
    }
}
