import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { MetricsQueries } from "../queries/metrics-queries.js";
import { LinearClient } from "../../../integrations/linear/client.js";
import { LinearTaskManager } from "../../tasks/linear-task-manager.js";
import Database from "better-sqlite3";
import path from "path";
import fs from "fs";
import os from "os";
function getEnv(key, defaultValue) {
  const value = process.env[key];
  if (value === void 0) {
    if (defaultValue !== void 0) return defaultValue;
    throw new Error(`Environment variable ${key} is required`);
  }
  return value;
}
function getOptionalEnv(key) {
  return process.env[key];
}
class AnalyticsService {
  metricsQueries;
  linearClient;
  taskStore;
  dbPath;
  projectPath;
  updateCallbacks = /* @__PURE__ */ new Set();
  constructor(projectPath) {
    this.projectPath = projectPath || process.cwd();
    this.dbPath = path.join(this.projectPath, ".stackmemory", "analytics.db");
    this.ensureDirectoryExists();
    this.metricsQueries = new MetricsQueries(this.dbPath);
    this.initializeTaskStore();
    if (process.env["LINEAR_API_KEY"]) {
      this.initializeLinearIntegration();
    }
  }
  initializeTaskStore() {
    try {
      const contextDbPath = path.join(
        this.projectPath,
        ".stackmemory",
        "context.db"
      );
      if (fs.existsSync(contextDbPath)) {
        const db = new Database(contextDbPath);
        this.taskStore = new LinearTaskManager(this.projectPath, db);
      }
    } catch (error) {
      console.error("Failed to initialize task store:", error);
    }
  }
  ensureDirectoryExists() {
    const dir = path.dirname(this.dbPath);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
  }
  async initializeLinearIntegration() {
    try {
      const configPath = path.join(
        os.homedir(),
        ".stackmemory",
        "linear-config.json"
      );
      if (fs.existsSync(configPath)) {
        const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
        this.linearClient = new LinearClient(config);
        await this.syncLinearTasks();
      }
    } catch (error) {
      console.error("Failed to initialize Linear integration:", error);
    }
  }
  async syncLinearTasks() {
    await this.syncFromTaskStore();
    if (this.linearClient) {
      try {
        const issues = await this.linearClient.getIssues({ limit: 100 });
        for (const issue of issues) {
          const task = {
            id: issue.id,
            title: issue.title,
            state: this.mapLinearState(issue.state.type),
            createdAt: new Date(issue.createdAt),
            completedAt: issue.state.type === "completed" ? new Date(issue.updatedAt) : void 0,
            estimatedEffort: issue.estimate ? issue.estimate * 60 : void 0,
            assigneeId: issue.assignee?.id,
            priority: this.mapLinearPriority(issue.priority),
            labels: Array.isArray(issue.labels) ? issue.labels.map((l) => l.name) : issue.labels?.nodes?.map((l) => l.name) || [],
            blockingIssues: []
          };
          this.metricsQueries.upsertTask(task);
        }
      } catch (error) {
        console.error("Failed to sync from Linear API:", error);
      }
    }
    await this.notifyUpdate();
  }
  async syncFromTaskStore() {
    if (!this.taskStore) return 0;
    try {
      const allTasks = this.getAllTasksFromStore();
      let synced = 0;
      for (const task of allTasks) {
        const analyticsTask = {
          id: task.id,
          title: task.title,
          state: this.mapTaskStatus(task.status),
          createdAt: new Date(task.created_at * 1e3),
          completedAt: task.completed_at ? new Date(task.completed_at * 1e3) : void 0,
          estimatedEffort: task.estimated_effort,
          actualEffort: task.actual_effort,
          assigneeId: task.assignee,
          priority: task.priority,
          labels: task.tags || [],
          blockingIssues: task.depends_on || []
        };
        this.metricsQueries.upsertTask(analyticsTask);
        synced++;
      }
      return synced;
    } catch (error) {
      console.error("Failed to sync from task store:", error);
      return 0;
    }
  }
  getAllTasksFromStore() {
    if (!this.taskStore) return [];
    try {
      const contextDbPath = path.join(
        this.projectPath,
        ".stackmemory",
        "context.db"
      );
      const db = new Database(contextDbPath);
      const rows = db.prepare(
        `
        SELECT * FROM task_cache 
        ORDER BY created_at DESC
      `
      ).all();
      db.close();
      return rows.map((row) => ({
        id: row.id,
        title: row.title,
        description: row.description,
        status: row.status,
        priority: row.priority,
        created_at: row.created_at,
        completed_at: row.completed_at,
        estimated_effort: row.estimated_effort,
        actual_effort: row.actual_effort,
        assignee: row.assignee,
        tags: JSON.parse(row.tags || "[]"),
        depends_on: JSON.parse(row.depends_on || "[]")
      }));
    } catch (error) {
      console.error("Failed to get all tasks:", error);
      return [];
    }
  }
  mapTaskStatus(status) {
    const statusMap = {
      pending: "todo",
      in_progress: "in_progress",
      completed: "completed",
      blocked: "blocked",
      cancelled: "blocked"
    };
    return statusMap[status] || "todo";
  }
  mapLinearState(linearState) {
    const stateMap = {
      backlog: "todo",
      unstarted: "todo",
      started: "in_progress",
      completed: "completed",
      done: "completed",
      canceled: "blocked"
    };
    return stateMap[linearState.toLowerCase()] || "todo";
  }
  mapLinearPriority(priority) {
    if (priority === 1) return "urgent";
    if (priority === 2) return "high";
    if (priority === 3) return "medium";
    return "low";
  }
  async getDashboardState(query = {}) {
    const timeRange = query.timeRange || this.getDefaultTimeRange();
    const metrics = this.metricsQueries.getTaskMetrics({
      ...query,
      timeRange
    });
    const recentTasks = this.metricsQueries.getRecentTasks({
      ...query,
      limit: 20
    });
    const teamMetrics = await this.getTeamMetrics(query);
    return {
      metrics,
      teamMetrics,
      recentTasks,
      timeRange,
      teamFilter: query.userIds || [],
      isLive: this.updateCallbacks.size > 0,
      lastUpdated: /* @__PURE__ */ new Date()
    };
  }
  async getTeamMetrics(query) {
    const uniqueUserIds = /* @__PURE__ */ new Set();
    const tasks = this.metricsQueries.getRecentTasks({ limit: 1e3 });
    tasks.forEach((task) => {
      if (task.assigneeId) {
        uniqueUserIds.add(task.assigneeId);
      }
    });
    const teamMetrics = [];
    const totalCompleted = tasks.filter((t) => t.state === "completed").length;
    for (const userId of uniqueUserIds) {
      const userQuery = { ...query, userIds: [userId] };
      const individualMetrics = this.metricsQueries.getTaskMetrics(userQuery);
      teamMetrics.push({
        userId,
        userName: await this.getUserName(userId),
        individualMetrics,
        contributionPercentage: totalCompleted > 0 ? individualMetrics.completedTasks / totalCompleted * 100 : 0,
        lastActive: /* @__PURE__ */ new Date()
      });
    }
    return teamMetrics.sort(
      (a, b) => b.contributionPercentage - a.contributionPercentage
    );
  }
  async getUserName(userId) {
    return userId;
  }
  getDefaultTimeRange() {
    const end = /* @__PURE__ */ new Date();
    const start = /* @__PURE__ */ new Date();
    start.setDate(start.getDate() - 7);
    return {
      start,
      end,
      preset: "7d"
    };
  }
  subscribeToUpdates(callback) {
    this.updateCallbacks.add(callback);
    return () => {
      this.updateCallbacks.delete(callback);
    };
  }
  async notifyUpdate() {
    const state = await this.getDashboardState();
    this.updateCallbacks.forEach((callback) => callback(state));
  }
  async addTask(task) {
    this.metricsQueries.upsertTask(task);
    await this.notifyUpdate();
  }
  async updateTask(taskId, updates) {
    const tasks = this.metricsQueries.getRecentTasks({ limit: 1 });
    const existingTask = tasks.find((t) => t.id === taskId);
    if (existingTask) {
      const updatedTask = { ...existingTask, ...updates };
      this.metricsQueries.upsertTask(updatedTask);
      await this.notifyUpdate();
    }
  }
  close() {
    this.metricsQueries.close();
  }
}
export {
  AnalyticsService
};
//# sourceMappingURL=analytics-service.js.map
