<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use App\Models\UserRole;
use App\Models\Setting;

class AzureADService
{
    private $clientId;
    private $clientSecret;
    private $tenantId;
    private $redirectUri;

    public function __construct()
    {
        $config = Setting::get('azure_ad_config', []);
        $this->clientId = $config['clientId'] ?? env('AZURE_CLIENT_ID');
        $this->clientSecret = $config['clientSecret'] ?? env('AZURE_CLIENT_SECRET');
        $this->tenantId = $config['tenantId'] ?? env('AZURE_TENANT_ID');
        $this->redirectUri = $config['redirectUri'] ?? env('AZURE_REDIRECT_URI');
    }

    /**
     * Get Azure AD authorization URL
     */
    public function getAuthorizationUrl(string $state): string
    {
        $params = http_build_query([
            'client_id' => $this->clientId,
            'response_type' => 'code',
            'redirect_uri' => $this->redirectUri,
            'response_mode' => 'query',
            'scope' => 'openid profile email User.Read',
            'state' => $state,
        ]);

        return "https://login.microsoftonline.com/{$this->tenantId}/oauth2/v2.0/authorize?{$params}";
    }

    /**
     * Exchange authorization code for access token
     */
    public function getAccessToken(string $code): ?string
    {
        $response = Http::asForm()->post(
            "https://login.microsoftonline.com/{$this->tenantId}/oauth2/v2.0/token",
            [
                'client_id' => $this->clientId,
                'client_secret' => $this->clientSecret,
                'code' => $code,
                'redirect_uri' => $this->redirectUri,
                'grant_type' => 'authorization_code',
                'scope' => 'User.Read',
            ]
        );

        if ($response->failed()) {
            \Log::error('Azure AD token exchange failed', [
                'status' => $response->status(),
                'body' => $response->body(),
            ]);
            return null;
        }

        return $response->json('access_token');
    }

    /**
     * Get user profile from Microsoft Graph API
     */
    public function getUserProfile(string $accessToken): ?array
    {
        $response = Http::withToken($accessToken)
            ->get('https://graph.microsoft.com/v1.0/me');

        if ($response->failed()) {
            \Log::error('Microsoft Graph API failed', [
                'status' => $response->status(),
                'body' => $response->body(),
            ]);
            return null;
        }

        $data = $response->json();

        return [
            'email' => $data['mail'] ?? $data['userPrincipalName'],
            'name' => $data['displayName'],
            'phone' => $data['businessPhones'][0] ?? $data['mobilePhone'] ?? null,
        ];
    }

    /**
     * Handle complete Azure AD authentication flow
     */
    public function authenticate(string $code): ?array
    {
        // Get access token
        $accessToken = $this->getAccessToken($code);
        if (!$accessToken) {
            return null;
        }

        // Get user profile
        $profile = $this->getUserProfile($accessToken);
        if (!$profile) {
            return null;
        }

        // Find or create user in user_roles table
        $userRole = UserRole::firstOrCreate(
            ['email' => $profile['email']],
            [
                'role' => 'user', // Default role
                'is_active' => true,
            ]
        );

        // Check if user is active
        if (!$userRole->is_active) {
            throw new \Exception('User account is inactive');
        }

        // Update last login
        $userRole->update(['last_login_at' => now()]);

        return [
            'email' => $userRole->email,
            'name' => $profile['name'],
            'phone' => $profile['phone'],
            'role' => $userRole->role,
        ];
    }
}
