<?php

declare(strict_types=1);

namespace App\Http\Controllers\Backend;

use App\Http\Controllers\Controller;
use App\Http\Requests\AdminRequest;
use App\Models\Admin;
use App\Models\Country;
use App\Models\State;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Spatie\Permission\Models\Role;
use Illuminate\Http\Request;
use Yajra\DataTables\DataTables;
use Auth;

class FranchiseController extends Controller
{
	public function index(): Renderable
	{
		// Ensure the user has the 'franchise.view' permission
		$this->checkAuthorization(auth()->user(), ['franchise.view']);

		// Get all channel partners with 'franchise' role
		$channelpartners = Admin::with('children')->whereHas('roles', function ($q) {
			$q->where('name', 'franchise');
		})->get();

		return view('backend.pages.franchise.index', [
			'admins' => $channelpartners,
			'visited' => []
		]);
	}


/**
 * Get all users in the referral hierarchy recursively for a given user.
 *
 * @param  int  $userId
 * @param  array  &$visited
 * @return \Illuminate\Support\Collection
 */
public function getReferralHierarchy($userId, array &$visited)
{
    $user = Admin::find($userId);

    if (!$user) {
        return collect(); // Return an empty collection if the user does not exist
    }

    return $this->getChildrenRecursively($user, $visited);
}

/**
 * Recursively get children of a given user, preventing infinite loops.
 *
 * @param  Admin  $user
 * @param  array  &$visited
 * @return \Illuminate\Support\Collection
 */
private function getChildrenRecursively(Admin $user, array &$visited)
{
    $userId = $user->id;

    // Avoid revisiting nodes
    if (in_array($userId, $visited)) {
        return collect(); // Return an empty collection to prevent recursion
    }

    // Mark the current user as visited
    $visited[] = $userId;

    // Get the children of the current user
    $children = $user->children;

    // Initialize the result collection with the current user
    $result = collect([$user]);

    foreach ($children as $child) {
        // Pass the updated visited array by reference to avoid infinite loops
        $result = $result->merge($this->getChildrenRecursively($child, $visited));
    }

    return $result;
}

    public function create(): Renderable
    {
        $this->checkAuthorization(auth()->user(), ['franchise.create']);
		$countries = Country::all();
		$roles = Role::all();
        return view('backend.pages.franchise.create', compact('roles', 'countries'));
    }

    public function store(AdminRequest $request): RedirectResponse
    {
        $this->checkAuthorization(auth()->user(), ['franchise.create']);
		if(in_array('franchise',$request->roles))
		{
			$generateReferralId = $this->generateFranchiseReferralId();
		}
		else
		{
			$generateReferralId = $this->generateChannalReferralId();
		}
        $admin = new Admin();
        $admin->title = $request->title; 
        $admin->username = $request->username; 
        $admin->first_name = $request->first_name; 
        $admin->middle_name = $request->middle_name; 
        $admin->last_name = $request->last_name; 
        $admin->father_name = $request->father_name; 
        $admin->mobile = $request->mobile;
        $admin->email = $request->email;
        $admin->address = $request->address; 
        $admin->country_id = $request->country; 
        $admin->state_id = $request->state; 
        $admin->city = $request->city; 
        $admin->years_of_exp = $request->years_of_exp; 
        $admin->company_name = $request->company_name; 
        $admin->company_gst = $request->company_gst; 
        $admin->education_qualification = $request->education_qualification; 
        $admin->my_referral_id = $request->my_referral_id; 
        $admin->referral_id = $generateReferralId; // Generate or assign your logic

        // Add nominee details
        $admin->nominee_name = $request->nominee_name;
        $admin->nominee_relationship = $request->nominee_relationship;
        $admin->nominee_contact = $request->nominee_contact;

        // Add bank details
        $admin->bank_name = $request->bank_name;
        $admin->account_number = $request->account_number;
        $admin->ifsc_code = $request->ifsc_code;
        $admin->account_type = $request->account_type;
		$admin->pan = $request->pan; 
		$admin->aadhar_number = $request->aadhar_number; // New field
        $admin->password = Hash::make($request->password);
        $admin->name = trim("{$request->first_name} {$request->middle_name} {$request->last_name}");
        $admin->save();

        if ($request->roles) {
            $admin->assignRole(['franchise']);
        }

        session()->flash('success', __('Franchise has been created.'));
        return redirect()->route('admin.franchise.index');
    }

