package com.android.dialer.app.calllog;

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.provider.CallLog.Calls;
import com.android.dialer.common.LogUtil;
import com.android.dialer.constants.ScheduledJobIds;
import java.util.concurrent.TimeUnit;

/** Privacy-first rolling retention for the system call history. */
public final class CallHistoryRetentionManager {

  public static final String PREF_KEY = "lemenzo_call_history_retention";
  public static final String OFF = "off";
  private static final long PERIOD_MILLIS = TimeUnit.HOURS.toMillis(12);

  private CallHistoryRetentionManager() {}

  public static void applySetting(Context context, String value) {
    if (retentionMillis(value) <= 0) {
      cancel(context);
      return;
    }
    schedule(context);
    // Apply the newly selected policy immediately instead of waiting for the first job window.
    CallHistoryRetentionJobService.runCleanupAsync(context.getApplicationContext(), null);
  }

  public static void restoreSchedule(Context context) {
    String value = getValue(context);
    if (retentionMillis(value) > 0) {
      schedule(context);
    } else {
      cancel(context);
    }
  }

  static String getValue(Context context) {
    SharedPreferences preferences =
        PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
    return preferences.getString(PREF_KEY, OFF);
  }

  static long retentionMillis(String value) {
    if ("24h".equals(value)) {
      return TimeUnit.HOURS.toMillis(24);
    } else if ("2d".equals(value)) {
      return TimeUnit.DAYS.toMillis(2);
    } else if ("4d".equals(value)) {
      return TimeUnit.DAYS.toMillis(4);
    } else if ("7d".equals(value)) {
      return TimeUnit.DAYS.toMillis(7);
    } else if ("14d".equals(value)) {
      return TimeUnit.DAYS.toMillis(14);
    }
    return 0;
  }

  static int deleteExpired(Context context) {
    long retention = retentionMillis(getValue(context));
    if (retention <= 0) {
      return 0;
    }

    long cutoff = System.currentTimeMillis() - retention;
    try {
      // Calls.CONTENT_URI is the authoritative Android call history. The annotated Lemenzo
      // database observes this provider and refreshes after the deletion.
      int deleted =
          context
              .getContentResolver()
              .delete(Calls.CONTENT_URI, Calls.DATE + " < ?", new String[] {Long.toString(cutoff)});
      LogUtil.i(
          "CallHistoryRetentionManager.deleteExpired",
          "removed %d expired call-history rows",
          deleted);
      return deleted;
    } catch (SecurityException e) {
      // Never crash Phone if the dialer role/permission is temporarily unavailable.
      LogUtil.e(
          "CallHistoryRetentionManager.deleteExpired",
          "WRITE_CALL_LOG unavailable",
          e);
      return 0;
    } catch (RuntimeException e) {
      LogUtil.e(
          "CallHistoryRetentionManager.deleteExpired",
          "call-history cleanup failed",
          e);
      return 0;
    }
  }

  private static void schedule(Context context) {
    JobScheduler scheduler = context.getSystemService(JobScheduler.class);
    JobInfo job =
        new JobInfo.Builder(
                ScheduledJobIds.CALL_HISTORY_RETENTION_JOB,
                new ComponentName(context, CallHistoryRetentionJobService.class))
            .setPeriodic(PERIOD_MILLIS)
            .setPersisted(true)
            .build();
    int result = scheduler.schedule(job);
    LogUtil.i(
        "CallHistoryRetentionManager.schedule",
        "scheduled retention job, result=%d",
        result);
  }

  private static void cancel(Context context) {
    context
        .getSystemService(JobScheduler.class)
        .cancel(ScheduledJobIds.CALL_HISTORY_RETENTION_JOB);
  }
}
