<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\AdvanceSetting;
use App\Models\Company;
use App\Models\CompanyAddress;
use App\Models\FinancialYear;
use App\Models\Library\BookApi;
use App\Models\LibrarySetting\LibrarianGernes;
use App\Models\LicenseAuthentication;
use App\Models\LicenseDetail;
use App\Models\LicenseRegistered;
use App\Models\MenuModelPermission;
use App\Models\PlanModuleMapping;
use App\Models\StorageSetting;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Session;
use Spatie\Permission\Models\Permission;

class LoginController extends Controller {
    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = RouteServiceProvider::HOME;
    protected $licenseCheckResponse;
    /**
     * Show the application's login form.
     *
     * @return \Illuminate\View\View
     */
    public function showLoginForm() {
        $license = LicenseAuthentication::orderBy('is_default')->first();

        if (!$license) {
            Session::flush();
            Auth::logout();

            return Redirect('client-license-register')->with('error', 'No license found! Please contact administrator');
        }

        $companyData = Company::with('getCompanyImage')->select('id', 'name', 'logo')->where('office_type', 'head_office')->first();

        return view('auth.login', compact('companyData'));
    }

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct() {
        $this->middleware('guest')->except('logout');
    }

    // public function login(Request $request) {
    //     $this->validateLogin($request);

    //     if ($this->hasTooManyLoginAttempts($request)) {
    //         return $this->sendLockoutResponse($request);
    //     }

    //     if ($this->attemptLogin($request)) {
    //         if (!$this->licenseCheck()) {
    //             return redirect('login')->with('error', 'License validation failed.');
    //         }

    //         $this->handleSuccessfulLogin($request);

    //         return $this->sendLoginResponse($request);
    //     }

    //     $this->incrementLoginAttempts($request);

    //     return $this->sendFailedLoginResponse($request);
    // }
    public function login(Request $request) {
        $this->validateLogin($request);

        if ($this->hasTooManyLoginAttempts($request)) {
            return response()->json(['message' => 'Too many login attempts. Please try again later.', 'success' => false]);
        }

        if ($this->attemptLogin($request)) {
            if (Auth()->user()->status != 1) {
                Session::flush();
                Auth::logout();

                return response()->json(['message' => 'Inactive user status! Please contact administrator.', 'success' => false]);
            }

            if (!$this->licenseCheck()) {
                return response()->json(['message' => 'License validation failed.', 'success' => false]);
            }

            $this->handleSuccessfulLogin($request);

            // Return JSON response with success message or any additional data
            return response()->json(['success' => true, 'message' => 'Login successful.']);
        }

        $this->incrementLoginAttempts($request);

        // Return JSON response with login failure message
        return response()->json(['message' => 'Invalid credentials.', 'success' => false]);
    }


    protected function handleSuccessfulLogin(Request $request) {
        if ($request->hasSession()) {
            $request->session()->put('auth.password_confirmed_at', time());
        }

        $this->setRolePermissions();
        $this->setModulePermissions();
        $this->setCompanyData();
        $this->setFinancialYear();
        $this->setHeadOfficeData();
        // $this->setBookApiData();
        $this->setDecimalPoints();
        $this->setSessionBucketData();
    }

    protected function licenseCheck() {
        $license = LicenseAuthentication::orderBy('is_default')->first();

        if (!$license) {
            Session::flush();
            Auth::logout();

            return false;
        }

        $response = Http::asForm()->post($license->api_endpoint, [
            'license_key'    => $license->license_key,
            'license_secret' => $license->license_secret,
        ]);

        $this->licenseCheckResponse = json_decode($response->body(), true);

        if ((isset($this->licenseCheckResponse['success']) && !$this->licenseCheckResponse['success']) || !isset($this->licenseCheckResponse['success'])) {
            Session::flush();
            Auth::logout();

            return false;
        }

        return true;
    }

    protected function setRolePermissions() {
        $roles = Auth::user()->roles->pluck('id')->all();

        $rolePermissions = Permission::select('permissions.name')
            ->join("role_has_permissions", "role_has_permissions.permission_id", "=", "permissions.id")
            ->whereIn("role_has_permissions.role_id", $roles)
            ->groupBy('permissions.id')
            ->get();

        $permissionsArray = $rolePermissions->pluck('name')->mapWithKeys(function($permission) {
            return [$permission => $permission];
        })->toArray();

        Session::put('rolePermissions', $permissionsArray);
    }

