<?php

namespace App\Services\GoogleWorkspace;

use Illuminate\Support\Facades\Http;
use Exception;
use App\User;
use App\Models\Department;
use App\Models\EmployeePosition;
use App\Models\EmployeeType;
use App\Models\UserType;
use App\Services\Integrations\GoogleWorkspace\GoogleWorkspaceIntegration;
use Illuminate\Support\Facades\Log;

/**
 *  Service Class for GoogleDirectory Api
 */
class GoogleDirectoryService
{

    public function __construct(protected GoogleWorkspaceIntegration $integration) {}

    /**
     * Retrieves the JWT access token for the Google Directory API
     *
     * @return string|false The JWT access token or false if an error occurred
     */
    public function getJwtAccessToken()
    {
        return $this->integration->getAccessTokenWithJwt('google_directory');
    }

    /**
     * Get the Google Directory Users
     *	
     * @return Mixed
     */
    public function importDirectoryUsers()
    {
        $token = $this->getJwtAccessToken();
        $pageToken = '';
        $count = 0;

        while (1) {

            $response = $this->integration->getDirectoryUsers($token, $pageToken);

            if ($response === false) {
                return null;
            }

            if (!empty($response['nextPageToken'])) {
                $pageToken = $response['nextPageToken'];
            }

            if (isset($response['users'])) {
                $count += $this->saveUsers($response['users']);
            }

            if ($pageToken == '') {
                break;
            }
        }

        return $count;
    }

    /**
     * Saves an array of users.
     *
     * @param array $users An array of users to be saved.
     * @throws Exception If there is an error while saving the users.
     * @return int The number of users saved.
     */
    public function saveUsers($users)
    {
        $count = 0;
        $userTypeId = UserType::people()->first()->id;
        foreach ($users as $key => $item) {
            $userData = $this->generateUserData($item);

            $user = User::Where('email', $userData['email'])->first();
            if (!$user) {
                $userData['user_type_id'] = $userTypeId;
            }

            try {
                User::updateOrCreate(['email' => $userData['email']], $userData);
                $count++;
            } catch (Exception $e) {
                // dd($e->getMessage());
                Log::channel('daily')->info($userData['email'] . " Cannot be added");
            }
            if ($count % 100 == 1) {
                sleep(1);
                // Log::channel('daily')->info($count . "Users Updated");
            }
        }
        return $count;
    }


    /**
     * Map the api response data with the table columns
     *
     * @return array
     */
    public function generateUserData($item)
    {
        $headerMap = config('google-directory.googleDirectoryUserData');

        $userData = [];

        if (empty($item)) {
            return false;
        }
        foreach ($headerMap as $dbField => $fileHeader) {
            $result = $this->getRelationalValues($item, $dbField, $fileHeader);

            if ($result !== false) {
                $userData[$dbField] = $result ?? null;
            }
        }
        $userData['employee_id'] = $item['id'] ?? null;
        $userData['first_name'] = $item['name']['givenName'] ?? null;
        $userData['last_name'] = $item['name']['familyName'] ?? null;
        $userData['email'] = $item['primaryEmail'] ?? null;
        $userData['business_title'] = $item['organizations'][0]['title'] ?? null;
        $userData['status'] = $item['suspended'] == true ? 0 : 1;

        return $userData;
    }


    /**
     * Maps the api response data to the teqtivity ids
     * @param mixed $item
     * @param mixed $dbField
     * @param mixed $fileHeader
     * 
     * @return [type]
     */
    public function getRelationalValues($item, $dbField)
    {

        // $item->originalhiredate = '2021-12-10';
        if ($dbField == "position_id") {
            $position = null;
            if (isset($item['organizations'][0]['title']) &&  $item['organizations'][0]['title']) {
                $slug = str_slug($item['organizations'][0]['title'], '_');
                $position = EmployeePosition::firstOrCreate(['name' => trim($item['organizations'][0]['title'])], ['slug'  => trim($slug)]);
            }
            $positionId = $position ? $position->id : null;

            return $positionId;
        }

        if ($dbField == "department_id") {
            $department = null;
            if (isset($item['organizations'][0]['department']) && $item['organizations'][0]['department']) {

                $slug = str_slug($item['organizations'][0]['department'], '_');
                $department = Department::firstOrCreate(['slug' => trim($slug)], ['name' => $item['organizations'][0]['department']]);
            }
            $departmentId = $department ? $department->id : null;

            return $departmentId;
        }

        if ($dbField == "employee_type_id") {
            $department = null;
            if (isset($item['orgUnitPath']) && $item['orgUnitPath']) {
                list($first, $employeeType) = explode('/', $item['orgUnitPath']);
                if (in_array($employeeType, ['Suspended', ''])) {
                    $employeeType = 'Employee';
                }
                $employeeType = EmployeeType::firstOrCreate(['slug' => trim($employeeType)], ['name' => $employeeType]);
            }
            $employeeTypeId = $employeeType ? $employeeType->id : null;

            return $employeeTypeId;
        }

        return false;
    }
}