    public function edit(int $id): Renderable
    {
		
        $this->checkAuthorization(auth()->user(), ['franchise.edit']);

        $admin = Admin::findOrFail($id);
        $countries = Country::all();
        $roles = Role::all();
        $states = State::all();
        return view('backend.pages.franchise.edit', compact('admin', 'countries', 'roles', 'states'));
    }

    public function update(AdminRequest $request, int $id): RedirectResponse
    {
        $this->checkAuthorization(auth()->user(), ['franchise.edit']);

        $admin = Admin::findOrFail($id);
        $admin->username = $request->username; 
        $admin->title = $request->title; 
        $admin->first_name = $request->first_name; 
        $admin->middle_name = $request->middle_name; 
        $admin->last_name = $request->last_name; 
        $admin->father_name = $request->father_name; 
        $admin->mobile = $request->mobile;
        $admin->email = $request->email;
        $admin->address = $request->address; 
        $admin->country_id = $request->country; 
        $admin->state_id = $request->state; 
        $admin->city = $request->city; 
        $admin->years_of_exp = $request->years_of_exp; 
        $admin->company_name = $request->company_name; 
        $admin->company_gst = $request->company_gst; 
        $admin->education_qualification = $request->education_qualification; 
        $admin->my_referral_id = $request->my_referral_id; 

        // Update nominee details
        $admin->nominee_name = $request->nominee_name;
        $admin->nominee_relationship = $request->nominee_relationship;
        $admin->nominee_contact = $request->nominee_contact;

        // Update bank details
        $admin->bank_name = $request->bank_name;
        $admin->account_number = $request->account_number;
        $admin->ifsc_code = $request->ifsc_code;
        $admin->account_type = $request->account_type;
		$admin->pan = $request->pan; 
		$admin->aadhar_number = $request->aadhar_number; // New field
        $admin->name = trim("{$request->first_name} {$request->middle_name} {$request->last_name}");
        if ($request->password) {
            $admin->password = Hash::make($request->password);
        }
        
        $admin->save();

        $admin->roles()->detach();
        

        session()->flash('success', 'Franchise has been updated.');
        return back();
    }

    public function destroy(int $id): RedirectResponse
    {
        $this->checkAuthorization(auth()->user(), ['franchise.delete']);

        $admin = Admin::findOrFail($id);
        $admin->delete();
        session()->flash('success', 'Franchise has been deleted.');
        return back();
    }

   protected function generateChannalReferralId()
	{
		$prefix = 'GIOCP';
		// Get the last referral ID from the Admin table
		$lastReferral = Admin::where('referral_id', 'LIKE', "{$prefix}%")->orderBy('referral_id', 'desc')->first();

		// Extract the numeric part and increment it
		if (!empty($lastReferral->referral_id)) {
			// Get the numeric part after the prefix (e.g., "GIOCP" or "FR")
			$lastId = intval(substr($lastReferral->referral_id, strlen($prefix))); 
			// Increment the ID and pad with zeros to ensure 5 digits
			$newId = str_pad((string)($lastId + 1), 5, '0', STR_PAD_LEFT); 
		} else {
			// If no referral ID exists, start from 00001
			$newId = '00001';
		}

		// Return the new Referral ID with the prefix
		return $prefix . $newId;
	}

	protected function generateFranchiseReferralId()
	{
		// Define the prefix
		$prefix = "FR";

		// Get the last referral ID from the Admin table that matches the pattern
		$lastReferral = Admin::where('referral_id', 'LIKE', "{$prefix}%")
			->orderBy('referral_id', 'desc')
			->first();

		// Extract the numeric part and increment it
		if (!empty($lastReferral) && !empty($lastReferral->referral_id)) {
			// Get the numeric part after the prefix
			$lastId = intval(substr($lastReferral->referral_id, strlen($prefix)));
			// Increment the ID and pad with zeros to ensure 5 digits
			$newId = str_pad((string)($lastId + 1), 5, '0', STR_PAD_LEFT);
		} else {
			// If no referral ID exists, start from 00001
			$newId = '00001';
		}

		// Return the new Referral ID with the prefix
		return $prefix . $newId;
	}


    public function getStates(Request $request)
    {
        $countryId = $request->input('country_id');
        $states = State::where('country_id', $countryId)->select('state_id', 'name')->get();
        return response()->json($states);
    }
	
	
	

   



}
