<?php

namespace App\Http\Controllers;

use App\Models\Client;
use App\Models\ClientLocation;
use App\Models\ClientContract;
use App\Models\ClientContact;
use App\Models\Country;
use App\Models\CustomerMember;
use App\Models\Status;
use App\Models\Locker;
use App\Models\LockerGroup;
use App\Models\LockerRegistration;
use App\Models\MembershipPlan;
use App\Models\ReferredClient;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log;

class ClientController extends Controller
{
    // public function index(Request $request)
    // {
    //     $query = Client::with(['status', 'customerMembers', 'accountType', 'lockerRegistrations'])
    //         ->byTenant();

    //     if ($request->filled('search')) {
    //         $search = $request->search;
    //         $query->where('name', 'like', "%{$search}%");
    //     }

    //     if ($request->filled('status')) {
    //         $query->whereHas('status', function ($q) use ($request) {
    //             $q->where('name', $request->status);
    //         });
    //     }

    //     $clients = $query->orderBy('id', 'desc')->paginate(20);

    //     return view('clients.index', compact('clients'));
    // }

    public function index(Request $request)
    {
        $query = Client::with([
            'status',
            'customerMembers',
            'accountType',

            // LOAD ONLY ACTIVE REGISTRATION
            'lockerRegistrations' => function ($q) {
                $q->where('status', 'Active')
                    ->latest(); // latest renewal
            }
        ])->byTenant();

        if ($request->filled('search')) {
            $query->where('name', 'like', "%{$request->search}%");
        }

        if ($request->filled('status')) {
            $query->whereHas('status', function ($q) use ($request) {
                $q->where('name', $request->status);
            });
        }

        $clients = $query->orderBy('id', 'desc')->paginate(20);

        return view('clients.index', compact('clients'));
    }

