import a from './index5.mjs';
import { i as inquirer } from './index6.mjs';
import { i18n } from './index2.mjs';
import { m as maskToken, a as isValidTokenFormat, c as generateDeviceToken, d as decryptToken, e as encryptToken, f as getDeviceInfo, i as isDeviceBound, g as getBindingStatus, u as unbindDevice, b as bindDevice, s as sendNotification } from '../shared/ccjk.DcMvE7lf.mjs';
import { exec } from 'node:child_process';
import * as fs from 'node:fs';
import fs__default from 'node:fs';
import * as os from 'node:os';
import os__default from 'node:os';
import * as path from 'node:path';
import path__default from 'node:path';
import process__default from 'node:process';
import { promisify } from 'node:util';
import { writeFileAtomic } from './fs-operations.mjs';
import { p as parse } from '../shared/ccjk.BBtCGd_g.mjs';
import { stringify } from './index3.mjs';
import { CLOUD_ENDPOINTS } from './constants.mjs';
import '../shared/ccjk.BAGoDD49.mjs';
import 'node:readline';
import 'stream';
import 'node:tty';
import 'node:async_hooks';
import '../shared/ccjk.Cjgrln_h.mjs';
import 'tty';
import 'fs';
import 'child_process';
import 'node:crypto';
import 'buffer';
import 'string_decoder';
import 'node:url';
import '../shared/ccjk.bQ7Dh1g4.mjs';
import '../shared/ccjk.D0g2ABGg.mjs';
import '../shared/ccjk.D6ycHbak.mjs';
import 'node:buffer';
import 'node:fs/promises';

const execAsync = promisify(exec);
const DEFAULT_CONFIG = {
  shortcutName: "ClaudeNotify",
  barkUrl: "",
  preferLocal: true,
  smartNotify: true,
  fallbackToBark: true
};
const CONFIG_DIR = path.join(os.homedir(), ".ccjk");
const CONFIG_FILE = path.join(CONFIG_DIR, "notification-config.json");
const TEMP_NOTIFICATION_FILE = "/tmp/ccjk-notification.json";
class LocalNotificationService {
  config;
  constructor(config) {
    this.config = { ...DEFAULT_CONFIG, ...config };
  }
  // ==========================================================================
  // Screen Lock Detection
  // ==========================================================================
  /**
   * Check if the macOS screen is locked
   *
   * Uses Python with Quartz framework to detect screen lock status.
   *
   * @returns true if screen is locked, false otherwise
   */
  async isScreenLocked() {
    if (process__default.platform !== "darwin") {
      return false;
    }
    try {
      const pythonScript = `
import Quartz
session_dict = Quartz.CGSessionCopyCurrentDictionary()
if session_dict:
    locked = session_dict.get('CGSSessionScreenIsLocked', False)
    print('true' if locked else 'false')
else:
    print('false')
`;
      const { stdout } = await execAsync(`python3 -c "${pythonScript}"`, {
        timeout: 5e3
      });
      return stdout.trim().toLowerCase() === "true";
    } catch (error) {
      console.error("Failed to detect screen lock status:", error);
      return false;
    }
  }
  // ==========================================================================
  // macOS Shortcut Notification
  // ==========================================================================
  /**
   * Send notification via macOS Shortcuts
   *
   * Creates a JSON file with notification data and runs the specified shortcut.
   * The shortcut should be configured to read the JSON and display a notification.
   *
   * @param shortcutName - Name of the macOS Shortcut to run
   * @param options - Notification options
   */
  async sendShortcutNotification(shortcutName, options) {
    if (process__default.platform !== "darwin") {
      throw new Error("macOS Shortcuts are only available on macOS");
    }
    const notificationData = {
      title: options.title,
      body: options.body,
      sound: options.sound !== false,
      url: options.url || "",
      group: options.group || "ccjk",
      timestamp: (/* @__PURE__ */ new Date()).toISOString()
    };
    writeFileAtomic(TEMP_NOTIFICATION_FILE, JSON.stringify(notificationData, null, 2), "utf-8");
    try {
      await execAsync(`shortcuts run "${shortcutName}" --input-path "${TEMP_NOTIFICATION_FILE}"`, {
        timeout: 3e4
        // 30 second timeout
      });
    } finally {
      try {
        if (fs.existsSync(TEMP_NOTIFICATION_FILE)) {
          fs.unlinkSync(TEMP_NOTIFICATION_FILE);
        }
      } catch {
      }
    }
  }
  // ==========================================================================
  // Bark Push Notification
  // ==========================================================================
  /**
   * Send notification via Bark push service
   *
   * Bark is an iOS app that allows sending push notifications via HTTP API.
   * API format: https://api.day.app/YOUR_KEY/title/body
   *
   * @param barkUrl - Bark API URL (e.g., https://api.day.app/YOUR_KEY)
   * @param options - Notification options
   */
  async sendBarkNotification(barkUrl, options) {
    if (!barkUrl) {
      throw new Error("Bark URL is not configured");
    }
    const encodedTitle = encodeURIComponent(options.title);
    const encodedBody = encodeURIComponent(options.body);
    const params = new URLSearchParams();
    if (options.sound !== false) {
      params.append("sound", "default");
    }
    if (options.url) {
      params.append("url", options.url);
    }
    if (options.group) {
      params.append("group", options.group);
    }
    if (options.icon) {
      params.append("icon", options.icon);
    }
    const baseUrl = barkUrl.endsWith("/") ? barkUrl.slice(0, -1) : barkUrl;
    let fullUrl = `${baseUrl}/${encodedTitle}/${encodedBody}`;
    const queryString = params.toString();
    if (queryString) {
      fullUrl += `?${queryString}`;
    }
    try {
      await execAsync(`curl -s -o /dev/null -w "%{http_code}" "${fullUrl}"`, {
        timeout: 1e4
      });
    } catch (error) {
      throw new Error(`Failed to send Bark notification: ${error}`);
    }
  }
  // ==========================================================================
  // Smart Notification
  // ==========================================================================
  /**
   * Smart notification - automatically choose notification method
   *
   * Logic:
   * 1. If screen is unlocked and preferLocal is true, use macOS Shortcut
   * 2. If screen is locked or shortcut fails, use Bark
   * 3. If both fail, throw error
   *
   * @param options - Notification options
   * @returns Notification result
   */
  async smartNotify(options) {
    const isLocked = await this.isScreenLocked();
    if (!isLocked && this.config.preferLocal && this.config.shortcutName) {
      try {
        await this.sendShortcutNotification(this.config.shortcutName, options);
        return {
          success: true,
          method: "shortcut"
        };
      } catch (error) {
        if (this.config.fallbackToBark && this.config.barkUrl) {
          try {
            await this.sendBarkNotification(this.config.barkUrl, options);
            return {
              success: true,
              method: "bark"
            };
          } catch (barkError) {
            return {
              success: false,
              method: "none",
              error: `Shortcut failed: ${error}. Bark also failed: ${barkError}`
            };
          }
        }
        return {
          success: false,
          method: "none",
          error: `Shortcut notification failed: ${error}`
        };
      }
    }
    if (this.config.barkUrl) {
      try {
        await this.sendBarkNotification(this.config.barkUrl, options);
        return {
          success: true,
          method: "bark"
        };
      } catch (error) {
        return {
          success: false,
          method: "none",
          error: `Bark notification failed: ${error}`
        };
      }
    }
    if (this.config.shortcutName) {
      try {
        await this.sendShortcutNotification(this.config.shortcutName, options);
        return {
          success: true,
          method: "shortcut"
        };
      } catch (error) {
        return {
          success: false,
          method: "none",
          error: `Shortcut notification failed: ${error}`
        };
      }
    }
    return {
      success: false,
      method: "none",
      error: "No notification method configured"
    };
  }
  // ==========================================================================
  // Configuration Management
  // ==========================================================================
  /**
   * Update service configuration
   *
   * @param config - Partial configuration to update
   */
  updateConfig(config) {
    this.config = { ...this.config, ...config };
  }
  /**
   * Get current configuration
   *
   * @returns Current configuration
   */
  getConfig() {
    return { ...this.config };
  }
}
async function loadLocalNotificationConfig() {
  try {
    if (!fs.existsSync(CONFIG_FILE)) {
      return { ...DEFAULT_CONFIG };
    }
    const content = fs.readFileSync(CONFIG_FILE, "utf-8");
    const config = JSON.parse(content);
    return {
      ...DEFAULT_CONFIG,
      ...config
    };
  } catch (error) {
    console.error("Failed to load local notification config:", error);
    return { ...DEFAULT_CONFIG };
  }
}
async function saveLocalNotificationConfig(config) {
  try {
    if (!fs.existsSync(CONFIG_DIR)) {
      fs.mkdirSync(CONFIG_DIR, { recursive: true });
    }
    const existingConfig = await loadLocalNotificationConfig();
    const newConfig = { ...existingConfig, ...config };
    writeFileAtomic(CONFIG_FILE, JSON.stringify(newConfig, null, 2));
  } catch (error) {
    throw new Error(`Failed to save local notification config: ${error}`);
  }
}
let serviceInstance = null;
async function getLocalNotificationService() {
  if (!serviceInstance) {
    const config = await loadLocalNotificationConfig();
    serviceInstance = new LocalNotificationService(config);
  }
  return serviceInstance;
}
async function isShortcutsAvailable() {
  if (process__default.platform !== "darwin") {
    return false;
  }
  try {
    await execAsync("which shortcuts", { timeout: 5e3 });
    return true;
  } catch {
    return false;
  }
}
async function listShortcuts() {
  if (process__default.platform !== "darwin") {
    return [];
  }
  try {
    const { stdout } = await execAsync("shortcuts list", { timeout: 1e4 });
    return stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
  } catch {
    return [];
  }
}
function isValidBarkUrl(url) {
  if (!url) {
    return false;
  }
  try {
    const parsed = new URL(url);
    return parsed.protocol === "https:" || parsed.protocol === "http:";
  } catch {
    return false;
  }
}

