import path from "path";
import ora from "ora";
import { Command } from "commander";
import { SimpleDevServer } from "../../../utils/shopify/simple-dev-server.js";
import { ThemeManager } from "../../../utils/shopify/theme-manager.js";
import { createLogger } from "../../../utils/logger.js";
import Shopify from "shopify-api-node";
import dotenv from "dotenv";

const logger = createLogger("theme-dev");

/**
 * Options for the theme development server
 */
export interface ThemeDevOptions {
  /** Shopify store name (e.g., my-store) */
  store: string;
  /** Shopify Admin API key */
  apiKey: string;
  /** Shopify Admin API password/token */
  password: string;
  /** Theme ID to use for development (optional) */
  themeId?: string;
  /** Theme directory (defaults to current directory) */
  themeDir?: string;
  /** Port for preview server */
  port?: string;
  /** Name for the development theme if creating a new one */
  themeName?: string;
  /** Enable debug mode */
  debug?: boolean;
}

/**
 * Load environment variables from .env file
 */
function loadEnvVariables(): void {
  const result = dotenv.config();

  if (result.error) {
    logger.warn(
      "No .env file found. You'll need to provide credentials via command line options."
    );
    return;
  }

  if (result.parsed) {
    logger.info("Loaded environment variables from .env file");
  }
}

/**
 * Validate required credentials
 */
function validateCredentials(options: ThemeDevOptions): void {
  const missingCredentials: string[] = [];

  if (!options.store) {
    if (process.env.SHOPIFY_STORE) {
      options.store = process.env.SHOPIFY_STORE;
    } else {
      missingCredentials.push("store (-s, --store)");
    }
  }

  if (!options.apiKey) {
    if (process.env.SHOPIFY_API_KEY) {
      options.apiKey = process.env.SHOPIFY_API_KEY;
    } else {
      missingCredentials.push("API key (-k, --api-key)");
    }
  }

  if (!options.password) {
    if (process.env.SHOPIFY_PASSWORD) {
      options.password = process.env.SHOPIFY_PASSWORD;
    } else {
      missingCredentials.push("password (-p, --password)");
    }
  }

  if (missingCredentials.length > 0) {
    logger.error("Missing required credentials:");
    missingCredentials.forEach((cred) => logger.error(`  - ${cred}`));
    logger.info("\nYou can provide these credentials in two ways:");
    logger.info(
      "1. Create a .env file in your theme directory with the following variables:"
    );
    logger.info("   SHOPIFY_STORE=your-store");
    logger.info("   SHOPIFY_API_KEY=your-api-key");
    logger.info("   SHOPIFY_PASSWORD=your-password");
    logger.info("\n2. Pass them as command line options:");
    logger.info(
      "   npx @dscodotco/theme-cli shopify theme dev -s your-store -k your-api-key -p your-password"
    );
    process.exit(1);
  }
}

export const dev = new Command()
  .name("dev")
  .description("Start a local development server for theme development")
  .option("-s, --store <store>", "Shopify store name (e.g., my-store)")
  .option("-k, --api-key <key>", "Shopify Admin API key")
  .option("-p, --password <password>", "Shopify Admin API password/token")
  .option("-t, --theme-id <id>", "Theme ID to use for development")
  .option(
    "-d, --theme-dir <dir>",
    "Theme directory (defaults to current directory)"
  )
  .option("--port <port>", "Port for preview server", "3000")
  .option("--theme-name <n>", "Name for the development theme")
  .option("--debug", "Enable debug mode with verbose logging", false)
  .action(async (options: ThemeDevOptions) => {
    // Load environment variables
    loadEnvVariables();

    // Validate credentials
    validateCredentials(options);

    const spinner = ora("Starting development server...").start();

    try {
      if (options.debug) {
        logger.info("Debug mode enabled");
        logger.info("Configuration:");
        logger.info(`  Store: ${options.store}`);
        logger.info(`  Theme directory: ${options.themeDir || "."}`);
        logger.info(`  Port: ${options.port || "3000"}`);
        logger.info(`  Theme ID: ${options.themeId || "Creating new theme"}`);
      }

      // Initialize Shopify client
      const shopify = new Shopify({
        shopName: options.store,
        accessToken: options.password,
        apiVersion: "2023-04",
      });

      // Initialize theme manager
      const themeManager = new ThemeManager({
        storeName: options.store,
        apiKey: options.apiKey,
        password: options.password,
      });

      // Resolve theme directory
      const themeDir = path.resolve(options.themeDir || ".");

      // Get or create theme ID
      let themeId = options.themeId ? parseInt(options.themeId) : undefined;
      if (!themeId) {
        spinner.text = "Creating a new development theme...";
        const theme = await themeManager.createDevelopmentTheme(
          options.themeName || "Development Theme"
        );
        themeId = theme.id;
        spinner.succeed(
          `Created new development theme: ${theme.name} (ID: ${themeId})`
        );
      }

      // Start development server
      spinner.start("Starting development server...");
      const port = parseInt(options.port || "3000");
      const server = new SimpleDevServer({
        port,
        themeDir,
        shopify,
        themeManager,
        credentials: {
          storeName: options.store,
          apiKey: options.apiKey,
          password: options.password,
        },
        themeId,
        debug: options.debug,
      });

      await server.start();
      spinner.succeed("Development server running");

      // Log preview URL
      const previewUrl = themeManager.getThemePreviewUrl(themeId);
      logger.info(`\nShopify theme preview: ${previewUrl}`);

      if (!options.themeId) {
        logger.info("\nA new development theme was created for this session.");
        logger.info(
          "It will remain in your Shopify admin until you delete it.\n"
        );
      }

      logger.info("Press Ctrl+C to stop the development server");

      // Handle shutdown
      process.on("SIGINT", () => {
        logger.info("\nShutting down...");
        server.stop();
        process.exit(0);
      });
    } catch (error) {
      spinner.fail(
        `Failed to start development server: ${(error as Error).message}`
      );
      if (options.debug && error instanceof Error) {
        logger.error("Stack trace:");
        logger.error(error.stack || "No stack trace available");
      }
      process.exit(1);
    }
  });
