import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import express from "express";
import { URL } from "url";
import { logger } from "../../core/monitoring/logger.js";
import { LinearAuthManager } from "./auth.js";
import chalk from "chalk";
import { IntegrationError, ErrorCode } from "../../core/errors/index.js";
function getEnv(key, defaultValue) {
  const value = process.env[key];
  if (value === void 0) {
    if (defaultValue !== void 0) return defaultValue;
    throw new IntegrationError(
      `Environment variable ${key} is required`,
      ErrorCode.LINEAR_AUTH_FAILED
    );
  }
  return value;
}
function getOptionalEnv(key) {
  return process.env[key];
}
class LinearOAuthServer {
  app;
  server = null;
  authManager;
  config;
  pendingCodeVerifiers = /* @__PURE__ */ new Map();
  authCompleteCallbacks = /* @__PURE__ */ new Map();
  constructor(projectRoot, config) {
    this.app = express();
    this.authManager = new LinearAuthManager(projectRoot);
    this.config = {
      port: config?.port || 3456,
      host: config?.host || "localhost",
      redirectPath: config?.redirectPath || "/auth/linear/callback",
      autoShutdown: config?.autoShutdown !== false,
      shutdownDelay: config?.shutdownDelay || 5e3
    };
    this.setupRoutes();
  }
  setupRoutes() {
    this.app.get("/health", (req, res) => {
      res.json({
        status: "healthy",
        service: "linear-oauth",
        timestamp: (/* @__PURE__ */ new Date()).toISOString()
      });
    });
    this.app.get(this.config.redirectPath, async (req, res) => {
      const { code, state, error, error_description } = req.query;
      if (error) {
        logger.error(`OAuth error: ${error} - ${error_description}`);
        res.send(
          this.generateErrorPage(
            "Authorization Failed",
            `${error}: ${error_description || "An error occurred during authorization"}`
          )
        );
        if (state && this.authCompleteCallbacks.has(state)) {
          this.authCompleteCallbacks.get(state)(false);
          this.authCompleteCallbacks.delete(state);
        }
        this.scheduleShutdown();
        return;
      }
      if (!code) {
        res.send(
          this.generateErrorPage(
            "Missing Authorization Code",
            "No authorization code was provided in the callback"
          )
        );
        this.scheduleShutdown();
        return;
      }
      try {
        const codeVerifier = state ? this.pendingCodeVerifiers.get(state) : process.env["_LINEAR_CODE_VERIFIER"];
        if (!codeVerifier) {
          throw new IntegrationError(
            "Code verifier not found. Please restart the authorization process.",
            ErrorCode.LINEAR_AUTH_FAILED
          );
        }
        logger.info("Exchanging authorization code for tokens...");
        await this.authManager.exchangeCodeForToken(
          code,
          codeVerifier
        );
        if (state) {
          this.pendingCodeVerifiers.delete(state);
        }
        delete process.env["_LINEAR_CODE_VERIFIER"];
        const testSuccess = await this.testConnection();
        if (testSuccess) {
          res.send(this.generateSuccessPage());
          logger.info("Linear OAuth authentication completed successfully!");
        } else {
          throw new IntegrationError(
            "Failed to verify Linear connection",
            ErrorCode.LINEAR_AUTH_FAILED
          );
        }
        if (state && this.authCompleteCallbacks.has(state)) {
          this.authCompleteCallbacks.get(state)(true);
          this.authCompleteCallbacks.delete(state);
        }
        this.scheduleShutdown();
      } catch (error2) {
        logger.error("Failed to complete OAuth flow:", error2);
        res.send(
          this.generateErrorPage(
            "Authentication Failed",
            error2.message
          )
        );
        if (state && this.authCompleteCallbacks.has(state)) {
          this.authCompleteCallbacks.get(state)(false);
          this.authCompleteCallbacks.delete(state);
        }
        this.scheduleShutdown();
      }
    });
    this.app.get("/auth/linear/start", (req, res) => {
      try {
        const config = this.authManager.loadConfig();
        if (!config) {
          res.status(400).send(
            this.generateErrorPage(
              "Configuration Missing",
              "Linear OAuth configuration not found. Please configure your client ID and secret."
            )
          );
          return;
        }
        const state = this.generateState();
        const { url, codeVerifier } = this.authManager.generateAuthUrl(state);
        this.pendingCodeVerifiers.set(state, codeVerifier);
        res.redirect(url);
      } catch (error) {
        logger.error("Failed to start OAuth flow:", error);
        res.status(500).send(
          this.generateErrorPage(
            "OAuth Start Failed",
            error.message
          )
        );
      }
    });
    this.app.use((req, res) => {
      res.status(404).json({ error: "Not found" });
    });
  }
  generateState() {
    return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
  }
  generateSuccessPage() {
    return `
      <!DOCTYPE html>
      <html>
      <head>
        <title>Linear Authorization Successful</title>
        <style>
          body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
          }
          .container {
            background: white;
            padding: 3rem;
            border-radius: 12px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            text-align: center;
            max-width: 400px;
          }
          h1 {
            color: #2d3748;
            margin-bottom: 1rem;
          }
          .success-icon {
            font-size: 4rem;
            margin-bottom: 1rem;
          }
          p {
            color: #4a5568;
            line-height: 1.6;
            margin: 1rem 0;
          }
          .close-note {
            color: #718096;
            font-size: 0.875rem;
            margin-top: 2rem;
          }
          code {
            background: #f7fafc;
            padding: 0.25rem 0.5rem;
            border-radius: 4px;
            font-family: 'Courier New', monospace;
          }
        </style>
      </head>
      <body>
        <div class="container">
          <div class="success-icon">\u2705</div>
          <h1>Authorization Successful!</h1>
          <p>Your Linear account has been successfully connected to StackMemory.</p>
          <p>You can now use Linear integration features:</p>
          <p><code>stackmemory linear sync</code></p>
          <p><code>stackmemory linear create</code></p>
          <p class="close-note">You can safely close this window and return to your terminal.</p>
        </div>
      </body>
      </html>
    `;
  }
  generateErrorPage(title, message) {
    return `
      <!DOCTYPE html>
      <html>
      <head>
        <title>${title}</title>
        <style>
          body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
          }
          .container {
            background: white;
            padding: 3rem;
            border-radius: 12px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            text-align: center;
            max-width: 400px;
          }
          h1 {
            color: #e53e3e;
            margin-bottom: 1rem;
          }
          .error-icon {
            font-size: 4rem;
            margin-bottom: 1rem;
          }
          p {
            color: #4a5568;
            line-height: 1.6;
            margin: 1rem 0;
          }
          .error-message {
            background: #fff5f5;
            border: 1px solid #fed7d7;
            color: #742a2a;
            padding: 1rem;
            border-radius: 6px;
            margin-top: 1rem;
            font-size: 0.875rem;
          }
          .retry-note {
            color: #718096;
            font-size: 0.875rem;
            margin-top: 2rem;
          }
          code {
            background: #f7fafc;
            padding: 0.25rem 0.5rem;
            border-radius: 4px;
            font-family: 'Courier New', monospace;
          }
        </style>
      </head>
      <body>
        <div class="container">
          <div class="error-icon">\u274C</div>
          <h1>${title}</h1>
          <p>Unable to complete Linear authorization.</p>
          <div class="error-message">${message}</div>
          <p class="retry-note">
            Please try again with:<br>
            <code>stackmemory linear auth</code>
          </p>
        </div>
      </body>
      </html>
    `;
  }
  async testConnection() {
    try {
      const token = await this.authManager.getValidToken();
      const response = await fetch("https://api.linear.app/graphql", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          query: "query { viewer { id name email } }"
        })
      });
      if (response.ok) {
        const result = await response.json();
        if (result.data?.viewer) {
          logger.info(
            `Connected to Linear as: ${result.data.viewer.name} (${result.data.viewer.email})`
          );
          return true;
        }
      }
      return false;
    } catch (error) {
      logger.error("Linear connection test failed:", error);
      return false;
    }
  }
  scheduleShutdown() {
    if (this.config.autoShutdown && this.server) {
      setTimeout(() => {
        logger.info("Auto-shutting down OAuth server...");
        this.stop();
      }, this.config.shutdownDelay);
    }
  }
  async start() {
    return new Promise((resolve, reject) => {
      try {
        const config = this.authManager.loadConfig();
        if (!config) {
          const setupUrl = `http://${this.config.host}:${this.config.port}/auth/linear/start`;
          this.server = this.app.listen(
            this.config.port,
            this.config.host,
            () => {
              console.log(
                chalk.green("\u2713") + chalk.bold(" Linear OAuth Server Started")
              );
              console.log(chalk.cyan("  Authorization URL: ") + setupUrl);
              console.log(
                chalk.cyan("  Callback URL: ") + `http://${this.config.host}:${this.config.port}${this.config.redirectPath}`
              );
              console.log("");
              console.log(chalk.yellow("  \u26A0 Configuration Required:"));
              console.log(
                "  1. Create a Linear OAuth app at: https://linear.app/settings/api"
              );
              console.log(
                `  2. Set redirect URI to: http://${this.config.host}:${this.config.port}${this.config.redirectPath}`
              );
              console.log("  3. Set environment variables:");
              console.log('     export LINEAR_CLIENT_ID="your_client_id"');
              console.log(
                '     export LINEAR_CLIENT_SECRET="your_client_secret"'
              );
              console.log("  4. Restart the auth process");
              resolve({ url: setupUrl });
            }
          );
          return;
        }
        const state = this.generateState();
        const { url, codeVerifier } = this.authManager.generateAuthUrl(state);
        this.pendingCodeVerifiers.set(state, codeVerifier);
        this.server = this.app.listen(
          this.config.port,
          this.config.host,
          () => {
            console.log(
              chalk.green("\u2713") + chalk.bold(" Linear OAuth Server Started")
            );
            console.log(chalk.cyan("  Open this URL in your browser:"));
            console.log("  " + chalk.underline(url));
            console.log("");
            console.log(
              chalk.gray(
                "  The server will automatically shut down after authorization completes."
              )
            );
            resolve({ url, codeVerifier });
          }
        );
        this.authCompleteCallbacks.set(state, (success) => {
          if (success) {
            console.log(
              chalk.green("\n\u2713 Linear authorization completed successfully!")
            );
          } else {
            console.log(chalk.red("\n\u2717 Linear authorization failed"));
          }
        });
      } catch (error) {
        reject(error);
      }
    });
  }
  async stop() {
    return new Promise((resolve) => {
      if (this.server) {
        this.server.close(() => {
          logger.info("OAuth server stopped");
          this.server = null;
          resolve();
        });
      } else {
        resolve();
      }
    });
  }
  async waitForAuth(state, timeout = 3e5) {
    return new Promise((resolve) => {
      const timeoutId = setTimeout(() => {
        this.authCompleteCallbacks.delete(state);
        resolve(false);
      }, timeout);
      this.authCompleteCallbacks.set(state, (success) => {
        clearTimeout(timeoutId);
        resolve(success);
      });
    });
  }
}
if (process.argv[1] === new URL(import.meta.url).pathname) {
  const projectRoot = process.cwd();
  const server = new LinearOAuthServer(projectRoot, {
    autoShutdown: true,
    shutdownDelay: 5e3
  });
  server.start().then(({ url }) => {
    if (url) {
      console.log(chalk.cyan("\nWaiting for authorization..."));
      console.log(chalk.gray("Press Ctrl+C to cancel\n"));
    }
  }).catch((error) => {
    console.error(chalk.red("Failed to start OAuth server:"), error);
    process.exit(1);
  });
  process.on("SIGINT", async () => {
    console.log(chalk.yellow("\n\nShutting down OAuth server..."));
    await server.stop();
    process.exit(0);
  });
}
export {
  LinearOAuthServer
};
//# sourceMappingURL=oauth-server.js.map