const DEFAULT_NOTIFICATION_CONFIG = {
  enabled: false,
  deviceToken: "",
  threshold: 10,
  // 10 minutes
  cloudEndpoint: `${CLOUD_ENDPOINTS.REMOTE.BASE_URL}/api/v1`,
  channels: {},
  quietHours: {
    enabled: false,
    startHour: 22,
    endHour: 8
  }
};
function validateNotificationConfig(config) {
  const errors = [];
  const warnings = [];
  if (config.threshold !== void 0) {
    if (config.threshold < 1) {
      errors.push({
        field: "threshold",
        message: "Threshold must be at least 1 minute",
        code: "THRESHOLD_TOO_LOW"
      });
    }
    if (config.threshold > 1440) {
      warnings.push("Threshold is set to more than 24 hours");
    }
  }
  if (config.channels?.feishu?.enabled) {
    if (!config.channels.feishu.webhookUrl) {
      errors.push({
        field: "channels.feishu.webhookUrl",
        message: "Feishu webhook URL is required when enabled",
        code: "FEISHU_WEBHOOK_REQUIRED"
      });
    } else if (!config.channels.feishu.webhookUrl.startsWith("https://")) {
      errors.push({
        field: "channels.feishu.webhookUrl",
        message: "Feishu webhook URL must use HTTPS",
        code: "FEISHU_WEBHOOK_INVALID"
      });
    }
  }
  if (config.channels?.wechat?.enabled) {
    if (!config.channels.wechat.corpId) {
      errors.push({
        field: "channels.wechat.corpId",
        message: "WeChat Work Corp ID is required when enabled",
        code: "WECHAT_CORPID_REQUIRED"
      });
    }
    if (!config.channels.wechat.agentId) {
      errors.push({
        field: "channels.wechat.agentId",
        message: "WeChat Work Agent ID is required when enabled",
        code: "WECHAT_AGENTID_REQUIRED"
      });
    }
    if (!config.channels.wechat.secret) {
      errors.push({
        field: "channels.wechat.secret",
        message: "WeChat Work Secret is required when enabled",
        code: "WECHAT_SECRET_REQUIRED"
      });
    }
  }
  if (config.channels?.email?.enabled) {
    if (!config.channels.email.address) {
      errors.push({
        field: "channels.email.address",
        message: "Email address is required when enabled",
        code: "EMAIL_ADDRESS_REQUIRED"
      });
    } else if (!/^[^\s@]+@[^\s@][^\s.@]*\.[^\s@]+$/.test(config.channels.email.address)) {
      errors.push({
        field: "channels.email.address",
        message: "Invalid email address format",
        code: "EMAIL_ADDRESS_INVALID"
      });
    }
  }
  if (config.channels?.sms?.enabled) {
    if (!config.channels.sms.phone) {
      errors.push({
        field: "channels.sms.phone",
        message: "Phone number is required when enabled",
        code: "SMS_PHONE_REQUIRED"
      });
    } else if (!/^\d{10,15}$/.test(config.channels.sms.phone.replace(/\D/g, ""))) {
      errors.push({
        field: "channels.sms.phone",
        message: "Invalid phone number format",
        code: "SMS_PHONE_INVALID"
      });
    }
  }
  if (config.quietHours?.enabled) {
    if (config.quietHours.startHour < 0 || config.quietHours.startHour > 23) {
      errors.push({
        field: "quietHours.startHour",
        message: "Start hour must be between 0 and 23",
        code: "QUIET_HOURS_INVALID"
      });
    }
    if (config.quietHours.endHour < 0 || config.quietHours.endHour > 23) {
      errors.push({
        field: "quietHours.endHour",
        message: "End hour must be between 0 and 23",
        code: "QUIET_HOURS_INVALID"
      });
    }
  }
  return {
    valid: errors.length === 0,
    errors,
    warnings
  };
}

