<?php
// Einzige Stelle, die HTTP-Details von omsorgCore kennt (Basis-URL, Header, JSON-(De)Kodierung) -
// analog zu httpClient.cjs/authClient.cjs in omsorgapp. Alle Aufrufer bekommen ein einheitliches
// Ergebnis-Array: ['ok' => bool, 'status' => int, 'data' => array|null].
//
// Auth-Endpunkte plus die für den Außendienst freigegebenen Absences-/ValueLists-Endpunkte -
// Connect verwaltet weiterhin keine anderen Nutzer/Rollen/Mitarbeiter (das bleibt OMSORG Desktop
// vorbehalten), deshalb fehlen hier bewusst omsorgcore_users_*/roles_*/employees_*.
//
// Transport läuft über den generierten Client in ../api-client-php/ (openapi-generator, siehe
// ../api-client-php/ANLEITUNG.md) statt über rohes cURL.

require_once __DIR__ . '/../api-client-php/vendor/autoload.php';

// Führt einen generierten Api-Aufruf aus und wandelt das Ergebnis in den einheitlichen
// Vertrag ['ok', 'status', 'data'] um. $fn bekommt die fertige Configuration und muss
// eine ...WithHttpInfo(...)-Methode aufrufen (liefert [$model, $status, $headers]).
function omsorgcore_call(array $config, callable $fn): array
{
    $configuration = \OmsorgCoreClient\Configuration::getDefaultConfiguration()
        ->setHost(rtrim($config['omsorg_core_url'], '/'));

    try {
        [$model, $status] = $fn($configuration);
        $data = $model !== null ? json_decode(json_encode($model), true) : null;
        return ['ok' => true, 'status' => $status, 'data' => $data];
    } catch (\OmsorgCoreClient\ApiException $e) {
        $status = $e->getCode();
        $body = $e->getResponseBody();
        $decoded = $body !== null ? json_decode($body, true) : null;
        $data = $decoded !== null ? $decoded : $body;

        $result = ['ok' => false, 'status' => $status, 'data' => $data];
        if ($status === 0) {
            $result['error'] = $e->getMessage();
        }
        return $result;
    }
}

// --- Auth ---

function omsorgcore_login(array $config, string $username, string $password): array
{
    $loginRequest = new \OmsorgCoreClient\Model\LoginRequest(['username' => $username, 'password' => $password]);
    return omsorgcore_call($config, fn($cfg) => (new \OmsorgCoreClient\Api\AuthApi(new \GuzzleHttp\Client(), $cfg))
        ->apiAuthLoginPostWithHttpInfo($loginRequest));
}

function omsorgcore_refresh(array $config, string $refreshToken): array
{
    $refreshRequest = new \OmsorgCoreClient\Model\RefreshRequest(['refresh_token' => $refreshToken]);
    return omsorgcore_call($config, fn($cfg) => (new \OmsorgCoreClient\Api\AuthApi(new \GuzzleHttp\Client(), $cfg))
        ->apiAuthRefreshPostWithHttpInfo($refreshRequest));
}

function omsorgcore_logout(array $config, string $refreshToken): array
{
    $logoutRequest = new \OmsorgCoreClient\Model\LogoutRequest(['refresh_token' => $refreshToken]);
    return omsorgcore_call($config, fn($cfg) => (new \OmsorgCoreClient\Api\AuthApi(new \GuzzleHttp\Client(), $cfg))
        ->apiAuthLogoutPostWithHttpInfo($logoutRequest));
}

function omsorgcore_me(array $config, string $accessToken): array
{
    return omsorgcore_call($config, function ($cfg) use ($accessToken) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\AuthApi(new \GuzzleHttp\Client(), $cfg))->apiAuthMeGetWithHttpInfo();
    });
}

function omsorgcore_change_password(array $config, string $accessToken, string $currentPassword, string $newPassword): array
{
    $changePasswordRequest = new \OmsorgCoreClient\Model\ChangePasswordRequest([
        'current_password' => $currentPassword,
        'new_password' => $newPassword,
    ]);
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $changePasswordRequest) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\AuthApi(new \GuzzleHttp\Client(), $cfg))
            ->apiAuthChangePasswordPostWithHttpInfo($changePasswordRequest);
    });
}

function omsorgcore_forgot_password_request(array $config, string $username): array
{
    $forgotPasswordRequestRequest = new \OmsorgCoreClient\Model\ForgotPasswordRequestRequest(['username' => $username]);
    return omsorgcore_call($config, fn($cfg) => (new \OmsorgCoreClient\Api\AuthApi(new \GuzzleHttp\Client(), $cfg))
        ->apiAuthForgotPasswordRequestPostWithHttpInfo($forgotPasswordRequestRequest));
}

