import axios from "axios";
import { createLogger } from "../logger.js";
import { createHmac } from "crypto";

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

export interface ShopifyCredentials {
  storeName: string;
  apiKey: string;
  password: string;
}

export interface ShopifyTheme {
  id: number;
  name: string;
  role: string;
  theme_store_id?: number;
  previewable: boolean;
  processing: boolean;
  admin_graphql_api_id: string;
  created_at: string;
  updated_at: string;
}

/**
 * Manages Shopify themes through the Admin API
 */
export class ThemeManager {
  private credentials: ShopifyCredentials;
  private baseUrl: string;
  private apiUrl: string;
  private isAccessToken: boolean;

  /**
   * Creates a new ThemeManager instance
   * @param credentials Shopify store credentials
   */
  constructor(credentials: ShopifyCredentials) {
    this.credentials = credentials;
    this.baseUrl = `https://${credentials.storeName}.myshopify.com`;
    this.apiUrl = `${this.baseUrl}/admin/api/2023-04`;

    // Determine if we're using an access token (shpat_) or API key + secret
    this.isAccessToken = this.credentials.password.startsWith("shpat_");

    if (!this.isAccessToken) {
      logger.info("Using API key + secret authentication");
    } else {
      logger.info("Using access token authentication");
    }
  }

  /**
   * Gets the appropriate authentication configuration for Shopify API calls
   * @returns Authentication config object
   */
  public getAuthConfig = (): any => {
    if (this.isAccessToken) {
      // Access token auth - use headers
      return {
        headers: {
          "X-Shopify-Access-Token": this.credentials.password,
          "Content-Type": "application/json",
        },
      };
    } else {
      // API key + secret auth - use basic auth
      return {
        auth: {
          username: this.credentials.apiKey,
          password: this.credentials.password,
        },
        headers: {
          "Content-Type": "application/json",
        },
      };
    }
  };

  /**
   * Lists all themes in the store
   * @returns Promise containing array of themes
   */
  async listThemes(): Promise<ShopifyTheme[]> {
    try {
      const authConfig = this.getAuthConfig();
      const response = await axios.get(
        `${this.apiUrl}/themes.json`,
        authConfig
      );

      return response.data.themes as ShopifyTheme[];
    } catch (error) {
      logger.error(`Failed to list themes: ${(error as Error).message}`);
      throw error;
    }
  }

  /**
   * Creates a new development theme
   * @param name The name for the new theme
   * @returns The created theme
   */
  async createDevelopmentTheme(name?: string): Promise<ShopifyTheme> {
    const themeName = name || `Development Theme (${new Date().toISOString()})`;
    const requestBody = {
      theme: {
        name: themeName,
        role: "development",
      },
    };

    try {
      logger.info(`Creating new development theme: ${themeName}`);

      const authConfig = this.getAuthConfig();
      const response = await axios.post(
        `${this.apiUrl}/themes.json`,
        requestBody,
        authConfig
      );

      const newTheme = response.data.theme as ShopifyTheme;
      logger.success(
        `Created new development theme: ${newTheme.name} (ID: ${newTheme.id})`
      );

      return newTheme;
    } catch (error) {
      logger.error(
        `Failed to create development theme: ${(error as Error).message}`
      );
      throw error;
    }
  }

  /**
   * Gets the preview URL for a theme
   * @param themeId The theme ID
   * @returns The preview URL
   */
  getThemePreviewUrl(themeId: number): string {
    return `${this.baseUrl}/?preview_theme_id=${themeId}`;
  }
}