const CCJK_CONFIG_DIR = path__default.join(os__default.homedir(), ".ccjk");
const CONFIG_FILE_PATH = path__default.join(CCJK_CONFIG_DIR, "config.toml");
const SECRETS_FILE_PATH = path__default.join(CCJK_CONFIG_DIR, ".notification-secrets");
async function loadNotificationConfig() {
  try {
    if (!fs__default.existsSync(CCJK_CONFIG_DIR)) {
      fs__default.mkdirSync(CCJK_CONFIG_DIR, { recursive: true });
    }
    if (!fs__default.existsSync(CONFIG_FILE_PATH)) {
      return { ...DEFAULT_NOTIFICATION_CONFIG };
    }
    const configContent = fs__default.readFileSync(CONFIG_FILE_PATH, "utf-8");
    const config = parse(configContent);
    const notificationConfig = config.notification;
    if (!notificationConfig) {
      return { ...DEFAULT_NOTIFICATION_CONFIG };
    }
    const deviceToken = await loadDeviceToken();
    const quietHoursConfig = notificationConfig.quietHours || {};
    const defaultQuietHours = DEFAULT_NOTIFICATION_CONFIG.quietHours || {
      enabled: false,
      startHour: 22,
      endHour: 8,
      timezone: "local"
    };
    return {
      ...DEFAULT_NOTIFICATION_CONFIG,
      ...notificationConfig,
      deviceToken: deviceToken || notificationConfig.deviceToken || "",
      channels: {
        ...DEFAULT_NOTIFICATION_CONFIG.channels,
        ...notificationConfig.channels
      },
      quietHours: {
        enabled: quietHoursConfig.enabled ?? defaultQuietHours.enabled,
        startHour: quietHoursConfig.startHour ?? defaultQuietHours.startHour,
        endHour: quietHoursConfig.endHour ?? defaultQuietHours.endHour,
        timezone: quietHoursConfig.timezone ?? defaultQuietHours.timezone
      }
    };
  } catch (error) {
    console.error("Failed to load notification config:", error);
    return { ...DEFAULT_NOTIFICATION_CONFIG };
  }
}
async function loadDeviceToken() {
  try {
    if (!fs__default.existsSync(SECRETS_FILE_PATH)) {
      return null;
    }
    const secretsContent = fs__default.readFileSync(SECRETS_FILE_PATH, "utf-8");
    const secrets = JSON.parse(secretsContent);
    if (!secrets.deviceToken) {
      return null;
    }
    const decryptedToken = decryptToken(secrets.deviceToken);
    return decryptedToken;
  } catch {
    return null;
  }
}
async function saveNotificationConfig(config) {
  try {
    if (!fs__default.existsSync(CCJK_CONFIG_DIR)) {
      fs__default.mkdirSync(CCJK_CONFIG_DIR, { recursive: true });
    }
    let existingConfig = {};
    if (fs__default.existsSync(CONFIG_FILE_PATH)) {
      const configContent = fs__default.readFileSync(CONFIG_FILE_PATH, "utf-8");
      existingConfig = parse(configContent);
    }
    const notificationConfig = { ...config };
    if (notificationConfig.deviceToken) {
      await saveDeviceToken(notificationConfig.deviceToken);
      delete notificationConfig.deviceToken;
    }
    existingConfig.notification = {
      ...existingConfig.notification || {},
      ...notificationConfig
    };
    const tomlContent = stringify(existingConfig);
    writeFileAtomic(CONFIG_FILE_PATH, tomlContent);
  } catch (error) {
    throw new Error(`Failed to save notification config: ${error}`);
  }
}
async function saveDeviceToken(token) {
  try {
    const encryptedToken = encryptToken(token);
    let secrets = {};
    if (fs__default.existsSync(SECRETS_FILE_PATH)) {
      const secretsContent = fs__default.readFileSync(SECRETS_FILE_PATH, "utf-8");
      secrets = JSON.parse(secretsContent);
    }
    secrets.deviceToken = encryptedToken;
    secrets.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
    writeFileAtomic(SECRETS_FILE_PATH, JSON.stringify(secrets, null, 2), {
      encoding: "utf-8",
      mode: 384
      // Owner read/write only
    });
  } catch (error) {
    throw new Error(`Failed to save device token: ${error}`);
  }
}
async function initializeNotificationConfig() {
  const existingConfig = await loadNotificationConfig();
  if (!existingConfig.deviceToken || !isValidTokenFormat(existingConfig.deviceToken)) {
    existingConfig.deviceToken = generateDeviceToken();
    await saveNotificationConfig(existingConfig);
  }
  return existingConfig;
}
async function updateNotificationConfig(updates) {
  const currentConfig = await loadNotificationConfig();
  const updatesQuietHours = updates.quietHours || {};
  const currentQuietHours = currentConfig.quietHours || {
    enabled: false,
    startHour: 22,
    endHour: 8,
    timezone: "local"
  };
  const newConfig = {
    ...currentConfig,
    ...updates,
    channels: {
      ...currentConfig.channels,
      ...updates.channels
    },
    quietHours: {
      enabled: updatesQuietHours.enabled ?? currentQuietHours.enabled,
      startHour: updatesQuietHours.startHour ?? currentQuietHours.startHour,
      endHour: updatesQuietHours.endHour ?? currentQuietHours.endHour,
      timezone: updatesQuietHours.timezone ?? currentQuietHours.timezone
    }
  };
  await saveNotificationConfig(newConfig);
  return newConfig;
}
async function enableChannel(channel, config) {
  const currentConfig = await loadNotificationConfig();
  currentConfig.channels[channel] = {
    ...config,
    enabled: true
  };
  await saveNotificationConfig(currentConfig);
}
async function disableChannel(channel) {
  const currentConfig = await loadNotificationConfig();
  if (currentConfig.channels[channel]) {
    currentConfig.channels[channel].enabled = false;
    await saveNotificationConfig(currentConfig);
  }
}
async function getEnabledChannels() {
  const config = await loadNotificationConfig();
  const enabledChannels = [];
  if (config.channels.feishu?.enabled) {
    enabledChannels.push("feishu");
  }
  if (config.channels.wechat?.enabled) {
    enabledChannels.push("wechat");
  }
  if (config.channels.email?.enabled) {
    enabledChannels.push("email");
  }
  if (config.channels.sms?.enabled) {
    enabledChannels.push("sms");
  }
  return enabledChannels;
}
async function validateCurrentConfig() {
  const config = await loadNotificationConfig();
  return validateNotificationConfig(config);
}
async function getConfigSummary() {
  const config = await loadNotificationConfig();
  const enabledChannels = await getEnabledChannels();
  return {
    enabled: config.enabled,
    deviceToken: maskToken(config.deviceToken),
    threshold: config.threshold,
    enabledChannels,
    quietHours: {
      enabled: config.quietHours?.enabled || false,
      hours: config.quietHours?.enabled ? `${config.quietHours.startHour}:00 - ${config.quietHours.endHour}:00` : void 0
    }
  };
}
const THRESHOLD_OPTIONS = [
  { value: 5, label: "5 minutes" },
  { value: 10, label: "10 minutes" },
  { value: 15, label: "15 minutes" },
  { value: 30, label: "30 minutes" },
  { value: 60, label: "1 hour" }
];
async function setThreshold(minutes) {
  if (minutes < 1) {
    throw new Error("Threshold must be at least 1 minute");
  }
  await updateNotificationConfig({ threshold: minutes });
}
async function enableNotifications() {
  await updateNotificationConfig({ enabled: true });
}
async function disableNotifications() {
  await updateNotificationConfig({ enabled: false });
}

