package de.gematik.dipag.client;

import java.util.List;
import java.util.Map;

import de.gematik.zeta.logging.Log;
import de.gematik.zeta.logging.ZetaLogLevel;
import de.gematik.zeta.sdk.BuildConfig;
import de.gematik.zeta.sdk.TpmConfig;
import de.gematik.zeta.sdk.ZetaSdk;
import de.gematik.zeta.sdk.ZetaSdkClient;
import de.gematik.zeta.sdk.ZetaSdkClientExtension;
import de.gematik.zeta.sdk.attestation.model.AttestationConfig;
import de.gematik.zeta.sdk.attestation.model.PlatformProductId;
import de.gematik.zeta.sdk.authentication.AuthConfig;
import de.gematik.zeta.sdk.authentication.smb.SmbTokenProvider;
import de.gematik.zeta.sdk.network.http.client.HttpClientExtension;
import de.gematik.zeta.sdk.network.http.client.ZetaHttpClient;
import de.gematik.zeta.sdk.network.http.client.ZetaHttpClientBuilder;
import de.gematik.zeta.sdk.storage.StorageConfig;
import io.ktor.client.plugins.logging.LogLevel;
import kotlin.Unit;


public class DiPagClient2 {

  private final static String diPagServer = "https://dev2.digitale-patientenrechnung.de/";

  private final static String CREATE_INSTITUTION_BODY = """
      {
        "zustimmungVerwendungTelematikID": true,
        "zustimmungVerwendungAnzeigename": true,
        "zustimmungNutzungsbedingungen": true
      }
      """;

  private final static List<String> SCOPES_CREATE_ACCOUNT = List.of("dipag", "practitionerAccount.crud");
  private final static List<String> SCOPES_SEARCH_PATIENT = List.of("dipag","insurantAccount.rs");

  private final static String telematikId = "9-2.270.73848333";

  private final static String STORAGE_KEY = "KqOHTbtH1711eFd/PUMFSISxsJA3U1n4eweFljdtoTA=";

  public static void main(String[] args) {
    var code = run(args);
    System.exit(code);
  }

  private static int run(String[] args) {

    final String smbKeystore = args[0];
    Log.INSTANCE.initDebugLogger();
    Log.INSTANCE.setLogLevel(ZetaLogLevel.WARN);
    
    var sdkClientAccount = buildClient(SCOPES_CREATE_ACCOUNT, smbKeystore);
    var sdkClientFHIR = buildClient(SCOPES_SEARCH_PATIENT, smbKeystore);

    ZetaHttpClient httpClientAccountAPI = null;
    ZetaHttpClient httpClientFhirAPI = null;

    try {
      httpClientAccountAPI = sdkClientAccount.httpClient(it -> {return Unit.INSTANCE;});
      httpClientFhirAPI = sdkClientFHIR.httpClient(it -> {return Unit.INSTANCE;});

      final Map<String, String> headers = Map.of("Accept", "application/json");

      // create account 
      var acccountRequest = HttpClientExtension.postAsync(httpClientAccountAPI, "/api/PractitionerAccount", headers, CREATE_INSTITUTION_BODY);
      var responseAccountCreation = acccountRequest.join();
      int status = responseAccountCreation.getStatus().getValue();
      System.out.println("# CREATE PRACTITIONER ACCOUNT STATUS: "+status);
      if(status != 201) return 1;
      
      // search patient
      var patientRequest = HttpClientExtension.getAsync(httpClientFhirAPI, "/fhir/Patient?identifier=V202606242&birthdate=1965-02-01", headers);
      var responsePatient = patientRequest.join();
      var responseBodyPatient = HttpClientExtension.bodyAsText(responsePatient).join();
      status = responsePatient.getStatus().getValue();
      System.out.println("# SEARCH PATIENT STATUS: "+status);
      System.out.println(responseBodyPatient);
      
      // delete account 
      var deleteAccountRequest = HttpClientExtension.deleteAsync(httpClientAccountAPI, "/api/PractitionerAccount/"+telematikId, headers);
      var deleteAccountResponse =  deleteAccountRequest.join();
      status = deleteAccountResponse.getStatus().getValue();
      System.out.println("# DELETE PRACTITIONER ACCOUNT STATUS: "+status);
      return 0;
      
    } finally {      
      httpClientAccountAPI.close();
      httpClientFhirAPI.close();  
      ZetaSdkClientExtension.close(sdkClientAccount);      
      ZetaSdkClientExtension.close(sdkClientFHIR);      
    }
  }


  private static ZetaSdkClient buildClient(final List<String> scopes, final String smbKeystore) {
    final StorageConfig storageConfig = new StorageConfig.Default(STORAGE_KEY, null);    
    return 
      ZetaSdk.INSTANCE.build(
        diPagServer,
        new BuildConfig(
            "DiPag-Demo-Client",
            "0.1.0",
            "dipag-client",
            storageConfig,
            new TpmConfig() { // kein TPM
            },
            new AuthConfig(
                scopes,
                30,
                false,
                new SmbTokenProvider(new SmbTokenProvider.Credentials(
                    smbKeystore,
                    "alias",
                    "00",
                    "")),
                AttestationConfig.software(),
                ""),
            new PlatformProductId.WindowsProductId("windows", "storeId", ""),
            new ZetaHttpClientBuilder().logging(LogLevel.ALL),
            null,
            null,
            null));
  }
  
}
