/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.snippet.telecom;

import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import androidx.test.platform.app.InstrumentationRegistry;
import org.json.JSONException;
import org.json.JSONObject;

/** Utility class for phone account related operations. */
final class PhoneAccountUtils {
  private static final Context context = InstrumentationRegistry.getInstrumentation().getContext();
  private static final TelecomManager telecomManager =
      context.getSystemService(TelecomManager.class);

  public static final String TEST_PHONE_ACCOUNT_ID = "test";
  public static final String TEST_PHONE_ACCOUNT_LABEL = "Telecom Mobly Snippet";
  public static final Uri TEST_PHONE_ACCOUNT_ADDRESS = Uri.parse("sip:test@android.com");
  public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE =
      new PhoneAccountHandle(
          new ComponentName(context, ManagedConnectionService.class), TEST_PHONE_ACCOUNT_ID);
  public static final PhoneAccount TEST_PHONE_ACCOUNT =
      new PhoneAccount.Builder(TEST_PHONE_ACCOUNT_HANDLE, TEST_PHONE_ACCOUNT_LABEL)
          .setAddress(TEST_PHONE_ACCOUNT_ADDRESS)
          .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
          .build();

  public static final Bundle TEST_SELF_MANAGED_PHONE_ACCOUNT_EXTRA;

  static {
    TEST_SELF_MANAGED_PHONE_ACCOUNT_EXTRA = new Bundle();
    TEST_SELF_MANAGED_PHONE_ACCOUNT_EXTRA.putBoolean(
        PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, true);
  }

  public static final String TEST_SELF_MANAGED_PHONE_ACCOUNT_ID = "selfMgdTest";
  public static final String TEST_SELF_MANAGED_PHONE_ACCOUNT_LABEL = "Telecom Mobly Snippet";
  public static final Uri TEST_SELF_MANAGED_PHONE_ACCOUNT_ADDRESS =
      Uri.parse("sip:sekf@android.com");
  public static final PhoneAccountHandle TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE =
      new PhoneAccountHandle(
          new ComponentName(context, ManagedConnectionService.class),
          TEST_SELF_MANAGED_PHONE_ACCOUNT_ID);
  public static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT =
      new PhoneAccount.Builder(
              TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE, TEST_SELF_MANAGED_PHONE_ACCOUNT_LABEL)
          .setAddress(TEST_SELF_MANAGED_PHONE_ACCOUNT_ADDRESS)
          .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
          .setExtras(TEST_SELF_MANAGED_PHONE_ACCOUNT_EXTRA)
          .build();

  public static final String TEST_SELF_MAANGED_PHONE_ACCOUNT2_ID = "selfMgdTest2";
  public static final String TEST_SELF_MANAGED_PHONE_ACCOUNT2_LABEL = "Telecom Mobly Snippet 2";

  public static final PhoneAccountHandle TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2 =
      new PhoneAccountHandle(
          new ComponentName(context, SelfManagedConnectionService.class),
          TEST_SELF_MAANGED_PHONE_ACCOUNT2_ID);
  public static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT_2 =
      new PhoneAccount.Builder(
              TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2, TEST_SELF_MANAGED_PHONE_ACCOUNT2_LABEL)
          .setAddress(TEST_SELF_MANAGED_PHONE_ACCOUNT_ADDRESS)
          .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
          .build();

  public static final JSONObject convertPhoneAccountToJsonObject(
      PhoneAccountHandle phoneAccountHandle) throws JSONException {
    JSONObject jsonObject = new JSONObject();
    appendPhoneAccountHandleInfo(jsonObject, phoneAccountHandle);
    PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle);
    appendPhoneAccountInfo(jsonObject, phoneAccount);
    return jsonObject;
  }

  public static final JSONObject convertPhoneAccountToJsonObject(PhoneAccount phoneAccount)
      throws JSONException {
    JSONObject jsonObject = new JSONObject();
    PhoneAccountHandle phoneAccountHandle = phoneAccount.getAccountHandle();
    appendPhoneAccountHandleInfo(jsonObject, phoneAccountHandle);
    appendPhoneAccountInfo(jsonObject, phoneAccount);
    return jsonObject;
  }

  public static void cleanupConnectionServices() {
    SelfManagedConnectionService selfConnSvr = SelfManagedConnectionService.getConnectionService();
    if (selfConnSvr != null) {
      selfConnSvr.getConnections().stream()
          .forEach(
              (c) -> {
                c.onDisconnect();
              });
    }

    ManagedConnectionService connSvr = ManagedConnectionService.getConnectionService();
    if (connSvr != null) {
      connSvr.getConnections().stream()
          .forEach(
              (c) -> {
                c.onDisconnect();
              });
    }

    telecomManager.unregisterPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE);
    telecomManager.unregisterPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2);
  }

  public static void appendPhoneAccountHandleInfo(
      JSONObject jsonObject, PhoneAccountHandle phoneAccountHandle) throws JSONException {
    ComponentName componentName = phoneAccountHandle.getComponentName();
    jsonObject.put(
        "componentName", componentName.getPackageName() + "/" + componentName.getClassName());
    jsonObject.put("id", phoneAccountHandle.getId());
  }

  public static void appendPhoneAccountInfo(JSONObject jsonObject, PhoneAccount phoneAccount)
      throws JSONException {
    Uri address = phoneAccount.getSubscriptionAddress();
    jsonObject.put("subscriptionAddress", address == null ? null : address.toString());
  }

  private PhoneAccountUtils() {}
}