const DEFAULT_CLOUD_ENDPOINT = `${CLOUD_ENDPOINTS.REMOTE.BASE_URL}/api/v1`;
const REQUEST_TIMEOUT = 3e4;
const POLL_TIMEOUT = 6e4;
class CloudClient {
  static instance = null;
  endpoint = DEFAULT_CLOUD_ENDPOINT;
  deviceToken = "";
  isPolling = false;
  pollAbortController = null;
  constructor() {
  }
  /**
   * Get the singleton instance
   */
  static getInstance() {
    if (!CloudClient.instance) {
      CloudClient.instance = new CloudClient();
    }
    return CloudClient.instance;
  }
  /**
   * Initialize the cloud client
   */
  async initialize() {
    const config = await loadNotificationConfig();
    this.endpoint = config.cloudEndpoint || DEFAULT_CLOUD_ENDPOINT;
    this.deviceToken = config.deviceToken;
  }
  /**
   * Set the cloud endpoint
   */
  setEndpoint(endpoint) {
    this.endpoint = endpoint;
  }
  /**
   * Set the device token
   */
  setDeviceToken(token) {
    this.deviceToken = token;
  }
  // ==========================================================================
  // Device Registration
  // ==========================================================================
  /**
   * Register this device with the cloud service
   */
  async registerDevice(name) {
    const deviceInfo = getDeviceInfo();
    const config = await loadNotificationConfig();
    const channelsArray = this.convertChannelsToArray(config.channels);
    const request = {
      name: name || deviceInfo.name,
      platform: deviceInfo.platform,
      version: "1.0.0",
      // Static version for cloud client
      config: {
        channels: channelsArray,
        threshold: config.threshold
      }
    };
    const response = await this.request(
      "/device/register",
      {
        method: "POST",
        body: JSON.stringify(request)
      }
    );
    if (response.success && response.data) {
      await updateNotificationConfig({
        deviceToken: response.data.token
      });
      this.deviceToken = response.data.token;
      return response.data;
    }
    throw new Error(response.error || "Failed to register device");
  }
  /**
   * Get device info from cloud service
   */
  async getDeviceInfo() {
    const response = await this.request(
      "/device/info",
      { method: "GET" }
    );
    if (response.success && response.data) {
      return response.data;
    }
    throw new Error(response.error || "Failed to get device info");
  }
  /**
   * Update device channels on cloud service
   */
  async updateChannels(channels) {
    const channelsArray = this.convertChannelsToArray(channels);
    const response = await this.request(
      "/device/channels",
      {
        method: "PUT",
        body: JSON.stringify({ channels: channelsArray })
      }
    );
    if (!response.success) {
      throw new Error(response.error || "Failed to update channels");
    }
  }
  // ==========================================================================
  // Notification Sending
  // ==========================================================================
  /**
   * Send a notification through the cloud service
   */
  async sendNotification(message, channels) {
    const config = await loadNotificationConfig();
    const targetChannels = channels || this.getEnabledChannelsFromConfig(config.channels);
    if (targetChannels.length === 0) {
      return [];
    }
    const title = message.title || this.generateTitle(message.type);
    const body = this.generateBody(message);
    const response = await this.request(
      "/notify",
      {
        method: "POST",
        body: JSON.stringify({
          type: message.type,
          title,
          body,
          task: message.task,
          channels: targetChannels,
          actions: message.actions,
          priority: message.priority
        })
      }
    );
    if (response.success && response.data) {
      return response.data.results;
    }
    return targetChannels.map((channel) => ({
      success: false,
      channel,
      sentAt: /* @__PURE__ */ new Date(),
      error: response.error || "Failed to send notification"
    }));
  }
  /**
   * Send a test notification
   */
  async sendTestNotification() {
    const response = await this.request(
      "/notify/test",
      { method: "POST" }
    );
    if (response.success && response.data) {
      return response.data.results;
    }
    throw new Error(response.error || "Failed to send test notification");
  }
  // ==========================================================================
  // Reply Polling
  // ==========================================================================
  /**
   * Start polling for replies
   *
   * @param onReply - Callback when a reply is received
   * @param onError - Callback when an error occurs
   */
  startPolling(onReply, onError) {
    if (this.isPolling) {
      return;
    }
    this.isPolling = true;
    this.pollLoop(onReply, onError);
  }
  /**
   * Stop polling for replies
   */
  stopPolling() {
    this.isPolling = false;
    if (this.pollAbortController) {
      this.pollAbortController.abort();
      this.pollAbortController = null;
    }
  }
  /**
   * Poll loop for replies
   */
  async pollLoop(onReply, onError) {
    while (this.isPolling) {
      try {
        const reply = await this.pollForReply();
        if (reply) {
          onReply(reply);
        }
      } catch (error) {
        if (error instanceof Error && error.name === "AbortError") {
          break;
        }
        onError?.(error instanceof Error ? error : new Error(String(error)));
        await this.sleep(5e3);
      }
    }
  }
  /**
   * Poll for a single reply (long-polling)
   */
  async pollForReply() {
    this.pollAbortController = new AbortController();
    try {
      const response = await this.request(
        "/reply/poll",
        {
          method: "GET",
          signal: this.pollAbortController.signal,
          timeout: POLL_TIMEOUT
        }
      );
      if (response.success && response.data?.reply) {
        return {
          ...response.data.reply,
          timestamp: new Date(response.data.reply.timestamp)
        };
      }
      return null;
    } finally {
      this.pollAbortController = null;
    }
  }
  /**
   * Get reply for a specific notification
   */
  async getReply(notificationId) {
    const response = await this.request(
      `/reply/${notificationId}`,
      { method: "GET" }
    );
    if (response.success && response.data?.reply) {
      return {
        ...response.data.reply,
        timestamp: new Date(response.data.reply.timestamp)
      };
    }
    return null;
  }
  // ==========================================================================
  // HTTP Request Helper
  // ==========================================================================
  /**
   * Make an HTTP request to the cloud service
   */
  async request(path, options) {
    const url = `${this.endpoint}${path}`;
    const timeout = options.timeout || REQUEST_TIMEOUT;
    const timeoutController = new AbortController();
    const timeoutId = setTimeout(() => timeoutController.abort(), timeout);
    try {
      const response = await fetch(url, {
        method: options.method,
        headers: {
          "Content-Type": "application/json",
          "X-Device-Token": this.deviceToken
        },
        body: options.body,
        signal: options.signal || timeoutController.signal
      });
      clearTimeout(timeoutId);
      const data = await response.json();
      if (!response.ok) {
        return {
          success: false,
          error: data.error || `HTTP ${response.status}: ${response.statusText}`,
          code: data.code
        };
      }
      return data;
    } catch (error) {
      clearTimeout(timeoutId);
      if (error instanceof Error) {
        if (error.name === "AbortError") {
          throw error;
        }
        return {
          success: false,
          error: error.message,
          code: "NETWORK_ERROR"
        };
      }
      return {
        success: false,
        error: String(error),
        code: "UNKNOWN_ERROR"
      };
    }
  }
  // ==========================================================================
  // Utility Methods
  // ==========================================================================
  /**
   * Get enabled channels from config
   */
  getEnabledChannelsFromConfig(channels) {
    const enabledChannels = [];
    for (const [name, channelConfig] of Object.entries(channels)) {
      if (channelConfig?.enabled) {
        enabledChannels.push(name);
      }
    }
    return enabledChannels;
  }
  /**
   * Sleep for a specified duration
   */
  sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }
  /**
   * Convert channels from object format to array format
   *
   * Converts from: { feishu: { enabled: true, webhookUrl: "..." } }
   * To: [{ type: "feishu", enabled: true, config: { webhookUrl: "..." } }]
   */
  convertChannelsToArray(channels) {
    const result = [];
    for (const [channelType, channelData] of Object.entries(channels)) {
      if (channelData && typeof channelData === "object") {
        const { enabled, ...config } = channelData;
        result.push({
          type: channelType,
          enabled: Boolean(enabled),
          config
        });
      }
    }
    return result;
  }
  /**
   * Generate notification title based on type
   */
  generateTitle(type) {
    const titles = {
      task_started: "Task Started",
      task_progress: "Task Progress",
      task_completed: "Task Completed",
      task_failed: "Task Failed",
      task_cancelled: "Task Cancelled",
      system: "System Notification"
    };
    return titles[type] || "Notification";
  }
  /**
   * Generate notification body from message
   */
  generateBody(message) {
    const { task } = message;
    const lines = [];
    lines.push(`**Task**: ${task.description}`);
    lines.push(`**Status**: ${task.status}`);
    if (task.duration) {
      const minutes = Math.floor(task.duration / 6e4);
      const seconds = Math.floor(task.duration % 6e4 / 1e3);
      lines.push(`**Duration**: ${minutes}m ${seconds}s`);
    }
    if (task.result) {
      lines.push(`**Result**: ${task.result}`);
    }
    if (task.error) {
      lines.push(`**Error**: ${task.error}`);
    }
    return lines.join("\n");
  }
  /**
   * Reset the singleton instance (for testing)
   */
  static resetInstance() {
    if (CloudClient.instance) {
      CloudClient.instance.stopPolling();
      CloudClient.instance = null;
    }
  }
}