    public function referralDetails(Request $request)
    {
        $query = CustomerMember::with(['client', 'statusRelation', 'referralRegistrations'])
            ->withSum('referralRegistrations as referred_commission', 'referred_commission')
            ->withSum('referralRegistrations as commission_used', 'commission_used');

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('mobile', 'like', "%{$search}%")
                    ->orWhere('proof_type', 'like', "%{$search}%")
                    ->orWhereHas('client', function ($clientQuery) use ($search) {
                        $clientQuery->where('phone', 'like', "%{$search}%")
                            ->orWhere('name', 'like', "%{$search}%");
                    })
                    ->orWhereHas('referralRegistrations', function ($registrationQuery) use ($search) {
                        $registrationQuery->where('referred_member_by', 'like', "%{$search}%");
                    });
            });
        }

        if ($request->filled('status')) {
            if ($request->status === 'active') {
                $query->where('is_active', true);
            } elseif ($request->status === 'inactive') {
                $query->where('is_active', false);
            } elseif ($request->status === 'blocked') {
                $query->whereHas('statusRelation', function ($statusQuery) {
                    $statusQuery->where('name', 'blocked');
                });
            }
        }

        $summaryQuery = clone $query;
        $summary = [
            'total_members' => $summaryQuery->count(),
            'total_referral_amount' => (clone $summaryQuery)->get()->sum('referred_commission'),
            'total_commission_used' => (clone $summaryQuery)->get()->sum('commission_used'),
            // 'total_amount' =>
            'total_balance' => (clone $summaryQuery)->get()->sum('referred_commission') - (clone $summaryQuery)->get()->sum('commission_used'),
        ];

        $records = $query->orderBy('name')->paginate(20)->withQueryString();

        $status = $request->status;
        $search = $request->search;

        return view('clients.referral-details', compact('records', 'summary', 'status', 'search'));
    }

    public function create()
    {
        $statuses = \App\Models\Status::all();
        $lockers = \App\Models\Locker::all();
        $account_type = \App\Models\AccountType::where('status', 1)->get();
        $membership_plan = MembershipPlan::select('id', 'name', 'duration_days', 'duration_months', 'price')->where('status', 1)->get();
        $locker_groups = LockerGroup::select('id', 'name')->get();
        $countries = Country::select('id', 'name')->where('status', 1)->get();

        return view('clients.create-edit', compact('statuses', 'lockers', 'account_type', 'membership_plan', 'locker_groups', 'countries'));
    }

    public function store(Request $request)
    {
        // echo "<pre>";
        // print_r($request->toArray());
        // exit;
        $validator = Validator::make($request->all(), [
            'account_type' => 'required|integer|exists:account_types,id',
            'auth_count' => 'required|numeric',
            'name' => 'required|string|max:255',
            'phone' => 'required|string|max:20',
            'landline' => 'nullable|string|max:20',
            'address' => 'required|string|max:500',
            'country' => 'required|string|max:100',
            'state' => 'required|string|max:100',
            'city' => 'required|string|max:100',
            'postal_code' => 'required|string|max:10',
            'registration_number' => 'nullable|string|max:30',
            'tax_type' => 'required|string|max:50',
            'tax_amount' => 'nullable|numeric|min:0',
            'stamping_fee' => 'required|numeric',
            'key_deposit' => 'required|numeric',
            'insurance_charges' => 'required|numeric',
            'discount_amount' => 'required|numeric',
            'final_amount' => 'nullable|numeric|min:0',
            'payment_mode' => 'required|string|max:50',
            'safebox_count' => 'required|numeric',
            'selected_lockers_data' => 'required|string|json',
            'payment_terms' => 'required|string|max:50',
            'contract_start_date' => 'required|date|after_or_equal:today',
            'contract_end_date' => 'required|date|after_or_equal:contract_start_date',
            'referred_member_by' => 'nullable|string|max:50',
            'referred_commission' => 'nullable|numeric',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors()
            ], 422);
        }

        try {
            DB::beginTransaction();

            // Decode locker data
            $lockersData = json_decode($request->selected_lockers_data, true);

            if (!$lockersData || !is_array($lockersData)) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid locker data format'
                ], 422);
            }

            // Validate each locker
            foreach ($lockersData as $locker) {
                if (!isset($locker['id'], $locker['number'], $locker['size'], $locker['type'])) {
                    return response()->json([
                        'success' => false,
                        'message' => 'Invalid locker structure'
                    ], 422);
                }

                $lockerRecord = \App\Models\Locker::find($locker['id']);

                if (!$lockerRecord || $lockerRecord->status !== 'Available') {
                    return response()->json([
                        'success' => false,
                        'message' => "Locker {$locker['number']} is not available"
                    ], 422);
                }
            }

            // Create Client
            $client = \App\Models\Client::create([
                'name' => $request->name,
                'phone' => $request->phone,
                'landline' => $request->landline,
                'address' => $request->address,
                'country' => $request->country,
                'state' => $request->state,
                'city' => $request->city,
                'postal_code' => $request->postal_code,
                'account_type_id' => $request->account_type,
                'tax_type' => $request->tax_type,
                'registration_number' => $request->registration_number,
                'auth_count' => $request->auth_count,
                'is_appointment' => '1',
                'status_id' => '1',
                'tenant_id' => config('app.default_tenant_id', 1),
            ]);

            // Create ONE Registration
            $registration = \App\Models\LockerRegistration::create([
                'client_id' => $client->id,
                'auth_count' => $request->auth_count,
                'locker_password' => '123456',
                'registration_date' => now()->toDateString(),
                'safebox_count' => $request->safebox_count,
                'contract_start_date' => $request->contract_start_date,
                'contract_end_date' => $request->contract_end_date,
                'payment_terms' => $request->payment_terms,
                'stamping_fee' => $request->stamping_fee,
                'key_deposit' => $request->key_deposit,
                'insurance_charges' => $request->insurance_charges,
                'discount_amount' => $request->discount_amount,
                'tax_amount' => $request->tax_amount,
                'referred_member_by' => $request->referred_member_by,
                'referred_commission' => $request->referred_commission,
                'status' => 'Active',
            ]);

            // Insert Locker Items
            $totalAmount = 0;

            foreach ($lockersData as $locker) {

                \App\Models\LockerRegistrationItem::create([
                    'registration_id' => $registration->id,
                    'locker_id' => $locker['id'],

                    'locker_number' => $locker['number'],
                    'size' => $locker['size'],
                    'type' => $locker['type'],
                    'locker_group' => $locker['locker_group'] ?? null,
                    'locker_position' => $locker['locker_position'] ?? null,

                    'start_date' => $request->contract_start_date,
                    'end_date' => $request->contract_end_date,

                    'amount' => $locker['amount'] ?? 0,

                    'status' => 'active',
                    'added_at' => now(),
                ]);

                // Update locker status
                \App\Models\Locker::where('id', $locker['id'])
                    ->update(['status' => 'Occupied']);

                // Calculate total
                $totalAmount += $locker['amount'] ?? 0;
            }

            $taxAmount = (float) ($request->tax_amount ?? 0);
            $finalAmount = (float) ($request->final_amount ?? 0);
            $paymentTotal = $finalAmount > 0 ? $finalAmount : ($totalAmount + $taxAmount);

            // Create Payment
            \App\Models\Payment::create([
                'registration_id' => $registration->id,
                'payment_mode' => $request->payment_mode,
                'total_amount' => $paymentTotal,
                'paid_amount' => $paymentTotal,
                'balance_amount' => 0,
                'payment_date' => now(),
                'status' => 'paid',
                'notes' => 'create',
            ]);

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Locker registered successfully',
                'redirect' => route('customers.members', ['client' => $client->id])
            ]);
        } catch (\Exception $e) {
            DB::rollBack();

            return response()->json([
                'success' => false,
                'message' => 'Error: ' . $e->getMessage()
            ], 500);
        }
    }

    // public function show($id)
    // {
    //     $client = Client::with([
    //         'lockerRegistrations' => function ($query) {
    //             $query->where('status', 'Active');
    //         },
    //         'lockerRegistrations.locker',
    //         'lockerRegistrations.membershipPlan',
    //         'lockerRegistrations.items',
    //         'lockerRegistrations.payments',
    //         'customerMembers',
    //     ])
    //         ->findOrFail($id);

    //     return view('clients.show', compact('client'));
    // }

    public function show($id)
    {
        $client = Client::with([
            'lockerRegistrations' => function ($query) {
                $query->where('status', 'Active');
            },
            'lockerRegistrations.locker',
            'lockerRegistrations.membershipPlan',
            'lockerRegistrations.items',
            'lockerRegistrations.payments',
            'customerMembers',
        ])
            ->findOrFail($id);

        return view('clients.show', compact('client'));
    }

    public function renewal($clientId, $registrationId)
    {
        $client = Client::findOrFail($clientId);

        $registration = LockerRegistration::with(['locker', 'membershipPlan', 'items' => function ($query) {
            $query->where('status', 'active');
        }, 'items.locker'])
            ->where('id', $registrationId)
            ->where('status', 'Active')
            ->where('client_id', $clientId)
            ->firstOrFail();

        $membership_plan = MembershipPlan::select('id', 'name', 'duration_days', 'duration_months', 'price')
            ->where('status', 1)
            ->orderBy('sort_order')
            ->get();

        return view('clients.renewal', compact('client', 'registration', 'membership_plan'));
    }

    public function createLocker($id)
    {
        $client = Client::byTenant()->findOrFail($id);
        $membership_plan = MembershipPlan::select('id', 'name', 'duration_days', 'duration_months', 'price')
            ->where('status', 1)
            ->get();
        $locker_groups = LockerGroup::select('id', 'name')->get();

        return view('clients.add-locker', compact('client', 'membership_plan', 'locker_groups'));
    }

    public function storeLocker(Request $request, $id)
    {
        $client = Client::byTenant()->findOrFail($id);

        $validator = Validator::make($request->all(), [
            'safebox_count' => 'required|numeric|min:1',
            'selected_lockers_data' => 'required|string|json',
            'payment_terms' => 'required|string|max:50',
            'contract_start_date' => 'required|date|after_or_equal:today',
            'contract_end_date' => 'nullable|date|after_or_equal:contract_start_date',
            'stamping_fee' => 'required|numeric',
            'key_deposit' => 'required|numeric',
            'insurance_charges' => 'required|numeric',
            'discount_amount' => 'required|numeric',
            'tax_amount' => 'required|numeric',
            'payment_mode' => 'required|string|max:50',
            'referred_member_by' => 'nullable|string|max:50',
            'referred_commission' => 'nullable|numeric',
        ]);

        if ($validator->fails()) {
            return redirect()->back()->withErrors($validator)->withInput();
        }

        try {
            DB::beginTransaction();

            $lockersData = json_decode($request->selected_lockers_data, true);

            if (!$lockersData || !is_array($lockersData)) {
                return redirect()->back()->with('error', 'Invalid locker selection format.');
            }

            foreach ($lockersData as $locker) {
                if (!isset($locker['id'], $locker['number'], $locker['size'], $locker['type'])) {
                    return redirect()->back()->with('error', 'Invalid locker data.');
                }

                $lockerRecord = \App\Models\Locker::find($locker['id']);
                if (!$lockerRecord || $lockerRecord->status !== 'Available') {
                    return redirect()->back()->with('error', "Locker {$locker['number']} is not available.");
                }
            }

            $registration = \App\Models\LockerRegistration::create([
                'client_id' => $client->id,
                'auth_count' => $client->auth_count ?? 0,
                'locker_password' => '123456',
                'registration_date' => now()->toDateString(),
                'safebox_count' => $request->safebox_count,
                'contract_start_date' => $request->contract_start_date,
                'contract_end_date' => $request->contract_end_date,
                'payment_terms' => $request->payment_terms,
                'stamping_fee' => $request->stamping_fee,
                'key_deposit' => $request->key_deposit,
                'insurance_charges' => $request->insurance_charges,
                'discount_amount' => $request->discount_amount,
                'tax_amount' => $request->tax_amount,
                'referred_member_by' => $request->referred_member_by,
                'referred_commission' => $request->referred_commission,
                'status' => 'Active',
            ]);

            $totalAmount = 0;
            foreach ($lockersData as $locker) {
                \App\Models\LockerRegistrationItem::create([
                    'registration_id' => $registration->id,
                    'locker_id' => $locker['id'],
                    'locker_number' => $locker['number'],
                    'size' => $locker['size'],
                    'type' => $locker['type'],
                    'locker_group' => $locker['locker_group'] ?? null,
                    'locker_position' => $locker['locker_position'] ?? null,
                    'start_date' => $request->contract_start_date,
                    'end_date' => $request->contract_end_date,
                    'amount' => $locker['amount'] ?? 0,
                    'status' => 'active',
                    'added_at' => now(),
                ]);

                \App\Models\Locker::where('id', $locker['id'])->update(['status' => 'Occupied']);
                $totalAmount += (float) ($locker['amount'] ?? 0);
            }

            $paymentTotal = (float) ($request->final_amount ?? 0);
            if ($paymentTotal <= 0) {
                $paymentTotal = $totalAmount + (float) ($request->tax_amount ?? 0);
            }

            \App\Models\Payment::create([
                'registration_id' => $registration->id,
                'payment_mode' => $request->payment_mode,
                'total_amount' => $paymentTotal,
                'paid_amount' => $paymentTotal,
                'balance_amount' => 0,
                'payment_date' => now(),
                'status' => 'paid',
                'notes' => 'add',
            ]);

            DB::commit();

            return redirect()->route('customers.show', $client->id)->with('success', 'Locker added successfully.');
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error adding locker for client ' . $id . ': ' . $e->getMessage());

            return redirect()->back()->with('error', 'Unable to add locker. Please try again.');
        }
    }

    public function edit($id)
    {
        $client = Client::byTenant()->findOrFail($id);
        $statuses = \App\Models\Status::where('type', 'client')->get();
        $lockers = \App\Models\Locker::all();
        $account_type = \App\Models\AccountType::select('id', 'type_name')->where('status', 1)->get();
        $membership_plan = MembershipPlan::select('id', 'name', 'price')->where('status', 1)->get();
        $locker_groups = LockerGroup::select('id', 'name')->get();
        $countries = Country::select('id', 'name')->where('status', 1)->get();
        return view('clients.create-edit', compact('client', 'statuses', 'lockers', 'account_type', 'membership_plan', 'locker_groups', 'countries'));
    }

    public function update(Request $request, $id)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'contact_person' => 'required|string|max:255',
            'email' => 'required|email',
            'phone' => 'required|string|max:20',
            'alternate_phone' => 'nullable|string|max:20',
            'address' => 'required|string|max:500',
            'city' => 'required|string|max:100',
            'state' => 'required|string|max:100',
            'country' => 'required|string|max:100',
            'postal_code' => 'required|string|max:20',
            'website' => 'nullable|url|max:255',
            'account_type' => 'required|integer|exists:account_types,id',
            'auth_count' => 'required|numeric',
            'gst_number' => 'nullable|string|max:50',
            'pan_number' => 'nullable|string|max:20',
            'payment_terms' => 'required|string|max:50',
            'contract_start_date' => 'nullable|date',
            'contract_end_date' => 'nullable|date|after_or_equal:contract_start_date',
            'status_id' => 'required|exists:statuses,id',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        try {
            DB::beginTransaction();

            $client = Client::byTenant()->findOrFail($id);

            $client->update([
                'name' => $request->name,
                'contact_person' => $request->contact_person,
                'email' => $request->email,
                'phone' => $request->phone,
                'alternate_phone' => $request->alternate_phone,
                'address' => $request->address,
                'city' => $request->city,
                'state' => $request->state,
                'country' => $request->country,
                'postal_code' => $request->postal_code,
                'website' => $request->website,
                'account_type_id' => $request->account_type,
                'auth_count' => $request->auth_count,
                'gst_number' => $request->gst_number,
                'pan_number' => $request->pan_number,
                'payment_terms' => $request->payment_terms,
                'contract_start_date' => $request->contract_start_date,
                'contract_end_date' => $request->contract_end_date,
                'status_id' => $request->status_id,
            ]);

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Client updated successfully',
                'redirect' => route('customers.members')
            ]);
        } catch (\Exception $e) {
            DB::rollBack();

            return response()->json([
                'success' => false,
                'message' => 'Error updating client: ' . $e->getMessage(),
                'errors' => []
            ], 500);
        }
    }

    public function destroy($id)
    {
        try {
            $client = Client::byTenant()->findOrFail($id);

            // Check if client has active contracts
            if ($client->contracts()->where('status_id', Status::getActiveId())->count() > 0) {
                return response()->json(['success' => false, 'message' => 'Cannot delete client with active contracts'], 400);
            }

            $client->delete();

            return response()->json(['success' => true, 'message' => 'Client deleted successfully']);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Error deleting client: ' . $e->getMessage()], 500);
        }
    }

    public function locations()
    {
        $locations = ClientLocation::with('client')
            ->byTenant()
            ->paginate(20);

        // Get filter options
        $clients = \App\Models\Client::byTenant()->active()->pluck('name', 'id');

        return view('clients.locations', compact('locations', 'clients'));
    }

    public function contracts()
    {
        $contracts = ClientContract::with(['client', 'status'])
            ->byTenant()
            ->paginate(20);

        // Get filter options
        $clients = \App\Models\Client::byTenant()->active()->pluck('name', 'id');
        $statuses = \App\Models\Status::where('type', 'contract')->pluck('name', 'id');

        return view('clients.contracts', compact('contracts', 'clients', 'statuses'));
    }

    public function contacts($clientId)
    {
        $client = Client::with(['contacts'])->byTenant()->findOrFail($clientId);
        return view('clients.contacts', compact('client'));
    }

    public function storeContact(Request $request, $clientId)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'email' => 'required|email',
            'phone' => 'required|string|max:20',
            'position' => 'nullable|string|max:255',
            'department' => 'nullable|string|max:255',
            'notes' => 'nullable|string|max:1000',
            'is_primary' => 'boolean',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        try {
            DB::beginTransaction();

            $client = Client::byTenant()->findOrFail($clientId);

            $contact = $client->addContact([
                'name' => $request->name,
                'email' => $request->email,
                'phone' => $request->phone,
                'position' => $request->position,
                'department' => $request->department,
                'notes' => $request->notes,
                'is_primary' => $request->boolean('is_primary', false),
            ]);

            DB::commit();

            return response()->json(['success' => true, 'contact' => $contact]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => 'Error creating contact: ' . $e->getMessage()], 500);
        }
    }

    public function showContact($contactId)
    {
        $contact = ClientContact::with(['client'])->byTenant()->findOrFail($contactId);
        return response()->json($contact);
    }

    public function updateContact(Request $request, $contactId)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'email' => 'required|email',
            'phone' => 'required|string|max:20',
            'position' => 'nullable|string|max:255',
            'department' => 'nullable|string|max:255',
            'notes' => 'nullable|string|max:1000',
            'is_primary' => 'boolean',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        try {
            DB::beginTransaction();

            $contact = ClientContact::byTenant()->findOrFail($contactId);

            $contact->update([
                'name' => $request->name,
                'email' => $request->email,
                'phone' => $request->phone,
                'position' => $request->position,
                'department' => $request->department,
                'notes' => $request->notes,
            ]);

            if ($request->boolean('is_primary', false)) {
                $contact->makePrimary();
            }

            DB::commit();

            return response()->json(['success' => true, 'contact' => $contact]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => 'Error updating contact: ' . $e->getMessage()], 500);
        }
    }

    public function destroyContact($contactId)
    {
        try {
            $contact = ClientContact::byTenant()->findOrFail($contactId);

            if ($contact->is_primary) {
                return response()->json(['success' => false, 'message' => 'Cannot delete primary contact'], 400);
            }

            $contact->delete();

            return response()->json(['success' => true, 'message' => 'Contact deleted successfully']);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Error deleting contact: ' . $e->getMessage()], 500);
        }
    }

    // // Customer Members Management
    // public function members($customerId)
    // {
    //     $client = Client::byTenant()
    //         ->with(['lockerRegistrations' => function ($query) {
    //             $query->with(['items', 'membershipPlan'])->where('status', 'Active');
    //         }])
    //         ->findOrFail($customerId);

    //     $members = $client->customerMembers()
    //         ->with('statusRelation')
    //         ->where('is_active', 1)
    //         ->get();

    //     return view('clients.members', compact('client', 'members'));
    // }

    public function members($customerId)
    {
        $client = Client::byTenant()
            ->with(['lockerRegistrations' => function ($query) {
                $query->with(['items', 'membershipPlan'])
                    ->where('status', 'Active');
            }])
            ->findOrFail($customerId);

        $members = $client->customerMembers()
            ->with('statusRelation')
            ->where('is_active', 1)
            ->get();

        // Calculate dynamically
        $authCount = $members->count();

        return view('clients.members', compact('client', 'members', 'authCount'));
    }

    public function storeMember(Request $request, $customerId)
    {
        $request->merge([
            'status' => 2
        ]);

        $validator = Validator::make($request->all(), [
            'name' => 'required|string|min:2|max:255',
            'email' => 'nullable|email|unique:customer_members,email,NULL,id,client_id,' . $customerId,
            'mobile' => 'required|digits:10',
            'proof_type' => 'required|string|in:passport,ic_number',
            'proof_number' => 'required|string|min:5|max:100',
            'address' => 'nullable|string|max:500',
            'finger_auth' => 'boolean',
            'face_auth' => 'required|boolean',
            'required_auth' => 'boolean',
            // 'status' => 2,
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        try {
            $client = Client::byTenant()->findOrFail($customerId);

            $authRequiredCount = $client->authorized_count; // authorized_count
            $currentRequiredCount = CustomerMember::where('client_id', $customerId)
                ->where('required_auth', 1)
                ->where('is_active', 1)
                ->count();

            if ($request->boolean('required_auth')) {
                if ($authRequiredCount <= $currentRequiredCount) {
                    return response()->json([
                        'success' => false,
                        'message' => "Cannot add more required members. Maximum limit reached: {$currentRequiredCount}/{$authRequiredCount}"
                    ], 422);
                }
            }

            // Check if adding member exceeds auth_count limit
            $currentMembersCount = $client->customerMembers()
                ->where('is_active', 1)
                ->count();

            // Calculate max auth count from locker registrations
            $maxAuthCount = $client->lockerRegistrations->sum('auth_count') ?: $client->auth_count;

            if ($currentMembersCount >= $maxAuthCount) {
                return response()->json([
                    'success' => false,
                    'message' => "Cannot add more members. Maximum limit reached: {$currentMembersCount}/{$maxAuthCount}"
                ], 422);
            }

            $member = $client->customerMembers()->create([
                'name' => $request->name,
                'email' => $request->email,
                'mobile' => $request->mobile,
                'proof_type' => $request->proof_type,
                'proof_number' => $request->proof_number,
                'address' => $request->address,
                'finger_auth' => $request->boolean('finger_auth'),
                'face_auth' => $request->boolean('face_auth'),
                'required_auth' => $request->boolean('required_auth'),
                'status' => $request->status ?? 1, // Default to active if not provided
                'is_active' => true,
                // 'tenant_id' => $client->tenant_id,
            ]);

            // Return a clean array to avoid JSON serialization issues
            $response = [
                'success' => true,
                'member' => [
                    'id' => $member->id,
                    'name' => $member->name,
                    'email' => $member->email,
                    'mobile' => $member->mobile,
                    'address' => $member->address,
                    'finger_auth' => $member->finger_auth,
                    'face_auth' => $member->face_auth,
                    'required_auth' => $member->required_auth,
                    'is_finger_verified' => $member->is_finger_verified,
                    'status' => $member->status,
                    'is_active' => $member->is_active,
                    'created_at' => $member->created_at,
                    'updated_at' => $member->updated_at,
                ]
            ];

            // Clean any output buffers and return JSON
            if (ob_get_level()) {
                ob_clean();
            }

            return response()->json($response);
        } catch (\Exception $e) {
            // Clean any output buffers and return JSON
            if (ob_get_level()) {
                ob_clean();
            }
            return response()->json(['success' => false, 'message' => 'Error adding member: ' . $e->getMessage()], 500);
        }
    }

    public function showMember($memberId)
    {
        try {
            $member = CustomerMember::findOrFail($memberId);

            return response()->json([
                'success' => true,
                'member' => [
                    'id' => $member->id,
                    'name' => $member->name,
                    'email' => $member->email,
                    'mobile' => $member->mobile,
                    'proof_type' => $member->proof_type,
                    'proof_number' => $member->proof_number,
                    'address' => $member->address,
                    'finger_auth' => $member->finger_auth,
                    'face_auth' => $member->face_auth,
                    'required_auth' => $member->required_auth,
                    'is_finger_verified' => $member->is_finger_verified,
                    'status' => $member->status,
                    'is_active' => $member->is_active,
                    'created_at' => $member->created_at,
                    'updated_at' => $member->updated_at,
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error loading member',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function updateMember(Request $request, $memberId)
    {
        $member = CustomerMember::findOrFail($memberId);

        $validator = Validator::make($request->all(), [
            'name' => 'required|string|min:2|max:255',
            'email' => 'nullable|email|unique:customer_members,email,' . $memberId . ',id,client_id,' . $member->client_id,
            'mobile' => 'required|string|max:20',
            'proof_type' => 'required|string|max:50',
            'proof_number' => 'required|string|min:5|max:100',
            'address' => 'nullable|string|max:500',
            'face_auth' => 'required|boolean',
            'finger_auth' => 'boolean',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        try {

            $customerId = $member->client_id;

            $client = Client::byTenant()->findOrFail($customerId);

            $authRequiredCount = $client->authorized_count; // authorized_count

            // $currentRequiredCount = CustomerMember::where('client_id', $customerId)
            //     ->where('required_auth', 1)
            //     ->count();
            $currentRequiredCount = CustomerMember::where('client_id', $customerId)
                ->where('required_auth', 1)
                ->where('id', '!=', $memberId) // IMPORTANT
                ->count();

            if ($request->boolean('required_auth')) {
                if ($authRequiredCount <= $currentRequiredCount) {
                    return response()->json([
                        'success' => false,
                        'message' => "Cannot add more required members. Maximum limit reached: {$currentRequiredCount}/{$authRequiredCount}"
                    ], 422);
                }
            }
            $updateData = [
                'name' => $request->name,
                'email' => $request->email,
                'mobile' => $request->mobile,
                'proof_type' => $request->proof_type,
                'proof_number' => $request->proof_number,
                'required_auth' => $request->boolean('required_auth'),
                'address' => $request->address,
                'finger_auth' => $request->boolean('finger_auth'),
                'face_auth' => $request->boolean('face_auth'),
            ];

            $member->update($updateData);

            // Clean any output buffers at start
            if (ob_get_level()) {
                ob_clean();
            }

            return response()->json([
                'success' => true,
                'member' => [
                    'id' => $member->id,
                    'name' => $member->name,
                    'email' => $member->email,
                    'mobile' => $member->mobile,
                    'address' => $member->address,
                    'finger_auth' => $member->finger_auth,
                    'is_finger_verified' => $member->is_finger_verified,
                    'created_at' => $member->created_at,
                    'updated_at' => $member->updated_at,
                ]
            ]);
        } catch (\Exception $e) {
            // Clean any output buffers and return JSON
            if (ob_get_level()) {
                ob_clean();
            }
            return response()->json(['success' => false, 'message' => 'Error updating member: ' . $e->getMessage()], 500);
        }
    }

    public function verifyFinger(Request $request, $memberId)
    {
        try {
            // Clean any output buffers at the very start
            while (ob_get_level()) {
                ob_end_clean();
            }

            $member = CustomerMember::findOrFail($memberId);

            // Check if fingerprint authentication is enabled for this member
            if (!$member->finger_auth) {
                return response()->json([
                    'success' => false,
                    'message' => 'Fingerprint authentication is not enabled for this member.'
                ], 400);
            }

            // In a real implementation, this would integrate with fingerprint hardware
            // For now, we'll simulate verification by marking as verified
            $member->update([
                'status' => 1,
                'is_finger_verified' => true,
                'finger_verified_at' => now(),
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Fingerprint verified successfully.',
                'member' => $member->only([
                    'id',
                    'name',
                    'email',
                    'mobile',
                    'address',
                    'finger_auth',
                    'is_finger_verified',
                    'status',
                    'is_active',
                    'created_at',
                    'updated_at'
                ])
            ]);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return response()->json([
                'success' => false,
                'message' => 'Member not found.'
            ], 404);
        } catch (\Exception $e) {
            Log::error('Error verifying fingerprint: ' . $e->getMessage(), [
                'member_id' => $memberId,
                'exception' => $e
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while verifying fingerprint.'
            ], 500);
        }
    }

    public function storeFace(Request $request, $memberId)
    {
        try {
            // Clean any output buffers at the very start
            while (ob_get_level()) {
                ob_end_clean();
            }

            $member = CustomerMember::findOrFail($memberId);

            // Check if face authentication is enabled for this member
            if (!$member->face_auth) {
                return response()->json([
                    'success' => false,
                    'message' => 'Face authentication is not enabled for this member.'
                ], 400);
            }

            // Validate request data
            $validator = Validator::make($request->all(), [
                'face_descriptor' => 'required|string',
                'landmarks' => 'nullable|string'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid face data provided.',
                    'errors' => $validator->errors()
                ], 422);
            }

            // Store face descriptor in database
            $member->update([
                'face_descriptor' => $request->face_descriptor,
                'is_face_verified' => 1,
                'status' => 1
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Face data stored successfully.',
                'member' => $member->only([
                    'id',
                    'name',
                    'email',
                    'mobile',
                    'face_auth',
                    'face_descriptor',
                    'is_face_verified',
                    'status',
                    'updated_at'
                ])
            ]);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return response()->json([
                'success' => false,
                'message' => 'Member not found.'
            ], 404);
        } catch (\Exception $e) {
            Log::error('Error storing face data: ' . $e->getMessage(), [
                'member_id' => $memberId,
                'exception' => $e
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while storing face data.'
            ], 500);
        }
    }

    public function verifyFace(Request $request, $memberId)
    {
        try {
            // Clean any output buffers at the very start
            while (ob_get_level()) {
                ob_end_clean();
            }

            $member = CustomerMember::findOrFail($memberId);

            // Check if face authentication is enabled for this member
            if (!$member->face_auth) {
                return response()->json([
                    'success' => false,
                    'message' => 'Face authentication is not enabled for this member.'
                ], 400);
            }

            // Validate request data
            $validator = Validator::make($request->all(), [
                'face_descriptor' => 'required|string'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid face data provided.',
                    'errors' => $validator->errors()
                ], 422);
            }

            // Check if member has stored face descriptor
            if (!$member->face_descriptor) {
                return response()->json([
                    'success' => false,
                    'message' => 'No face data found for this member. Please capture face data first.'
                ], 400);
            }

            // Compare face descriptors
            $storedDescriptor = json_decode($member->face_descriptor, true);
            $currentDescriptor = json_decode($request->face_descriptor, true);

            if (!$storedDescriptor || !$currentDescriptor) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid face descriptor format.'
                ], 400);
            }

            // Calculate similarity (cosine similarity)
            $similarity = $this->calculateFaceSimilarity($storedDescriptor, $currentDescriptor);

            // Threshold for verification (adjust as needed)
            $threshold = 0.6;

            if ($similarity >= $threshold) {
                // Update member verification status
                $member->update([
                    'is_face_verified' => true
                ]);

                return response()->json([
                    'success' => true,
                    'message' => 'Face verified successfully.',
                    'similarity' => round($similarity, 3),
                    'member' => $member->only([
                        'id',
                        'name',
                        'email',
                        'mobile',
                        'face_auth',
                        'is_face_verified'
                    ])
                ]);
            } else {
                return response()->json([
                    'success' => false,
                    'message' => 'Face verification failed. Similarity too low.',
                    'similarity' => round($similarity, 3),
                    'threshold' => $threshold
                ], 400);
            }
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return response()->json([
                'success' => false,
                'message' => 'Member not found.'
            ], 404);
        } catch (\Exception $e) {
            Log::error('Error verifying face: ' . $e->getMessage(), [
                'member_id' => $memberId,
                'exception' => $e
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while verifying face.'
            ], 500);
        }
    }

    private function calculateFaceSimilarity($descriptor1, $descriptor2)
    {
        // Calculate cosine similarity between two face descriptors
        $dotProduct = 0;
        $norm1 = 0;
        $norm2 = 0;

        for ($i = 0; $i < min(count($descriptor1), count($descriptor2)); $i++) {
            $dotProduct += $descriptor1[$i] * $descriptor2[$i];
            $norm1 += $descriptor1[$i] * $descriptor1[$i];
            $norm2 += $descriptor2[$i] * $descriptor2[$i];
        }

        $norm1 = sqrt($norm1);
        $norm2 = sqrt($norm2);

        if ($norm1 == 0 || $norm2 == 0) {
            return 0;
        }

        return $dotProduct / ($norm1 * $norm2);
    }

    public function destroyMember($memberId)
    {
        try {
            // Clean any output buffers at very start
            while (ob_get_level()) {
                ob_end_clean();
            }

            $member = CustomerMember::findOrFail($memberId);

            // Set status to 3 (Inactive) instead of deleting
            $member->update([
                'status' => 3,
                'is_active' => false,
                'updated_at' => now(),
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Member deactivated successfully.',
                'member' => $member->only([
                    'id',
                    'name',
                    'email',
                    'mobile',
                    'address',
                    'finger_auth',
                    'is_finger_verified',
                    'status',
                    'is_active',
                    'created_at',
                    'updated_at'
                ])
            ]);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return response()->json([
                'success' => false,
                'message' => 'Member not found.'
            ], 404);
        } catch (\Exception $e) {
            Log::error('Error deactivating member: ' . $e->getMessage(), [
                'member_id' => $memberId,
                'exception' => $e
            ]);

            return response()->json([
                'success' => false,
                'message' => 'An error occurred while deactivating the member.'
            ], 500);
        }
    }

    /**
     * Search members for dropdown
     */
    public function searchMembers(Request $request)
    {
        try {
            $query = CustomerMember::with('client:id,name')
                ->select('id', 'name', 'mobile', 'client_id');

            if ($request->filled('search')) {
                $search = $request->search;
                $query->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                        ->orWhere('mobile', 'like', "%{$search}%");
                });
            }

            $members = $query->orderBy('name')->limit(20)->get();

            $formattedMembers = $members->map(function ($member) {
                return [
                    'id' => $member->id,
                    'name' => $member->name,
                    'phone' => $member->mobile,
                    'client_name' => $member->client ? $member->client->name : 'N/A',
                    'display_name' => $member->name . ' (' . ($member->client ? $member->client->name : 'N/A') . ')'
                ];
            });

            return response()->json($formattedMembers->values());
        } catch (\Throwable $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error searching members',
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get available lockers for selection
     */
    public function getAvailableLockers(Request $request)
    {
        try {
            $query = Locker::query();

            // Filter by size if specified
            if ($request->filled('size')) {
                $query->where('locker_size', $request->size);
            }

            // Filter by row if specified
            if ($request->filled('row')) {
                $query->where('locker_row_column', 'like', $request->row . 'C%');
            }

            // Filter by type if specified
            if ($request->filled('type')) {
                $query->where('locker_type', $request->type);
            }

            // Filter by group if specified
            if ($request->filled('group')) {
                $query->where('locker_group_id', $request->group);
            }

            // Filter by status if specified
            if ($request->filled('status')) {
                $query->where('status', ucfirst($request->status));
            }

            // If no status filter is specified, get all lockers for dashboard
            // If status is explicitly empty or not provided, get all lockers
            if (!$request->has('status') || $request->status === '') {
                $query->where('status', 'Available');
                $query->leftJoin('locker_groups', 'lockers.locker_group_id', '=', 'locker_groups.id')
                    ->select('lockers.*', 'locker_groups.name as name');

                $lockers = $query->orderBy('lockers.locker_number')->get();
            } else {
                // If status is specified (even if empty), filter by that status
                if ($request->status === '') {
                    // For client selection, default to available only
                    $query->where('status', 'Available');
                }
                $query->leftJoin('locker_groups', 'lockers.locker_group_id', '=', 'locker_groups.id')
                    ->select('lockers.*', 'locker_groups.name as name');

                $lockers = $query->orderBy('lockers.locker_number')->get();
            }

            return response()->json([
                'success' => true,
                'lockers' => $lockers
            ]);
        } catch (\Exception $e) {
            Log::error('Error fetching available lockers: ' . $e->getMessage());

            return response()->json([
                'success' => false,
                'message' => 'Error fetching lockers'
            ], 500);
        }
    }

    /**
     * Update authorized count for a client
     */
    // public function updateAuthCount(Request $request, $customerId)
    // {
    //     try {
    //         // Find the client explicitly
    //         $client = Client::findOrFail($customerId);

    //         // Validate the request
    //         $validator = Validator::make($request->all(), [
    //             'auth_count' => 'required|integer|min:1|max:999'
    //         ], [
    //             'auth_count.required' => 'Authorized count is required',
    //             'auth_count.integer' => 'Authorized count must be a number',
    //             'auth_count.min' => 'Authorized count must be at least 1',
    //             'auth_count.max' => 'Authorized count cannot exceed 999'
    //         ]);

    //         if ($validator->fails()) {
    //             return response()->json([
    //                 'success' => false,
    //                 'message' => $validator->errors()->first()
    //             ], 422);
    //         }

    //         $newAuthCount = $request->input('auth_count');
    //         $currentMembersCount = $client->customerMembers()->count();

    //         // For authorized_count (minimum allowed), we don't need to check against current members
    //         // as this represents the minimum baseline, not the maximum limit

    //         // But we should ensure minimum doesn't exceed maximum limit
    //         $maxAuthCount = $client->lockerRegistrations->sum('auth_count') ?: $client->auth_count;
    //         if ($newAuthCount > $maxAuthCount) {
    //             return response()->json([
    //                 'success' => false,
    //                 'message' => "Minimum allowed ({$newAuthCount}) cannot be more than maximum limit ({$maxAuthCount})"
    //             ], 422);
    //         }

    //         // Check limit required member count
    //         $currentRequiredCount = CustomerMember::where('client_id', $customerId)->where('required_auth', 1)->count();

    //         if ($newAuthCount < $currentRequiredCount) {
    //             return response()->json([
    //                 'success' => false,
    //                 'message' => "Cannot set minimum to {$newAuthCount}. You already have {$currentRequiredCount} required members. Minimum must be at least {$currentRequiredCount}."
    //             ], 422);
    //         }

    //         // Update the client's authorized count (minimum allowed members)
    //         $client->authorized_count = $newAuthCount;
    //         $client->save();

    //         Log::info("Updated authorized count (minimum allowed) for client {$client->id} ({$client->name}) from {$client->getOriginal('authorized_count')} to {$newAuthCount}");

    //         return response()->json([
    //             'success' => true,
    //             'message' => "Authorized count updated successfully to {$newAuthCount}",
    //             'auth_count' => $newAuthCount
    //         ]);
    //     } catch (\Exception $e) {
    //         Log::error('Error updating authorized count: ' . $e->getMessage());

    //         return response()->json([
    //             'success' => false,
    //             'message' => 'Failed to update authorized count. Please try again.'
    //         ], 500);
    //     }
    // }

    public function updateAuthCount(Request $request, $customerId)
    {
        try {
            $client = Client::findOrFail($customerId);

            $validator = Validator::make($request->all(), [
                'auth_count' => 'required|integer|min:1|max:999'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'success' => false,
                    'message' => $validator->errors()->first()
                ], 422);
            }

            $newAuthCount = $request->input('auth_count');

            // FIX 1: Get ACTIVE registration only
            $activeRegistration = $client->lockerRegistrations()
                ->where('status', 'Active')
                ->latest()
                ->first();

            $maxAuthCount = $activeRegistration ? $activeRegistration->auth_count : 0;

            // Prevent exceeding contract limit
            if ($newAuthCount > $maxAuthCount) {
                return response()->json([
                    'success' => false,
                    'message' => "Cannot exceed contract limit ({$maxAuthCount})"
                ], 422);
            }

            // FIX 2: Get current members count (ACTIVE ONLY and REQUIRED)
            $currentMembersCount = $client->customerMembers()
                ->where('required_auth', 1)
                ->where('is_active', 1)
                ->count();

            // Prevent reducing below current members
            if ($newAuthCount < $currentMembersCount) {
                return response()->json([
                    'success' => false,
                    'message' => "You already have {$currentMembersCount} members. Cannot set less than that."
                ], 422);
            }

            // Required members check (your logic)
            $currentRequiredCount = CustomerMember::where('client_id', $customerId)
                ->where('required_auth', 1)
                ->count();

            if ($newAuthCount < $currentRequiredCount) {
                return response()->json([
                    'success' => false,
                    'message' => "Minimum must be at least {$currentRequiredCount}"
                ], 422);
            }

            // SAVE
            $client->authorized_count = $newAuthCount;
            $client->save();

            return response()->json([
                'success' => true,
                'message' => "Authorized count updated to {$newAuthCount}"
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error updating authorized count'
            ], 500);
        }
    }

    /**
     * Generate random password for locker
     */
    private function generateLockerPassword(): string
    {
        // Generate 6-character alphanumeric password
        $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $password = '';

        for ($i = 0; $i < 6; $i++) {
            $password .= $characters[rand(0, strlen($characters) - 1)];
        }

        return $password;
    }
}
