import { LinearClient } from "./client.js";
import { ContextService } from "../../services/context-service.js";
import { ConfigService } from "../../services/config-service.js";
import { logger } from "../../core/monitoring/logger.js";
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 LinearSyncService {
  linearClient;
  contextService;
  configService;
  // Using singleton logger from monitoring
  constructor() {
    this.configService = new ConfigService();
    this.contextService = new ContextService();
    const apiKey = process.env["LINEAR_API_KEY"];
    if (!apiKey) {
      throw new Error("LINEAR_API_KEY environment variable not set");
    }
    this.linearClient = new LinearClient({ apiKey });
  }
  async syncAllIssues() {
    const result = {
      created: 0,
      updated: 0,
      deleted: 0,
      conflicts: 0,
      errors: []
    };
    try {
      const config = await this.configService.getConfig();
      const teamId = config.integrations?.linear?.teamId;
      if (!teamId) {
        throw new Error("Linear team ID not configured");
      }
      const issues = await this.linearClient.getIssues({ teamId });
      for (const issue of issues) {
        try {
          const synced = await this.syncIssueToLocal(issue);
          if (synced === "created") result.created++;
          else if (synced === "updated") result.updated++;
        } catch (error) {
          const message = error instanceof Error ? error.message : String(error);
          result.errors.push(`Failed to sync ${issue.identifier}: ${message}`);
        }
      }
      logger.info(
        `Sync complete: ${result.created} created, ${result.updated} updated`
      );
    } catch (error) {
      logger.error("Sync failed:", error);
      const message = error instanceof Error ? error.message : String(error);
      result.errors.push(message);
    }
    return result;
  }
  async syncIssueToLocal(issue) {
    try {
      const task = this.convertIssueToTask(issue);
      const existingTask = await this.contextService.getTaskByExternalId(
        issue.id
      );
      if (existingTask) {
        if (this.hasChanges(existingTask, task)) {
          await this.contextService.updateTask(existingTask.id, task);
          logger.debug(`Updated task: ${issue.identifier}`);
          return "updated";
        }
        return "skipped";
      } else {
        await this.contextService.createTask(task);
        logger.debug(`Created task: ${issue.identifier}`);
        return "created";
      }
    } catch (error) {
      logger.error(`Failed to sync issue ${issue.identifier}:`, error);
      throw error;
    }
  }
  async syncLocalToLinear(taskId) {
    try {
      const task = await this.contextService.getTask(taskId);
      if (!task) {
        throw new Error(`Task ${taskId} not found`);
      }
      if (task.externalId) {
        const updateData = this.convertTaskToUpdateData(task);
        const updated = await this.linearClient.updateIssue(
          task.externalId,
          updateData
        );
        logger.debug(`Updated Linear issue: ${updated.identifier}`);
        return updated;
      } else {
        const config = await this.configService.getConfig();
        const teamId = config.integrations?.linear?.teamId;
        if (!teamId) {
          throw new Error("Linear team ID not configured");
        }
        const createData = {
          title: task.title,
          description: task.description,
          teamId,
          priority: this.mapTaskPriorityToLinearPriority(task.priority)
        };
        const created = await this.linearClient.createIssue(createData);
        await this.contextService.updateTask(taskId, {
          externalId: created.id
        });
        logger.debug(`Created Linear issue: ${created.identifier}`);
        return created;
      }
    } catch (error) {
      logger.error(`Failed to sync task ${taskId} to Linear:`, error);
      throw error;
    }
  }
  async removeLocalIssue(identifier) {
    try {
      const tasks = await this.contextService.getAllTasks();
      const task = tasks.find((t) => t.externalIdentifier === identifier);
      if (task) {
        await this.contextService.deleteTask(task.id);
        logger.debug(`Removed local task: ${identifier}`);
      }
    } catch (error) {
      logger.error(`Failed to remove task ${identifier}:`, error);
      throw error;
    }
  }
  convertIssueToTask(issue) {
    return {
      title: issue.title,
      description: issue.description || "",
      status: this.mapLinearStateToTaskStatus(issue.state.type),
      priority: this.mapLinearPriorityToTaskPriority(issue.priority),
      externalId: issue.id,
      externalIdentifier: issue.identifier,
      externalUrl: issue.url,
      tags: issue.labels?.map((l) => l.name) || [],
      metadata: {
        linear: {
          stateId: issue.state.id,
          stateName: issue.state.name,
          assigneeId: issue.assignee?.id,
          assigneeName: issue.assignee?.name
        }
      },
      updatedAt: new Date(issue.updatedAt)
    };
  }
  convertTaskToUpdateData(task) {
    return {
      title: task.title,
      description: task.description,
      priority: this.mapTaskPriorityToLinearPriority(task.priority),
      stateId: task.metadata?.linear?.stateId
    };
  }
  mapLinearStateToTaskStatus(state) {
    switch (state.toLowerCase()) {
      case "backlog":
      case "triage":
        return "todo";
      case "unstarted":
      case "todo":
        return "todo";
      case "started":
      case "in_progress":
        return "in_progress";
      case "completed":
      case "done":
        return "done";
      case "canceled":
      case "cancelled":
        return "cancelled";
      default:
        return "todo";
    }
  }
  mapTaskPriorityToLinearPriority(priority) {
    switch (priority) {
      case "urgent":
        return 1;
      case "high":
        return 2;
      case "medium":
        return 3;
      case "low":
        return 4;
      default:
        return 0;
    }
  }
  mapLinearPriorityToTaskPriority(priority) {
    switch (priority) {
      case 1:
        return "urgent";
      case 2:
        return "high";
      case 3:
        return "medium";
      case 4:
        return "low";
      default:
        return void 0;
    }
  }
  hasChanges(existing, updated) {
    return existing.title !== updated.title || existing.description !== updated.description || existing.status !== updated.status || existing.priority !== updated.priority || JSON.stringify(existing.tags) !== JSON.stringify(updated.tags);
  }
}
export {
  LinearSyncService
};
//# sourceMappingURL=sync-service.js.map