async function notificationCommand(action = "menu", args) {
  switch (action) {
    case "config":
    case "configure":
      await runConfigWizard();
      break;
    case "status":
      await showStatus();
      break;
    case "test":
      await sendTestNotification();
      break;
    case "enable":
      await enableNotifications();
      console.log(a.green(`\u2705 ${i18n.t("notification:status.enabled")}`));
      break;
    case "disable":
      await disableNotifications();
      console.log(a.yellow(`\u23F8\uFE0F ${i18n.t("notification:status.disabled")}`));
      break;
    case "channels":
      await manageChannels();
      break;
    case "threshold":
      await configureThreshold();
      break;
    case "bind":
      console.log(a.yellow(i18n.t("notification:cloud.migrateToRemoteSetup")));
      await handleBind(args?.[0]);
      break;
    case "unbind":
      await handleUnbind();
      break;
    case "cloud-status":
      await showCloudStatus();
      break;
    case "local-config":
      await configureLocalNotification();
      break;
    case "local-test":
      await testLocalNotification();
      break;
    case "menu":
    default:
      await showNotificationMenu();
      break;
  }
}
async function showNotificationMenu() {
  const config = await loadNotificationConfig();
  const enabledChannels = await getEnabledChannels();
  const cloudBound = isDeviceBound();
  console.log("");
  console.log(a.bold.cyan(i18n.t("notification:menu.title")));
  console.log("");
  const statusText = config.enabled ? a.green(i18n.t("notification:status.enabled")) : a.yellow(i18n.t("notification:status.disabled"));
  console.log(`  ${a.dim(i18n.t("notification:menu.statusLabel"))} ${statusText}`);
  const cloudStatusText = cloudBound ? a.green(i18n.t("notification:cloud.bound")) : a.yellow(i18n.t("notification:cloud.notBound"));
  console.log(`  ${a.dim(i18n.t("notification:cloud.statusLabel"))} ${cloudStatusText}`);
  if (enabledChannels.length > 0) {
    const channelNames = enabledChannels.map((ch) => i18n.t(`notification:channels.${ch}`)).join(", ");
    console.log(`  ${a.dim(i18n.t("notification:menu.channelsLabel"))} ${channelNames}`);
  } else {
    console.log(`  ${a.dim(i18n.t("notification:menu.channelsLabel"))} ${a.yellow(i18n.t("notification:channels.noChannels"))}`);
  }
  console.log(`  ${a.dim(i18n.t("notification:menu.thresholdLabel"))} ${config.threshold} ${i18n.t("notification:config.threshold.minutes", { count: config.threshold })}`);
  console.log("");
  const choices = [];
  if (!cloudBound) {
    choices.push({ name: `\u{1F517} ${i18n.t("notification:cloud.bindDevice")}`, value: "bind" });
  } else {
    choices.push({ name: `\u2601\uFE0F  ${i18n.t("notification:cloud.viewStatus")}`, value: "cloud-status" });
  }
  choices.push({
    name: config.enabled ? `\u23F8\uFE0F  ${i18n.t("notification:menu.disable")}` : `\u25B6\uFE0F  ${i18n.t("notification:menu.enable")}`,
    value: config.enabled ? "disable" : "enable"
  });
  choices.push(
    { name: `\u2699\uFE0F  ${i18n.t("notification:menu.configWizard")}`, value: "config" },
    { name: `\u{1F4F1} ${i18n.t("notification:menu.manageChannels")}`, value: "channels" },
    { name: `\u{1F514} ${i18n.t("notification:local.menuTitle")}`, value: "local-config" },
    { name: `\u23F1\uFE0F  ${i18n.t("notification:menu.setThreshold")}`, value: "threshold" },
    { name: `\u{1F4CA} ${i18n.t("notification:menu.viewStatus")}`, value: "status" },
    { name: `\u{1F9EA} ${i18n.t("notification:menu.sendTest")}`, value: "test" }
  );
  if (cloudBound) {
    choices.push({ name: `\u{1F513} ${i18n.t("notification:cloud.unbindDevice")}`, value: "unbind" });
  }
  choices.push({ name: `\u2190 ${i18n.t("notification:menu.back")}`, value: "back" });
  const { action } = await inquirer.prompt([{
    type: "list",
    name: "action",
    message: i18n.t("notification:menu.selectAction"),
    choices
  }]);
  if (action === "back") {
    return;
  }
  await notificationCommand(action);
}
async function runConfigWizard() {
  console.log("");
  console.log(a.bold.cyan(i18n.t("notification:config.wizard.title")));
  console.log(a.dim(i18n.t("notification:config.wizard.welcome")));
  console.log("");
  console.log(a.yellow(i18n.t("notification:config.wizard.step1")));
  const config = await initializeNotificationConfig();
  console.log(a.green(i18n.t("notification:config.wizard.tokenGenerated", { token: maskToken(config.deviceToken) })));
  console.log("");
  console.log(a.yellow(i18n.t("notification:config.wizard.step2")));
  const channels = await selectChannels();
  console.log("");
  if (channels.length > 0) {
    console.log(a.yellow(i18n.t("notification:config.wizard.step3")));
    for (const channel of channels) {
      await configureChannel(channel);
    }
    console.log("");
  }
  console.log(a.yellow(i18n.t("notification:config.wizard.step4")));
  await configureThreshold();
  console.log("");
  console.log(a.yellow(i18n.t("notification:config.wizard.step5")));
  await updateNotificationConfig({ enabled: true });
  const { shouldTest } = await inquirer.prompt([{
    type: "confirm",
    name: "shouldTest",
    message: "\u662F\u5426\u53D1\u9001\u6D4B\u8BD5\u901A\u77E5?",
    default: true
  }]);
  if (shouldTest) {
    await sendTestNotification();
  }
  console.log("");
  console.log(a.bold.green(i18n.t("notification:config.wizard.complete")));
  console.log("");
}
async function selectChannels() {
  const choices = [
    { name: `\u{1F4F1} ${i18n.t("notification:channels.feishu")}`, value: "feishu" },
    { name: `\u{1F4AC} ${i18n.t("notification:channels.wechat")}`, value: "wechat" },
    { name: `\u{1F4E7} ${i18n.t("notification:channels.email")}`, value: "email" },
    { name: `\u{1F4F2} ${i18n.t("notification:channels.sms")}`, value: "sms" }
  ];
  const selected = [];
  for (const choice of choices) {
    const { enable } = await inquirer.prompt([{
      type: "confirm",
      name: "enable",
      message: `\u542F\u7528 ${choice.name}?`,
      default: false
    }]);
    if (enable) {
      selected.push(choice.value);
    }
  }
  return selected;
}
async function configureChannel(channel) {
  console.log("");
  console.log(a.green(`\u914D\u7F6E ${i18n.t(`notification:channels.${channel}`)}:`));
  switch (channel) {
    case "feishu":
      await configureFeishu();
      break;
    case "wechat":
      await configureWechat();
      break;
    case "email":
      await configureEmail();
      break;
    case "sms":
      await configureSms();
      break;
  }
}
async function configureFeishu() {
  const { webhookUrl } = await inquirer.prompt([{
    type: "input",
    name: "webhookUrl",
    message: i18n.t("notification:feishu.webhookUrl"),
    validate: (value) => {
      if (!value.startsWith("https://")) {
        return i18n.t("notification:errors.invalidWebhook");
      }
      return true;
    }
  }]);
  const { secret } = await inquirer.prompt([{
    type: "input",
    name: "secret",
    message: `${i18n.t("notification:feishu.secret")} (\u53EF\u9009\uFF0C\u76F4\u63A5\u56DE\u8F66\u8DF3\u8FC7):`
  }]);
  const config = {
    enabled: true,
    webhookUrl,
    ...secret && { secret }
  };
  await enableChannel("feishu", config);
  console.log(a.green(`\u2705 ${i18n.t("notification:channels.feishu")} ${i18n.t("notification:status.configured")}`));
}
async function configureWechat() {
  const { corpId } = await inquirer.prompt([{
    type: "input",
    name: "corpId",
    message: i18n.t("notification:wechat.corpId"),
    validate: (value) => !!value || i18n.t("notification:errors.invalidWebhook")
  }]);
  const { agentId } = await inquirer.prompt([{
    type: "input",
    name: "agentId",
    message: i18n.t("notification:wechat.agentId"),
    validate: (value) => !!value || i18n.t("notification:errors.invalidWebhook")
  }]);
  const { secret } = await inquirer.prompt([{
    type: "input",
    name: "secret",
    message: i18n.t("notification:wechat.secret"),
    validate: (value) => !!value || i18n.t("notification:errors.invalidWebhook")
  }]);
  const config = {
    enabled: true,
    corpId,
    agentId,
    secret
  };
  await enableChannel("wechat", config);
  console.log(a.green(`\u2705 ${i18n.t("notification:channels.wechat")} ${i18n.t("notification:status.configured")}`));
}
async function configureEmail() {
  const { address } = await inquirer.prompt([{
    type: "input",
    name: "address",
    message: i18n.t("notification:email.address"),
    validate: (value) => {
      if (!/^[^\s@]+@[^\s@][^\s.@]*\.[^\s@]+$/.test(value)) {
        return i18n.t("notification:errors.invalidEmail");
      }
      return true;
    }
  }]);
  const config = {
    enabled: true,
    address
  };
  await enableChannel("email", config);
  console.log(a.green(`\u2705 ${i18n.t("notification:channels.email")} ${i18n.t("notification:status.configured")}`));
}
async function configureSms() {
  const { phone } = await inquirer.prompt([{
    type: "input",
    name: "phone",
    message: i18n.t("notification:sms.phone"),
    validate: (value) => {
      if (!/^\d{10,15}$/.test(value.replace(/\D/g, ""))) {
        return i18n.t("notification:errors.invalidPhone");
      }
      return true;
    }
  }]);
  const { countryCode } = await inquirer.prompt([{
    type: "input",
    name: "countryCode",
    message: i18n.t("notification:sms.countryCode"),
    default: "+86"
  }]);
  const config = {
    enabled: true,
    phone,
    countryCode
  };
  await enableChannel("sms", config);
  console.log(a.green(`\u2705 ${i18n.t("notification:channels.sms")} ${i18n.t("notification:status.configured")}`));
}
async function manageChannels() {
  const enabledChannels = await getEnabledChannels();
  console.log("");
  console.log(a.bold.cyan(i18n.t("notification:channels.title")));
  console.log("");
  if (enabledChannels.length === 0) {
    console.log(a.yellow(i18n.t("notification:channels.noChannels")));
  } else {
    console.log(i18n.t("notification:channels.enabledCount", { count: enabledChannels.length }));
    for (const channel of enabledChannels) {
      console.log(`  \u2705 ${i18n.t(`notification:channels.${channel}`)}`);
    }
  }
  console.log("");
  const { action } = await inquirer.prompt([{
    type: "list",
    name: "action",
    message: "\u9009\u62E9\u64CD\u4F5C:",
    choices: [
      { name: "\u2795 \u6DFB\u52A0\u6E20\u9053", value: "add" },
      { name: "\u2796 \u79FB\u9664\u6E20\u9053", value: "remove" },
      { name: "\u2190 \u8FD4\u56DE", value: "back" }
    ]
  }]);
  if (action === "back") {
    return;
  }
  if (action === "add") {
    const allChannels = ["feishu", "wechat", "email", "sms"];
    const availableChannels = allChannels.filter((ch) => !enabledChannels.includes(ch));
    if (availableChannels.length === 0) {
      console.log(a.yellow("\u6240\u6709\u6E20\u9053\u90FD\u5DF2\u542F\u7528"));
      return;
    }
    const { channel } = await inquirer.prompt([{
      type: "list",
      name: "channel",
      message: "\u9009\u62E9\u8981\u6DFB\u52A0\u7684\u6E20\u9053:",
      choices: availableChannels.map((ch) => ({
        name: i18n.t(`notification:channels.${ch}`),
        value: ch
      }))
    }]);
    await configureChannel(channel);
  } else if (action === "remove") {
    if (enabledChannels.length === 0) {
      console.log(a.yellow("\u6CA1\u6709\u5DF2\u542F\u7528\u7684\u6E20\u9053"));
      return;
    }
    const { channel } = await inquirer.prompt([{
      type: "list",
      name: "channel",
      message: "\u9009\u62E9\u8981\u79FB\u9664\u7684\u6E20\u9053:",
      choices: enabledChannels.map((ch) => ({
        name: i18n.t(`notification:channels.${ch}`),
        value: ch
      }))
    }]);
    await disableChannel(channel);
    console.log(a.green(`\u2705 \u5DF2\u79FB\u9664 ${i18n.t(`notification:channels.${channel}`)}`));
  }
}
async function configureThreshold() {
  const config = await loadNotificationConfig();
  console.log("");
  console.log(a.dim(i18n.t("notification:config.threshold.description")));
  console.log("");
  const { threshold } = await inquirer.prompt([{
    type: "list",
    name: "threshold",
    message: i18n.t("notification:config.threshold.title"),
    choices: [
      ...THRESHOLD_OPTIONS.map((opt) => ({
        name: opt.label,
        value: opt.value
      })),
      { name: i18n.t("notification:config.threshold.custom"), value: -1 }
    ],
    default: config.threshold
  }]);
  let finalThreshold = threshold;
  if (threshold === -1) {
    const { customValue } = await inquirer.prompt([{
      type: "input",
      name: "customValue",
      message: "\u8F93\u5165\u81EA\u5B9A\u4E49\u9608\u503C\uFF08\u5206\u949F\uFF09:",
      validate: (value) => {
        const num = Number.parseInt(value, 10);
        if (Number.isNaN(num) || num < 1) {
          return "\u8BF7\u8F93\u5165\u5927\u4E8E 0 \u7684\u6570\u5B57";
        }
        return true;
      }
    }]);
    finalThreshold = Number.parseInt(customValue, 10);
  }
  await setThreshold(finalThreshold);
  console.log(a.green(`\u2705 \u9608\u503C\u5DF2\u8BBE\u7F6E\u4E3A ${finalThreshold} \u5206\u949F`));
}
async function showStatus() {
  const summary = await getConfigSummary();
  const validation = await validateCurrentConfig();
  console.log("");
  console.log(a.bold.cyan("\u{1F4CA} \u901A\u77E5\u7CFB\u7EDF\u72B6\u6001"));
  console.log("");
  const statusIcon = summary.enabled ? "\u2705" : "\u23F8\uFE0F";
  const statusText = summary.enabled ? a.green(i18n.t("notification:status.enabled")) : a.yellow(i18n.t("notification:status.disabled"));
  console.log(`  ${statusIcon} \u72B6\u6001: ${statusText}`);
  console.log(`  \u{1F511} \u8BBE\u5907\u4EE4\u724C: ${a.dim(summary.deviceToken)}`);
  console.log(`  \u23F1\uFE0F  \u9608\u503C: ${summary.threshold} \u5206\u949F`);
  console.log("");
  console.log(a.bold("  \u{1F4F1} \u901A\u77E5\u6E20\u9053:"));
  if (summary.enabledChannels.length === 0) {
    console.log(`     ${a.yellow(i18n.t("notification:channels.noChannels"))}`);
  } else {
    for (const channel of summary.enabledChannels) {
      console.log(`     \u2705 ${i18n.t(`notification:channels.${channel}`)}`);
    }
  }
  if (summary.quietHours.enabled) {
    console.log("");
    console.log(`  \u{1F319} \u514D\u6253\u6270: ${summary.quietHours.hours}`);
  }
  if (!validation.valid) {
    console.log("");
    console.log(a.bold.red("  \u26A0\uFE0F \u914D\u7F6E\u95EE\u9898:"));
    for (const error of validation.errors) {
      console.log(`     \u274C ${error.message}`);
    }
  }
  if (validation.warnings.length > 0) {
    console.log("");
    console.log(a.bold.yellow("  \u26A0\uFE0F \u8B66\u544A:"));
    for (const warning of validation.warnings) {
      console.log(`     \u26A0\uFE0F ${warning}`);
    }
  }
  console.log("");
}
async function sendTestNotification() {
  const enabledChannels = await getEnabledChannels();
  if (enabledChannels.length === 0) {
    console.log(a.yellow(i18n.t("notification:errors.noChannels")));
    return;
  }
  console.log("");
  console.log(a.green(i18n.t("notification:test.sending")));
  try {
    const client = CloudClient.getInstance();
    await client.initialize();
    const results = await client.sendTestNotification();
    console.log("");
    let hasSuccess = false;
    let hasFailure = false;
    for (const result of results) {
      const channelName = i18n.t(`notification:channels.${result.channel}`);
      if (result.success) {
        console.log(a.green(`\u2705 ${channelName}: ${i18n.t("notification:test.success")}`));
        hasSuccess = true;
      } else {
        console.log(a.red(`\u274C ${channelName}: ${result.error || i18n.t("notification:test.failed")}`));
        hasFailure = true;
      }
    }
    console.log("");
    if (hasSuccess) {
      console.log(a.dim(i18n.t("notification:test.checkDevice")));
    }
    if (hasFailure) {
      console.log(a.yellow(i18n.t("notification:test.partialFailure")));
    }
  } catch (error) {
    console.log("");
    console.log(a.red(`\u274C ${i18n.t("notification:errors.sendFailed")}`));
    if (error instanceof Error) {
      console.log(a.dim(error.message));
    }
    console.log("");
    console.log(a.yellow(i18n.t("notification:test.troubleshooting")));
    console.log(a.dim(`  1. ${i18n.t("notification:test.checkConnection")}`));
    console.log(a.dim(`  2. ${i18n.t("notification:test.checkConfig")}`));
    console.log(a.dim(`  3. ${i18n.t("notification:test.checkToken")}`));
  }
  console.log("");
}
async function handleBind(code) {
  console.log("");
  console.log(a.bold.cyan(i18n.t("notification:cloud.bindTitle")));
  console.log("");
  if (isDeviceBound()) {
    console.log(a.yellow(i18n.t("notification:cloud.alreadyBound")));
    console.log("");
    const { confirmRebind } = await inquirer.prompt([{
      type: "confirm",
      name: "confirmRebind",
      message: i18n.t("notification:cloud.confirmRebind"),
      default: false
    }]);
    if (!confirmRebind) {
      return;
    }
    unbindDevice();
  }
  let bindingCode = code;
  if (!bindingCode) {
    console.log(a.dim(i18n.t("notification:cloud.bindInstructions")));
    console.log("");
    const { inputCode } = await inquirer.prompt([{
      type: "input",
      name: "inputCode",
      message: i18n.t("notification:cloud.enterCode"),
      validate: (value) => {
        if (!value || value.trim().length === 0) {
          return i18n.t("notification:cloud.codeRequired");
        }
        if (value.trim().length < 4) {
          return i18n.t("notification:cloud.codeInvalid");
        }
        return true;
      }
    }]);
    bindingCode = inputCode.trim();
  }
  console.log("");
  console.log(a.green(i18n.t("notification:cloud.binding")));
  try {
    const result = await bindDevice(bindingCode);
    if (result.success) {
      console.log("");
      console.log(a.green(`\u2705 ${i18n.t("notification:cloud.bindSuccess")}`));
      console.log("");
      console.log(a.dim(i18n.t("notification:cloud.deviceId", { id: result.data?.deviceId || "N/A" })));
      console.log("");
      const { sendTest } = await inquirer.prompt([{
        type: "confirm",
        name: "sendTest",
        message: i18n.t("notification:cloud.sendTestAfterBind"),
        default: true
      }]);
      if (sendTest) {
        await sendCloudTestNotification();
      }
    } else {
      console.log("");
      console.log(a.red(`\u274C ${i18n.t("notification:cloud.bindFailed")}`));
      console.log(a.dim(result.error || i18n.t("notification:cloud.unknownError")));
      console.log("");
      console.log(a.yellow(i18n.t("notification:cloud.bindTroubleshooting")));
      console.log(a.dim(`  1. ${i18n.t("notification:cloud.checkCode")}`));
      console.log(a.dim(`  2. ${i18n.t("notification:cloud.checkExpiry")}`));
      console.log(a.dim(`  3. ${i18n.t("notification:cloud.checkNetwork")}`));
    }
  } catch (error) {
    console.log("");
    console.log(a.red(`\u274C ${i18n.t("notification:cloud.bindError")}`));
    if (error instanceof Error) {
      console.log(a.dim(error.message));
    }
  }
  console.log("");
}
async function handleUnbind() {
  console.log("");
  if (!isDeviceBound()) {
    console.log(a.yellow(i18n.t("notification:cloud.notBoundYet")));
    console.log("");
    return;
  }
  const { confirmUnbind } = await inquirer.prompt([{
    type: "confirm",
    name: "confirmUnbind",
    message: i18n.t("notification:cloud.confirmUnbind"),
    default: false
  }]);
  if (!confirmUnbind) {
    console.log(a.dim(i18n.t("notification:cloud.unbindCancelled")));
    console.log("");
    return;
  }
  unbindDevice();
  console.log(a.green(`\u2705 ${i18n.t("notification:cloud.unbindSuccess")}`));
  console.log("");
}
async function showCloudStatus() {
  console.log("");
  console.log(a.bold.cyan(i18n.t("notification:cloud.statusTitle")));
  console.log("");
  const status = await getBindingStatus();
  if (!status.bound) {
    console.log(`  ${a.yellow("\u26A0\uFE0F")} ${i18n.t("notification:cloud.notBound")}`);
    console.log("");
    console.log(a.dim(i18n.t("notification:cloud.bindHint")));
    console.log("");
    return;
  }
  console.log(`  ${a.green("\u2705")} ${i18n.t("notification:cloud.bound")}`);
  console.log("");
  if (status.deviceId) {
    console.log(`  ${a.dim(i18n.t("notification:cloud.deviceIdLabel"))} ${status.deviceId}`);
  }
  if (status.deviceInfo) {
    console.log(`  ${a.dim(i18n.t("notification:cloud.deviceNameLabel"))} ${status.deviceInfo.name}`);
    console.log(`  ${a.dim(i18n.t("notification:cloud.platformLabel"))} ${status.deviceInfo.platform}`);
  }
  if (status.lastUsed) {
    const lastUsedDate = new Date(status.lastUsed);
    console.log(`  ${a.dim(i18n.t("notification:cloud.lastUsedLabel"))} ${lastUsedDate.toLocaleString()}`);
  }
  console.log("");
}
async function sendCloudTestNotification() {
  console.log("");
  console.log(a.green(i18n.t("notification:cloud.sendingTest")));
  try {
    const result = await sendNotification({
      title: i18n.t("notification:cloud.testTitle"),
      body: i18n.t("notification:cloud.testBody"),
      type: "success"
    });
    if (result.success) {
      console.log(a.green(`\u2705 ${i18n.t("notification:cloud.testSuccess")}`));
      console.log(a.dim(i18n.t("notification:cloud.checkPhone")));
    } else {
      console.log(a.red(`\u274C ${i18n.t("notification:cloud.testFailed")}`));
      console.log(a.dim(result.error || i18n.t("notification:cloud.unknownError")));
    }
  } catch (error) {
    console.log(a.red(`\u274C ${i18n.t("notification:cloud.testError")}`));
    if (error instanceof Error) {
      console.log(a.dim(error.message));
    }
  }
  console.log("");
}
async function configureLocalNotification() {
  const config = await loadLocalNotificationConfig();
  const shortcutsAvailable = await isShortcutsAvailable();
  console.log("");
  console.log(a.bold.cyan(i18n.t("notification:local.title")));
  console.log(a.dim(i18n.t("notification:local.description")));
  console.log("");
  console.log(a.bold(i18n.t("notification:local.currentStatus")));
  if (shortcutsAvailable) {
    const shortcutsStatus = config.shortcutName ? a.green(i18n.t("notification:status.enabled")) : a.yellow(i18n.t("notification:status.disabled"));
    console.log(`  \u{1F34E} ${i18n.t("notification:local.shortcuts.name")}: ${shortcutsStatus}`);
    if (config.shortcutName) {
      console.log(`     ${a.dim(i18n.t("notification:local.shortcuts.currentShortcut", { name: config.shortcutName }))}`);
    }
  } else {
    console.log(`  \u{1F34E} ${i18n.t("notification:local.shortcuts.name")}: ${a.dim(i18n.t("notification:local.shortcuts.notAvailable"))}`);
  }
  const barkStatus = config.barkUrl ? a.green(i18n.t("notification:status.enabled")) : a.yellow(i18n.t("notification:status.disabled"));
  console.log(`  \u{1F4F1} ${i18n.t("notification:local.bark.name")}: ${barkStatus}`);
  if (config.barkUrl) {
    console.log(`     ${a.dim(i18n.t("notification:local.bark.currentServer", { url: config.barkUrl }))}`);
  }
  console.log("");
  const choices = [];
  if (shortcutsAvailable) {
    choices.push({
      name: config.shortcutName ? `\u{1F34E} ${i18n.t("notification:local.shortcuts.configure")}` : `\u{1F34E} ${i18n.t("notification:local.shortcuts.enable")}`,
      value: "shortcuts"
    });
  }
  choices.push({
    name: config.barkUrl ? `\u{1F4F1} ${i18n.t("notification:local.bark.configure")}` : `\u{1F4F1} ${i18n.t("notification:local.bark.enable")}`,
    value: "bark"
  });
  choices.push(
    { name: `\u{1F9EA} ${i18n.t("notification:local.testLocal")}`, value: "test" },
    { name: `\u2190 ${i18n.t("notification:menu.back")}`, value: "back" }
  );
  const { action } = await inquirer.prompt([{
    type: "list",
    name: "action",
    message: i18n.t("notification:menu.selectAction"),
    choices
  }]);
  if (action === "back") {
    return;
  }
  switch (action) {
    case "shortcuts":
      await configureShortcuts();
      break;
    case "bark":
      await configureBark();
      break;
    case "test":
      await testLocalNotification();
      break;
  }
}
async function configureShortcuts() {
  console.log("");
  console.log(a.bold.cyan(i18n.t("notification:local.shortcuts.title")));
  console.log(a.dim(i18n.t("notification:local.shortcuts.description")));
  console.log("");
  console.log(a.dim(i18n.t("notification:local.shortcuts.scanning")));
  const shortcuts = await listShortcuts();
  if (shortcuts.length === 0) {
    console.log(a.yellow(i18n.t("notification:local.shortcuts.noShortcuts")));
    console.log(a.dim(i18n.t("notification:local.shortcuts.createHint")));
    console.log("");
    return;
  }
  console.log(a.green(i18n.t("notification:local.shortcuts.found", { count: shortcuts.length })));
  console.log("");
  const { shortcutName } = await inquirer.prompt([{
    type: "list",
    name: "shortcutName",
    message: i18n.t("notification:local.shortcuts.selectShortcut"),
    choices: [
      ...shortcuts.map((s) => ({ name: s, value: s })),
      { name: i18n.t("notification:local.shortcuts.enterManually"), value: "__manual__" },
      { name: i18n.t("notification:local.shortcuts.disable"), value: "__disable__" }
    ]
  }]);
  if (shortcutName === "__disable__") {
    await saveLocalNotificationConfig({ shortcutName: "" });
    console.log(a.yellow(`\u23F8\uFE0F ${i18n.t("notification:local.shortcuts.disabled")}`));
    return;
  }
  let finalShortcutName = shortcutName;
  if (shortcutName === "__manual__") {
    const { manualName } = await inquirer.prompt([{
      type: "input",
      name: "manualName",
      message: i18n.t("notification:local.shortcuts.enterName"),
      validate: (value) => !!value.trim() || i18n.t("notification:errors.required")
    }]);
    finalShortcutName = manualName.trim();
  }
  await saveLocalNotificationConfig({ shortcutName: finalShortcutName });
  console.log(a.green(`\u2705 ${i18n.t("notification:local.shortcuts.configured", { name: finalShortcutName })}`));
  const { shouldTest } = await inquirer.prompt([{
    type: "confirm",
    name: "shouldTest",
    message: i18n.t("notification:local.shortcuts.testNow"),
    default: true
  }]);
  if (shouldTest) {
    await testShortcutsNotification(finalShortcutName);
  }
}
async function configureBark() {
  console.log("");
  console.log(a.bold.cyan(i18n.t("notification:local.bark.title")));
  console.log(a.dim(i18n.t("notification:local.bark.description")));
  console.log("");
  const config = await loadLocalNotificationConfig();
  const { action } = await inquirer.prompt([{
    type: "list",
    name: "action",
    message: i18n.t("notification:menu.selectAction"),
    choices: [
      { name: i18n.t("notification:local.bark.configureServer"), value: "configure" },
      { name: i18n.t("notification:local.bark.disable"), value: "disable" },
      { name: `\u2190 ${i18n.t("notification:menu.back")}`, value: "back" }
    ]
  }]);
  if (action === "back") {
    return;
  }
  if (action === "disable") {
    await saveLocalNotificationConfig({ barkUrl: "" });
    console.log(a.yellow(`\u23F8\uFE0F ${i18n.t("notification:local.bark.disabled")}`));
    return;
  }
  const { barkUrl } = await inquirer.prompt([{
    type: "input",
    name: "barkUrl",
    message: i18n.t("notification:local.bark.enterUrl"),
    default: config.barkUrl || "https://api.day.app/your-key",
    validate: (value) => {
      if (!isValidBarkUrl(value)) {
        return i18n.t("notification:local.bark.invalidUrl");
      }
      return true;
    }
  }]);
  await saveLocalNotificationConfig({ barkUrl });
  console.log(a.green(`\u2705 ${i18n.t("notification:local.bark.configured")}`));
  const { shouldTest } = await inquirer.prompt([{
    type: "confirm",
    name: "shouldTest",
    message: i18n.t("notification:local.bark.testNow"),
    default: true
  }]);
  if (shouldTest) {
    await testBarkNotification(barkUrl);
  }
}
async function testLocalNotification() {
  const config = await loadLocalNotificationConfig();
  console.log("");
  console.log(a.green(i18n.t("notification:local.testing")));
  console.log("");
  let hasAnyEnabled = false;
  if (config.shortcutName) {
    hasAnyEnabled = true;
    await testShortcutsNotification(config.shortcutName);
  }
  if (config.barkUrl) {
    hasAnyEnabled = true;
    await testBarkNotification(config.barkUrl);
  }
  if (!hasAnyEnabled) {
    console.log(a.yellow(i18n.t("notification:local.noLocalEnabled")));
    console.log(a.dim(i18n.t("notification:local.configureFirst")));
  }
  console.log("");
}
async function testShortcutsNotification(shortcutName) {
  console.log(a.dim(`${i18n.t("notification:local.shortcuts.testing", { name: shortcutName })}...`));
  try {
    const service = await getLocalNotificationService();
    await service.sendShortcutNotification(shortcutName, {
      title: i18n.t("notification:local.testTitle"),
      body: i18n.t("notification:local.testBody")
    });
    console.log(a.green(`\u2705 ${i18n.t("notification:local.shortcuts.name")}: ${i18n.t("notification:test.success")}`));
  } catch (error) {
    console.log(a.red(`\u274C ${i18n.t("notification:local.shortcuts.name")}: ${error instanceof Error ? error.message : i18n.t("notification:test.failed")}`));
  }
}
async function testBarkNotification(barkUrl) {
  console.log(a.dim(`${i18n.t("notification:local.bark.testing")}...`));
  try {
    const service = await getLocalNotificationService();
    await service.sendBarkNotification(barkUrl, {
      title: i18n.t("notification:local.testTitle"),
      body: i18n.t("notification:local.testBody")
    });
    console.log(a.green(`\u2705 ${i18n.t("notification:local.bark.name")}: ${i18n.t("notification:test.success")}`));
  } catch (error) {
    console.log(a.red(`\u274C ${i18n.t("notification:local.bark.name")}: ${error instanceof Error ? error.message : i18n.t("notification:test.failed")}`));
  }
}

export { notificationCommand };