function omsorgcore_forgot_password_verify(array $config, string $username, string $pin): array
{
    $forgotPasswordVerifyRequest = new \OmsorgCoreClient\Model\ForgotPasswordVerifyRequest(['username' => $username, 'pin' => $pin]);
    return omsorgcore_call($config, fn($cfg) => (new \OmsorgCoreClient\Api\AuthApi(new \GuzzleHttp\Client(), $cfg))
        ->apiAuthForgotPasswordVerifyPostWithHttpInfo($forgotPasswordVerifyRequest));
}

function omsorgcore_forgot_password_reset(array $config, string $resetToken, string $newPassword): array
{
    $forgotPasswordResetRequest = new \OmsorgCoreClient\Model\ForgotPasswordResetRequest([
        'reset_token' => $resetToken,
        'new_password' => $newPassword,
    ]);
    return omsorgcore_call($config, fn($cfg) => (new \OmsorgCoreClient\Api\AuthApi(new \GuzzleHttp\Client(), $cfg))
        ->apiAuthForgotPasswordResetPostWithHttpInfo($forgotPasswordResetRequest));
}

function omsorgcore_password_policy(array $config): array
{
    return omsorgcore_call($config, fn($cfg) => (new \OmsorgCoreClient\Api\AuthApi(new \GuzzleHttp\Client(), $cfg))
        ->apiAuthPasswordPolicyGetWithHttpInfo());
}

// --- ValueLists (nur lesend - Dropdown-Optionen, z. B. "AbsenceType") ---

function omsorgcore_value_list_items(array $config, string $accessToken, string $key): array
{
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $key) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\ValueListsApi(new \GuzzleHttp\Client(), $cfg))
            ->apiValueListsKeyItemsGetWithHttpInfo($key);
    });
}

// --- Absences (Urlaub/Krankmeldung/Sonstige, FR-CON-1) ---
// Own-Scope: die EmployeeId wird serverseitig aus dem JWT aufgelöst (siehe AbsenceService in
// omsorgCore), Connect schickt hier bewusst nie eine employeeId mit.

function omsorgcore_absences_list(array $config, string $accessToken, ?string $status = null): array
{
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $status) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\AbsencesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiAbsencesGetWithHttpInfo($status);
    });
}

function omsorgcore_absences_create(array $config, string $accessToken, array $payload): array
{
    $createAbsenceRequest = new \OmsorgCoreClient\Model\CreateAbsenceRequest([
        'type' => $payload['type'],
        'start_date' => new \DateTime($payload['startDate']),
        'end_date' => new \DateTime($payload['endDate']),
        'reason' => $payload['reason'] !== '' ? $payload['reason'] : null,
        'substitute' => $payload['substitute'] !== '' ? $payload['substitute'] : null,
        'note' => $payload['note'] !== '' ? $payload['note'] : null,
    ]);
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $createAbsenceRequest) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\AbsencesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiAbsencesPostWithHttpInfo($createAbsenceRequest);
    });
}

// Nur solange der Antrag noch "Eingereicht" ist (serverseitig erzwungen, siehe
// AbsenceService.UpdateAsync in omsorgCore) - Genehmigt/Abgelehnt sind über diesen Endpoint
// bewusst nicht mehr änderbar.
function omsorgcore_absences_update(array $config, string $accessToken, string $id, array $payload): array
{
    $updateAbsenceRequest = new \OmsorgCoreClient\Model\UpdateAbsenceRequest([
        'type' => $payload['type'],
        'start_date' => new \DateTime($payload['startDate']),
        'end_date' => new \DateTime($payload['endDate']),
        'reason' => $payload['reason'] !== '' ? $payload['reason'] : null,
        'substitute' => $payload['substitute'] !== '' ? $payload['substitute'] : null,
        'note' => $payload['note'] !== '' ? $payload['note'] : null,
    ]);
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $id, $updateAbsenceRequest) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\AbsencesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiAbsencesIdPutWithHttpInfo($id, $updateAbsenceRequest);
    });
}

// --- Orders (nur lesend - Auftrags-Dropdown fürs Zeiterfassungsformular) ---
// Order hat noch keine Mitarbeiter-Zuweisung (FR-EM-3 offen), daher zeigt das Dropdown alle
// aktiven Aufträge - siehe omsorgCore/CLAUDE.md, Abschnitt "Zeiterfassung", dokumentierte Einschränkung.

function omsorgcore_orders_list(array $config, string $accessToken): array
{
    return omsorgcore_call($config, function ($cfg) use ($accessToken) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\OrdersApi(new \GuzzleHttp\Client(), $cfg))
            ->apiOrdersGetWithHttpInfo(null, null, null, null, null, null, 1, 200);
    });
}

