import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { logger } from "../../core/monitoring/logger.js";
import { LinearTaskManager } from "../../features/tasks/linear-task-manager.js";
import { LinearAuthManager } from "./auth.js";
import { LinearSyncEngine, DEFAULT_SYNC_CONFIG } from "./sync.js";
import { LinearConfigManager } from "./config.js";
import { IntegrationError, ErrorCode } from "../../core/errors/index.js";
import Database from "better-sqlite3";
import { join } from "path";
import { existsSync } from "fs";
class LinearAutoSyncService {
  config;
  projectRoot;
  configManager;
  syncEngine;
  intervalId;
  isRunning = false;
  lastSyncTime = 0;
  retryCount = 0;
  constructor(projectRoot, config) {
    this.projectRoot = projectRoot;
    this.configManager = new LinearConfigManager(projectRoot);
    const persistedConfig = this.configManager.loadConfig();
    const baseConfig = persistedConfig ? this.configManager.toAutoSyncConfig(persistedConfig) : {
      ...DEFAULT_SYNC_CONFIG,
      enabled: true,
      interval: 5,
      retryAttempts: 3,
      retryDelay: 3e4,
      autoSync: true,
      direction: "bidirectional",
      conflictResolution: "newest_wins",
      quietHours: { start: 22, end: 7 }
    };
    this.config = { ...baseConfig, ...config };
    if (config && Object.keys(config).length > 0) {
      this.configManager.saveConfig(config);
    }
  }
  /**
   * Start the auto-sync service
   */
  async start() {
    if (this.isRunning) {
      logger.warn("Linear auto-sync service is already running");
      return;
    }
    try {
      const authManager = new LinearAuthManager(this.projectRoot);
      if (!authManager.isConfigured()) {
        throw new IntegrationError(
          'Linear integration not configured. Run "stackmemory linear setup" first.',
          ErrorCode.LINEAR_AUTH_FAILED
        );
      }
      const dbPath = join(this.projectRoot, ".stackmemory", "context.db");
      if (!existsSync(dbPath)) {
        throw new IntegrationError(
          'StackMemory not initialized. Run "stackmemory init" first.',
          ErrorCode.LINEAR_SYNC_FAILED
        );
      }
      const db = new Database(dbPath);
      const taskStore = new LinearTaskManager(this.projectRoot, db);
      this.syncEngine = new LinearSyncEngine(
        taskStore,
        authManager,
        this.config
      );
      const token = await authManager.getValidToken();
      if (!token) {
        throw new IntegrationError(
          "Unable to get valid Linear token. Check authentication.",
          ErrorCode.LINEAR_AUTH_FAILED
        );
      }
      this.isRunning = true;
      this.scheduleNextSync();
      logger.info("Linear auto-sync service started", {
        interval: this.config.interval,
        direction: this.config.direction,
        conflictResolution: this.config.conflictResolution
      });
      this.performSync();
    } catch (error) {
      logger.error("Failed to start Linear auto-sync service:", error);
      throw error;
    }
  }
  /**
   * Stop the auto-sync service
   */
  stop() {
    if (this.intervalId) {
      clearTimeout(this.intervalId);
      this.intervalId = void 0;
    }
    this.isRunning = false;
    logger.info("Linear auto-sync service stopped");
  }
  /**
   * Get service status
   */
  getStatus() {
    const nextSyncTime = this.intervalId ? this.lastSyncTime + this.config.interval * 60 * 1e3 : void 0;
    return {
      running: this.isRunning,
      lastSyncTime: this.lastSyncTime,
      nextSyncTime,
      retryCount: this.retryCount,
      config: this.config
    };
  }
  /**
   * Update configuration
   */
  updateConfig(newConfig) {
    this.config = { ...this.config, ...newConfig };
    if (this.isRunning) {
      this.stop();
      this.start();
    }
    logger.info("Linear auto-sync config updated", newConfig);
  }
  /**
   * Force immediate sync
   */
  async forceSync() {
    if (!this.syncEngine) {
      throw new IntegrationError(
        "Sync engine not initialized",
        ErrorCode.LINEAR_SYNC_FAILED
      );
    }
    logger.info("Forcing immediate Linear sync");
    await this.performSync();
  }
  /**
   * Schedule next sync based on configuration
   */
  scheduleNextSync() {
    if (!this.isRunning) return;
    const delay = this.config.interval * 60 * 1e3;
    this.intervalId = setTimeout(() => {
      if (this.isRunning) {
        this.performSync();
      }
    }, delay);
  }
  /**
   * Perform synchronization with error handling and retries
   */
  async performSync() {
    if (!this.syncEngine) {
      logger.error("Sync engine not available");
      return;
    }
    if (this.isInQuietHours()) {
      logger.debug("Skipping sync during quiet hours");
      this.scheduleNextSync();
      return;
    }
    try {
      logger.debug("Starting Linear auto-sync");
      const result = await this.syncEngine.sync();
      if (result.success) {
        this.lastSyncTime = Date.now();
        this.retryCount = 0;
        const hasChanges = result.synced.toLinear > 0 || result.synced.fromLinear > 0 || result.synced.updated > 0;
        if (hasChanges) {
          logger.info("Linear auto-sync completed with changes", {
            toLinear: result.synced.toLinear,
            fromLinear: result.synced.fromLinear,
            updated: result.synced.updated,
            conflicts: result.conflicts.length
          });
        } else {
          logger.debug("Linear auto-sync completed - no changes");
        }
        if (result.conflicts.length > 0) {
          logger.warn("Linear sync conflicts detected", {
            count: result.conflicts.length,
            conflicts: result.conflicts.map((c) => ({
              taskId: c.taskId,
              reason: c.reason
            }))
          });
        }
      } else {
        throw new IntegrationError(
          `Sync failed: ${result.errors.join(", ")}`,
          ErrorCode.LINEAR_SYNC_FAILED
        );
      }
    } catch (error) {
      logger.error("Linear auto-sync failed:", error);
      this.retryCount++;
      if (this.retryCount <= this.config.retryAttempts) {
        logger.info(
          `Retrying Linear sync in ${this.config.retryDelay / 1e3}s (attempt ${this.retryCount}/${this.config.retryAttempts})`
        );
        setTimeout(() => {
          if (this.isRunning) {
            this.performSync();
          }
        }, this.config.retryDelay);
        return;
      } else {
        logger.error(
          `Linear auto-sync failed after ${this.config.retryAttempts} attempts, skipping until next interval`
        );
        this.retryCount = 0;
      }
    }
    this.scheduleNextSync();
  }
  /**
   * Check if current time is within quiet hours
   */
  isInQuietHours() {
    if (!this.config.quietHours) return false;
    const now = /* @__PURE__ */ new Date();
    const currentHour = now.getHours();
    const { start, end } = this.config.quietHours;
    if (start < end) {
      return currentHour >= start || currentHour < end;
    } else {
      return currentHour >= start && currentHour < end;
    }
  }
}
let autoSyncService = null;
function initializeAutoSync(projectRoot, config) {
  if (autoSyncService) {
    autoSyncService.stop();
  }
  autoSyncService = new LinearAutoSyncService(projectRoot, config);
  return autoSyncService;
}
function getAutoSyncService() {
  return autoSyncService;
}
function stopAutoSync() {
  if (autoSyncService) {
    autoSyncService.stop();
    autoSyncService = null;
  }
}
export {
  LinearAutoSyncService,
  getAutoSyncService,
  initializeAutoSync,
  stopAutoSync
};
//# sourceMappingURL=auto-sync.js.map
