import type * as NotificationsType from "expo-notifications";
import {
  loadNotifSettings,
  loadNotifThresholdLastFired,
  saveNotifThresholdLastFired,
} from "@/lib/storage";
import type { ClaudeUsageResponse } from "@/types/claude";
import type { CodexUsageResponse } from "@/types/codex";

// expo-notifications push notifications were removed from Expo Go in SDK 53.
// Use require() so the initialization error is caught gracefully in Expo Go.
let Notifications: typeof NotificationsType | null = null;
try {
  Notifications = require("expo-notifications") as typeof NotificationsType;
  Notifications.setNotificationHandler({
    handleNotification: async () => ({
      shouldShowAlert: true,
      shouldShowBanner: true,
      shouldShowList: true,
      shouldPlaySound: false,
      shouldSetBadge: false,
    }),
  });
} catch {
  // Running in Expo Go or native module unavailable — notifications disabled.
}

export async function requestPermissions(): Promise<boolean> {
  if (!Notifications) return false;
  const { status } = await Notifications.requestPermissionsAsync();
  return status === "granted";
}

export async function getPermissionStatus(): Promise<string> {
  if (!Notifications) return "undetermined";
  const { status } = await Notifications.getPermissionsAsync();
  return status;
}

const DAILY_ID = "codexbar-daily-digest";

export async function scheduleDailyDigest(
  hour: number,
  minute: number,
  claudeUsage: ClaudeUsageResponse | null,
  codexUsage: CodexUsageResponse | null
): Promise<void> {
  if (!Notifications) return;
  try {
    await Notifications.cancelScheduledNotificationAsync(DAILY_ID);
  } catch {}

  const parts: string[] = [];
  if (claudeUsage) {
    parts.push(`Claude 7d: ${Math.round(claudeUsage.seven_day.utilization)}% used`);
  }
  if (codexUsage) {
    parts.push(
      `Codex: ${Math.round(codexUsage.secondary?.usedPercent ?? 0)}% used`
    );
  }

  await Notifications.scheduleNotificationAsync({
    identifier: DAILY_ID,
    content: {
      title: "Usage Digest",
      body:
        parts.length > 0
          ? parts.join(" · ")
          : "Open to check your usage limits",
    },
    trigger: {
      type: Notifications.SchedulableTriggerInputTypes.CALENDAR,
      hour,
      minute,
      repeats: true,
    },
  });
}

export async function cancelDailyDigest(): Promise<void> {
  if (!Notifications) return;
  try {
    await Notifications.cancelScheduledNotificationAsync(DAILY_ID);
  } catch {}
}

interface ThresholdAlert {
  service: string;
  window: string;
  remaining: number;
}

function buildThresholdAlerts(
  thresholdPct: number,
  claudeUsage: ClaudeUsageResponse | null,
  codexUsage: CodexUsageResponse | null
): ThresholdAlert[] {
  const alerts: ThresholdAlert[] = [];

  if (claudeUsage) {
    const remaining = 100 - claudeUsage.seven_day.utilization;
    if (remaining <= thresholdPct) {
      alerts.push({ service: "Claude", window: "7-day", remaining });
    }
  }

  if (codexUsage) {
    const remaining = 100 - (codexUsage.secondary?.usedPercent ?? 0);
    if (remaining <= thresholdPct) {
      alerts.push({ service: "Codex", window: "weekly", remaining });
    }
  }

  return alerts;
}

/** Call this after every successful usage fetch. Reschedules daily digest and fires threshold alerts. */
export async function onUsageDataLoaded(
  claudeUsage: ClaudeUsageResponse | null,
  codexUsage: CodexUsageResponse | null
): Promise<void> {
  const settings = await loadNotifSettings();

  if (settings.dailyEnabled) {
    await scheduleDailyDigest(
      settings.dailyHour,
      settings.dailyMinute,
      claudeUsage,
      codexUsage
    );
  }

  if (settings.thresholdEnabled) {
    const today = new Date().toISOString().slice(0, 10);
    const lastFired = await loadNotifThresholdLastFired();
    if (lastFired !== today) {
      const alerts = buildThresholdAlerts(
        settings.thresholdPct,
        claudeUsage,
        codexUsage
      );
      if (alerts.length > 0 && Notifications) {
        await Notifications.scheduleNotificationAsync({
          content: {
            title: "Low quota warning",
            body: alerts
              .map(
                (a) =>
                  `${a.service} ${a.window}: ${Math.round(a.remaining)}% remaining`
              )
              .join("\n"),
          },
          trigger: null,
        });
        await saveNotifThresholdLastFired(today);
      }
    }
  }
}