// --- TimeEntries (Zeiterfassung pro Schicht, FR-ZE-1/FR-ZE-2) ---
// Own-Scope: die EmployeeId wird serverseitig aus dem JWT aufgelöst (siehe TimeEntryService in
// omsorgCore), Connect schickt hier bewusst nie eine employeeId mit.

function omsorgcore_time_entries_list(array $config, string $accessToken, ?string $statusId = null): array
{
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $statusId) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\TimeEntriesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiTimeEntriesGetWithHttpInfo($statusId);
    });
}

function omsorgcore_time_entries_create(array $config, string $accessToken, array $payload): array
{
    $createTimeEntryRequest = new \OmsorgCoreClient\Model\CreateTimeEntryRequest([
        'order_id' => $payload['orderId'],
        'date' => new \DateTime($payload['date']),
        'start' => $payload['start'],
        'end' => $payload['end'],
        'break_duration' => $payload['breakDuration'],
        'night_hours' => $payload['nightHours'],
        'saturday_hours' => $payload['saturdayHours'],
        'sunday_hours' => $payload['sundayHours'],
        'holiday_hours' => $payload['holidayHours'],
    ]);
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $createTimeEntryRequest) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\TimeEntriesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiTimeEntriesPostWithHttpInfo($createTimeEntryRequest);
    });
}

// Nur solange status.isEditableByOwner (serverseitig erzwungen, siehe TimeEntryService.UpdateAsync
// in omsorgCore) - kein statusId-Feld hier, Statuswechsel laufen ausschließlich über submit/decision.
function omsorgcore_time_entries_update(array $config, string $accessToken, string $id, array $payload): array
{
    $updateTimeEntryRequest = new \OmsorgCoreClient\Model\UpdateTimeEntryRequest([
        'order_id' => $payload['orderId'],
        'date' => new \DateTime($payload['date']),
        'start' => $payload['start'],
        'end' => $payload['end'],
        'break_duration' => $payload['breakDuration'],
        'night_hours' => $payload['nightHours'],
        'saturday_hours' => $payload['saturdayHours'],
        'sunday_hours' => $payload['sundayHours'],
        'holiday_hours' => $payload['holidayHours'],
    ]);
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $id, $updateTimeEntryRequest) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\TimeEntriesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiTimeEntriesIdPutWithHttpInfo($id, $updateTimeEntryRequest);
    });
}

function omsorgcore_value_list_transitions(array $config, string $accessToken, string $key): array
{
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $key) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\ValueListsApi(new \GuzzleHttp\Client(), $cfg))
            ->apiValueListsKeyTransitionsGetWithHttpInfo($key);
    });
}

function omsorgcore_time_entries_submit(array $config, string $accessToken, string $id): array
{
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $id) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\TimeEntriesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiTimeEntriesIdSubmitPostWithHttpInfo($id);
    });
}

// --- EmployeeFacilityDistances (eigene Fahrtstrecke km je Einrichtung, FR-EIN-4) ---
// Own-Scope: die EmployeeId wird serverseitig aus dem JWT aufgelöst (siehe
// MyFacilityDistancesController in omsorgCore), Connect schickt hier bewusst nie eine employeeId mit.
// Kein Facilities-Recht nötig - die Einrichtungsauswahl kommt über einen eigenen, minimalen
// Endpoint (nur Id/Name, keine Konditionen/CRM-Daten).

function omsorgcore_my_facility_distances_list(array $config, string $accessToken): array
{
    return omsorgcore_call($config, function ($cfg) use ($accessToken) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\MyFacilityDistancesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiMeFacilityDistancesGetWithHttpInfo();
    });
}

function omsorgcore_my_facility_distances_facility_options(array $config, string $accessToken): array
{
    return omsorgcore_call($config, function ($cfg) use ($accessToken) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\MyFacilityDistancesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiMeFacilityDistancesFacilitiesGetWithHttpInfo();
    });
}

function omsorgcore_my_facility_distances_create(array $config, string $accessToken, array $payload): array
{
    $request = new \OmsorgCoreClient\Model\CreateMyFacilityDistanceRequest([
        'facility_id' => $payload['facilityId'],
        'distance_km' => $payload['distanceKm'],
    ]);
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $request) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\MyFacilityDistancesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiMeFacilityDistancesPostWithHttpInfo($request);
    });
}

function omsorgcore_my_facility_distances_update(array $config, string $accessToken, string $id, array $payload): array
{
    $request = new \OmsorgCoreClient\Model\UpdateMyFacilityDistanceRequest([
        'distance_km' => $payload['distanceKm'],
    ]);
    return omsorgcore_call($config, function ($cfg) use ($accessToken, $id, $request) {
        $cfg->setAccessToken($accessToken);
        return (new \OmsorgCoreClient\Api\MyFacilityDistancesApi(new \GuzzleHttp\Client(), $cfg))
            ->apiMeFacilityDistancesIdPutWithHttpInfo($id, $request);
    });
}
