import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { LinearRestClient } from "./rest-client.js";
import { logger } from "../../core/monitoring/logger.js";
import { IntegrationError, ErrorCode } from "../../core/errors/index.js";
import chalk from "chalk";
class LinearMigrator {
  sourceClient;
  targetClient;
  config;
  constructor(config) {
    this.config = config;
    this.sourceClient = new LinearRestClient(config.sourceApiKey);
    this.targetClient = new LinearRestClient(config.targetApiKey);
  }
  /**
   * Test connections to both workspaces
   */
  async testConnections() {
    const result = {
      source: { success: false },
      target: { success: false }
    };
    try {
      const sourceViewer = await this.sourceClient.getViewer();
      const sourceTeam = await this.sourceClient.getTeam();
      result.source = {
        success: true,
        info: {
          user: sourceViewer,
          team: sourceTeam
        }
      };
    } catch (error) {
      result.source = {
        success: false,
        error: error.message
      };
    }
    try {
      const targetViewer = await this.targetClient.getViewer();
      const targetTeam = await this.targetClient.getTeam();
      result.target = {
        success: true,
        info: {
          user: targetViewer,
          team: targetTeam
        }
      };
    } catch (error) {
      result.target = {
        success: false,
        error: error.message
      };
    }
    return result;
  }
  /**
   * Migrate all tasks from source to target workspace
   */
  async migrate() {
    const result = {
      totalTasks: 0,
      exported: 0,
      imported: 0,
      failed: 0,
      deleted: 0,
      deleteFailed: 0,
      errors: [],
      taskMappings: []
    };
    try {
      console.log(chalk.yellow("Starting Linear workspace migration..."));
      const sourceTasks = await this.sourceClient.getAllTasks(true);
      result.totalTasks = sourceTasks.length;
      console.log(
        chalk.cyan(`Found ${sourceTasks.length} tasks in source workspace`)
      );
      let tasksToMigrate = sourceTasks;
      if (this.config.taskPrefix) {
        tasksToMigrate = sourceTasks.filter(
          (task) => task.identifier.startsWith(this.config.taskPrefix)
        );
        console.log(
          chalk.cyan(
            `Filtered to ${tasksToMigrate.length} tasks with prefix "${this.config.taskPrefix}"`
          )
        );
      }
      if (this.config.includeStates?.length) {
        tasksToMigrate = tasksToMigrate.filter(
          (task) => this.config.includeStates.includes(task.state.type)
        );
        const stateStr = this.config.includeStates.join(", ");
        console.log(
          chalk.cyan(
            `Further filtered to ${tasksToMigrate.length} tasks matching states: ${stateStr}`
          )
        );
      }
      result.exported = tasksToMigrate.length;
      if (this.config.dryRun) {
        console.log(chalk.yellow("DRY RUN - No tasks will be created"));
        tasksToMigrate.forEach((task) => {
          result.taskMappings.push({
            sourceId: task.id,
            sourceIdentifier: task.identifier,
            targetId: "DRY_RUN",
            targetIdentifier: "DRY_RUN"
          });
        });
        result.imported = tasksToMigrate.length;
        return result;
      }
      const targetTeam = await this.targetClient.getTeam();
      console.log(
        chalk.cyan(`Target team: ${targetTeam.name} (${targetTeam.key})`)
      );
      const batchSize = this.config.batchSize || 5;
      const delayMs = this.config.delayMs || 2e3;
      for (let i = 0; i < tasksToMigrate.length; i += batchSize) {
        const batch = tasksToMigrate.slice(i, i + batchSize);
        console.log(
          chalk.yellow(
            `Processing batch ${Math.floor(i / batchSize) + 1}/${Math.ceil(tasksToMigrate.length / batchSize)}`
          )
        );
        for (const task of batch) {
          try {
            const newTask = await this.migrateTask(task, targetTeam.id);
            const mapping = {
              sourceId: task.id,
              sourceIdentifier: task.identifier,
              targetId: newTask.id,
              targetIdentifier: newTask.identifier,
              deleted: false
            };
            result.imported++;
            console.log(
              chalk.green(
                `${task.identifier} \u2192 ${newTask.identifier}: ${task.title}`
              )
            );
            if (this.config.deleteFromSource) {
              try {
                await this.deleteTask(task.id);
                mapping.deleted = true;
                result.deleted++;
                console.log(
                  chalk.gray(`Deleted ${task.identifier} from source`)
                );
              } catch (deleteError) {
                result.deleteFailed++;
                result.errors.push(
                  `Delete failed for ${task.identifier}: ${deleteError.message}`
                );
                console.log(
                  chalk.yellow(
                    `Failed to delete ${task.identifier} from source: ${deleteError.message}`
                  )
                );
              }
            }
            result.taskMappings.push(mapping);
          } catch (error) {
            const errorMsg = error.message;
            result.errors.push(`${task.identifier}: ${errorMsg}`);
            result.taskMappings.push({
              sourceId: task.id,
              sourceIdentifier: task.identifier,
              error: errorMsg
            });
            result.failed++;
            console.log(chalk.red(`${task.identifier}: ${errorMsg}`));
          }
        }
        if (i + batchSize < tasksToMigrate.length) {
          console.log(chalk.gray(`Waiting ${delayMs}ms before next batch...`));
          await this.delay(delayMs);
        }
      }
    } catch (error) {
      result.errors.push(`Migration failed: ${error.message}`);
      logger.error("Migration failed:", error);
    }
    return result;
  }
  /**
   * Migrate a single task
   */
  async migrateTask(sourceTask, targetTeamId) {
    const stateMapping = {
      backlog: "backlog",
      unstarted: "unstarted",
      started: "started",
      completed: "completed",
      canceled: "canceled"
    };
    const createTaskQuery = `
      mutation CreateIssue($input: IssueCreateInput!) {
        issueCreate(input: $input) {
          success
          issue {
            id
            identifier
            title
            description
            state {
              id
              name
              type
            }
            priority
            createdAt
            updatedAt
            url
          }
        }
      }
    `;
    const taskInput = {
      title: `[MIGRATED] ${sourceTask.title}`,
      description: this.formatMigratedDescription(sourceTask),
      teamId: targetTeamId,
      priority: this.mapPriority(sourceTask.priority)
    };
    const response = await this.targetClient.makeRequest(createTaskQuery, { input: taskInput });
    if (!response.data?.issueCreate?.success) {
      throw new IntegrationError(
        "Failed to create task in target workspace",
        ErrorCode.LINEAR_SYNC_FAILED,
        { sourceTaskId: sourceTask.id, sourceIdentifier: sourceTask.identifier }
      );
    }
    return response.data.issueCreate.issue;
  }
  /**
   * Format description with migration context
   */
  formatMigratedDescription(sourceTask) {
    let description = sourceTask.description || "";
    description += `

---
**Migration Info:**
`;
    description += `- Original ID: ${sourceTask.identifier}
`;
    description += `- Migrated: ${(/* @__PURE__ */ new Date()).toISOString()}
`;
    description += `- Original State: ${sourceTask.state.name}
`;
    if (sourceTask.assignee) {
      description += `- Original Assignee: ${sourceTask.assignee.name}
`;
    }
    if (sourceTask.estimate) {
      description += `- Original Estimate: ${sourceTask.estimate} points
`;
    }
    return description;
  }
  /**
   * Map priority values
   */
  mapPriority(priority) {
    return priority || 0;
  }
  /**
   * Delete a task from the source workspace
   */
  async deleteTask(taskId) {
    const deleteQuery = `
      mutation DeleteIssue($id: String!) {
        issueDelete(id: $id) {
          success
        }
      }
    `;
    const response = await this.sourceClient.makeRequest(deleteQuery, {
      id: taskId
    });
    if (!response.data?.issueDelete?.success) {
      throw new IntegrationError(
        "Failed to delete task from source workspace",
        ErrorCode.LINEAR_SYNC_FAILED,
        { taskId }
      );
    }
  }
  /**
   * Delay helper
   */
  delay(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }
}
async function runMigration(config) {
  const migrator = new LinearMigrator(config);
  console.log(chalk.blue("Testing connections..."));
  const connectionTest = await migrator.testConnections();
  if (!connectionTest.source.success) {
    console.error(
      chalk.red(`Source connection failed: ${connectionTest.source.error}`)
    );
    return;
  }
  if (!connectionTest.target.success) {
    console.error(
      chalk.red(`Target connection failed: ${connectionTest.target.error}`)
    );
    return;
  }
  console.log(chalk.green("Both connections successful"));
  console.log(
    chalk.cyan(
      `Source: ${connectionTest.source.info.user.name} @ ${connectionTest.source.info.team.name}`
    )
  );
  console.log(
    chalk.cyan(
      `Target: ${connectionTest.target.info.user.name} @ ${connectionTest.target.info.team.name}`
    )
  );
  const result = await migrator.migrate();
  console.log(chalk.blue("\nMigration Summary:"));
  console.log(`  Total tasks: ${result.totalTasks}`);
  console.log(`  Exported: ${result.exported}`);
  console.log(chalk.green(`  Imported: ${result.imported}`));
  console.log(chalk.red(`  Failed: ${result.failed}`));
  if (config.deleteFromSource) {
    console.log(chalk.gray(`  Deleted: ${result.deleted}`));
    if (result.deleteFailed > 0) {
      console.log(chalk.yellow(`  Delete failed: ${result.deleteFailed}`));
    }
  }
  if (result.errors.length > 0) {
    console.log(chalk.red("\nErrors:"));
    result.errors.forEach((error) => console.log(chalk.red(`  - ${error}`)));
  }
  if (result.imported > 0) {
    console.log(
      chalk.green(
        `
Migration completed! ${result.imported} tasks migrated successfully.`
      )
    );
    if (config.deleteFromSource && result.deleted > 0) {
      console.log(
        chalk.gray(`   ${result.deleted} tasks deleted from source workspace.`)
      );
    }
  }
}
export {
  LinearMigrator,
  runMigration
};
//# sourceMappingURL=migration.js.map
