<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
use Microsoft\Kiota\Authentication\Cache\InMemoryAccessTokenCache;
use GuzzleHttp\Exception\RequestException;

use App\Models\Company;
use App\Models\GlobalSetting;
use App\Models\UserAuth;
use App\Models\User;
use Illuminate\Support\Facades\App;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\DB;
use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAccessTokenProvider;
use App\Actions\Fortify\AttemptToAuthenticate;

class OutlookController extends Controller
{
    protected $scopes = ['User.Read', 'Mail.ReadWrite', 'offline_access'];

    public function redirectToOutlook()
    {
        $query = http_build_query([
            'client_id' => config('services.outlook.client_id'),
            'response_type' => 'code',
            'redirect_uri' => config('services.outlook.redirect'),
            'response_mode' => 'query',
            'scope' => implode(' ', $this->scopes),
        ]);

        return redirect("https://login.microsoftonline.com/" . config('services.outlook.tenant_id') . "/oauth2/v2.0/authorize?$query");
    }

    public function handleCallback(Request $request)
    {
        session_start();
        $authCode = $request->query('code');

        if (!$authCode) {
            return redirect()->route('dashboard')->with('error', 'Authorization code missing.');
        }

        try {
            // Use InMemoryAccessTokenCache
            $tokenCache = new InMemoryAccessTokenCache();

            $tokenRequestContext = new AuthorizationCodeContext(
                config('services.outlook.tenant_id'),
                config('services.outlook.client_id'),
                config('services.outlook.client_secret'),
                $authCode,
                config('services.outlook.redirect'),
                
            );

         
                    
            $inMemoryCache = new InMemoryAccessTokenCache();

            $graphServiceClient = GraphServiceClient::createWithAuthenticationProvider(
                GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
                    GraphPhpLeagueAccessTokenProvider::createWithCache(
                        $inMemoryCache,
                        $tokenRequestContext,
                        $this->scopes
                    )
                )
            );

            //echo 'in here';exit;

            // Fetch user details
            $user = $graphServiceClient->me()->get()->wait();
            $email = $user->getMail();
        

              
            if(!user()){
                // Find user in database
                  $authUser = UserAuth::where('email', $email)->first();
  
                  if (!$authUser) {
                      return redirect()->route('login')->with('error', 'No account found for this email.');
                  }
                  Auth::login($authUser, true); // Log in user with remember me
                  $this->afterLoginUser($request,$email);
                  return redirect()->route('dashboard')->with('success', 'Outlook connected!s');
                  
  
              }
  

            
            $accessToken = $inMemoryCache->getTokenWithContext($tokenRequestContext);

           //dd($accessToken);
           //  dd($tokenCache->getAccessToken($tokenRequestContext->getCacheKey()),$user->getGivenName());exit;
            // Store token in session (No need for DB storage)
            // session([
            //     'outlook_access_token' => $accessToken->getToken(),
            //     'outlook_refresh_token' => $accessToken->getRefreshToken(),
            // ]);
             // ✅ Store the tokens in the database
            //  dd($accessToken->getExpires());
            $authUser = Auth::user();
             $authUser->update([
                'outlook_access_token' =>  $accessToken->getToken(),
                
                'outlook_refresh_token' =>  $accessToken->getRefreshToken(),
                'outlook_token_expiry' => $accessToken->getExpires(),
            ]);

            return redirect()->route('dashboard')->with('success', 'Outlook connected successfully! User: ' . $user->getGivenName());
        } catch (RequestException $e) {
            return redirect()->route('dashboard')->with('error', 'Failed to connect Outlook: ' . $e->getMessage());
        }
    }

    public function sendEmail()
    {
        try {
            // Retrieve token from session
            $accessToken = session('outlook_access_token');

            if (!$accessToken) {
                return redirect()->route('dashboard')->with('error', 'Access token not found.');
            }

            // Create Graph Client with stored access token
            $graphClient = new GraphServiceClient($accessToken);

            // Prepare email payload
            $emailData = [
                "message" => [
                    "subject" => "Test Email from Laravel",
                    "body" => [
                        "contentType" => "Text",
                        "content" => "This is a test email sent from Laravel using Microsoft Graph API.",
                    ],
                    "toRecipients" => [
                        [
                            "emailAddress" => [
                                "address" => "recipient@example.com",
                            ],
                        ],
                    ],
                ],
                "saveToSentItems" => true,
            ];

            // Send email via Graph API
            $response = $graphClient->me()->sendMail()->post($emailData);

            return redirect()->route('dashboard')->with('success', 'Email sent successfully!');
        } catch (\Exception $e) {
            return redirect()->route('dashboard')->with('error', 'Failed to send email: ' . $e->getMessage());
        }
    }


    public function redirectPath()
    {

        if (isWorksuiteSaas()) {
            session(['user' => User::find(user()->id)]);

            if (auth()->user() && auth()->user()->user->is_superadmin) {
                return (session()->has('url.intended') ? session()->get('url.intended') : RouteServiceProvider::SUPER_ADMIN_HOME);
            }

            $emailCountInCompanies = DB::table('users')->where('email', user()->email)->count();
            session()->forget('user_company_count');

            if ($emailCountInCompanies > 1) {
                if (module_enabled('Subdomain')) {
                    UserAuth::multipleUserLoginSubdomain();
                }
                else {
                    session(['user_company_count' => $emailCountInCompanies]);

                    return route('superadmin.superadmin.workspaces');
                }

            }

            return (session()->has('url.intended') ? session()->get('url.intended') : RouteServiceProvider::HOME);
        }

        if (method_exists($this, 'redirectTo')) {
            return $this->redirectTo();
        }

        return property_exists($this, 'redirectTo') ? $this->redirectTo : '/login';
    }

    private function afterLoginUser($request,$email){


        $globalSetting = GlobalSetting::first();

        $url = session('url.intended');
        $path = parse_url($url, PHP_URL_PATH);
        $token = basename($path);
        $company = Company::where('hash', $token)->first();

        $attemptAuth = App::make(AttemptToAuthenticate::class);
       
        $authUser = User::withoutGlobalScope(ActiveScope::class)->where('email', $email);

        if ($company) {
            $authUser->where('company_id', $company->id);
        }
        $authUser = $authUser->first();
        //dd($authUser);
        // Check if the user exists and belongs to the correct company
        if ($company && $company->id !== $authUser->company_id) {
            $attemptAuth->checkCompany();
        }


        if($authUser->company){
            $attendanceSetting = $authUser->company->attendanceSetting;
            $checkAutoClockinConditions = $attemptAuth->checkAutoClockinConditions($authUser);

            if ($attendanceSetting->auto_clock_in == 'yes' && $checkAutoClockinConditions) {
                if (($attendanceSetting->radius_check == 'yes' && $attemptAuth->isInRadius($request, $attendanceSetting)) || $attendanceSetting->radius_check == 'no') {
                  // dd('12');
                    $attemptAuth->storeClockIn($request, $authUser->id);
                }
            }
        }

    }



}