    protected function setModulePermissions() {
        $moduleCodes = [];

        if (isset($this->licenseCheckResponse['permissions'])) {
            $moduleCodes = $this->licenseCheckResponse['permissions'] ?? [];
        }
        // For localhost
        // $moduleCodes = MenuModelPermission::select('code')
        //     ->orderBy('priority', 'ASC')
        //     ->get()->pluck('code')->toArray();

        Session::put('modulePermissions', $moduleCodes);
        $allModules = MenuModelPermission::select('menu_name', 'code', 'route', 'icon', 'module_type', 'priority', 'permissions.name as permission')
            ->leftjoin('permissions', function ($join) {
                $join->on('permissions.module_id', '=', 'menu_model_permissios.id')
                    ->where('permissions.name', 'LIKE', '%-list%');
            })
            ->with('listingPermissions')
            ->whereIn('code', $moduleCodes)
            ->orderBy('priority', 'ASC')
            ->get();

        $modules = $allModules->where('parent_id', null)->keyBy('code')->toArray();

        $leftMenuModules  = $allModules->where('module_type', 'left_menu');
        $topMenuModules   = $allModules->where('module_type', 'top_menu');
        $quickMenuModules = $allModules->where('module_type', 'quick_menu');

        Session::put('menuModules', $modules);
        Session::put('leftMenuModules', $leftMenuModules);
        Session::put('topMenuModules', $topMenuModules);
        Session::put('quickMenuModules', $quickMenuModules);
    }

    protected function setCompanyData() {
        $company_data = DB::table('companies')
            ->select('companies.*', 'timezones.name as time_zone', 'countries.currency_symbol', 'countries.formats', 'countries.code as country_code', 'companies_addresses.*', 'country_currencies.id as currency_id', 'country_currencies.code as currency_code', 'country_currencies.currency')
            ->leftjoin('timezones', 'timezones.id', 'companies.time_zone')
            ->leftjoin('companies_addresses', 'companies.id', 'companies_addresses.company_id')
            ->leftjoin('countries', 'countries.id', 'companies_addresses.country_id')
            ->leftjoin('country_currencies', 'country_currencies.country_id', 'companies_addresses.country_id')
            ->where('companies.id', Auth::user()->company_id)
            ->first();

        $company_data = (array)$company_data; // Convert to array

        $company_data['auth_currency']       = $company_data['currency_symbol'] ?? 'USD';
        $company_data['auth_formats']        = $company_data['formats']         ?? 'm-d-Y';
        $company_data['companies_addresses'] = [
            'address_1'          => $company_data['address_1'],
            'address_2'          => $company_data['address_2'],
            'country_id'         => $company_data['country_id'],
            'state_id'           => $company_data['state_id'],
            'city_id'            => $company_data['city_id'],
            'pin_code'           => $company_data['pin_code'],
            'google_place_link'  => $company_data['google_place_link'],
            'location_latitude'  => $company_data['location_latitude'],
            'location_longitude' => $company_data['location_longitude'],
            'is_default'         => $company_data['is_default'],
            'status'             => $company_data['status'],
            'priority'           => $company_data['priority'],
            'district_name'      => $company_data['district_name'],
            'taluka_name'        => $company_data['taluka_name'],
            'address_type_id'    => $company_data['address_type_id'],
            'time_zone'          => $company_data['time_zone'],
        ];

        Session::put('company_data', $company_data);
    }

    protected function setFinancialYear() {
        $company_id = Auth::user()->company_id;

        // Get all financial years for the company in one query
        $financialYears = FinancialYear::select([
            'financialyearid',
            'financial_year_end_date',
            'financial_year_name',
            'company_id',
            'status',
            'is_default'
        ])
            ->where('company_id', $company_id)
            ->where('status', '1')
            ->orderBy('is_default', 'desc')
            ->get();
        // Get the latest financial year
        $financial_year = $financialYears->first();

        Session::put('financial_year', $financial_year);

        $financial_year_id = Auth::user()->my_financial_year_id;

        if (empty($financial_year_id) && $company_id) {
            // Get the default financial year from the already retrieved financial years
            $financialYear     = $financialYears->where('is_default', 1)->first();
            $financial_year_id = $financialYear->financialyearid ?? '';
        }

        Session::put('user_financial_year_id', $financial_year_id);
        // The financial years are already retrieved, no need for an extra query
        Session::put('financialyear', $financialYears);
    }

    protected function setHeadOfficeData() {
        $HeadOfficeData = Company::select('name', 'id', 'logo')->where('office_type', 'head_office')->where('status', '1')->first();

        Session::put('HeadOfficeData', $HeadOfficeData);
        Session::put('SessionHeadOfficeData', $HeadOfficeData);
    }

    protected function setBookApiData() {
        $BookApiData = BookApi::select(['id', 'base_url', 'exyention', 'veriables'])->where(['status' => '1'])->first();
        Session::put('BookApiData', $BookApiData);
    }

    protected function setDecimalPoints() {
        $decimal = AdvanceSetting::decimalPoint();
        Session::put('decimallength', $decimal);
    }

    protected function setSessionBucketData() {
        $BucketData = StorageSetting::select([
            'main_folder',
            'access_key',
            'secret_key',
            'region',
            'bucket_name',
            'storage_validation',
            'storage_max_upload_size',
        ])
            ->where(['storage_type' => 's3_bucket'])->first();

        Session::put('BucketData', $BucketData);
        Session::put('SessionBucketData', $BucketData);
    }
}
