import React from 'react';
import { createRoot, Root } from 'react-dom/client';
import { PlasoViewer } from './components/PlasoViewer';
import { Environment } from './config/environment';
import { PlasoContentType,getUrlConfigMap } from './config/url';

export interface PlasoClientOptions {
  token: string;
  container: HTMLElement;
  env?: Environment;
  onError?: (error: Error) => void;
  onLoading?: (isLoading: boolean) => void;
  // 是否打开开发者工具
  devTools?: boolean
  sdkVersion: string;
  platform?: string;
}

// 定义URL映射配置
interface UrlConfig {
  baseUrl: string;
}


export class PlasoClient {
  private platform: string;
  private token: string;
  private container: HTMLElement;
  private onError?: (error: Error) => void;
  private onLoading?: (isLoading: boolean) => void;
  private root: Root | null = null;
  private env: Environment;
  private URL_CONFIG_MAP: Record<PlasoContentType, UrlConfig> | null = null;
  private devTools: boolean;
  private sdkVersion: string;
  
  constructor(options: PlasoClientOptions) {
    this.platform = options.platform || 'plaso';
    this.token = options.token;
    this.container = options.container;
    this.onError = options.onError;
    this.onLoading = options.onLoading;
    this.root = createRoot(this.container);
    this.env = options.env || Environment.PROD;
    this.URL_CONFIG_MAP = getUrlConfigMap(this.env, this.platform);
    this.devTools = options.devTools || false;
    this.sdkVersion = options.sdkVersion;
    this.checkParams();
  }

  private checkParams = () => {
    if(!(this.token && this.container && this.sdkVersion)){
      this.onError?.(new Error('传入参数有误'));
    }
  }

  private handleError(error: Error): void {
    console.error('Plaso客户端错误:', error);
    if (this.onError) {
      this.onError(error);
    }
  }

  /**
   * 构建完整URL
   * @param type 内容类型
   * @returns 完整的URL
   */
  private buildUrl(type: PlasoContentType): string {
    const config = this.URL_CONFIG_MAP?.[type];
    if (!config) {
      throw new Error(`不支持的内容类型: ${type}`);
    }

    const { baseUrl } = config;
    
    // 检查baseUrl是否已包含参数
    const hasParams = baseUrl.includes('?');
    const separator = hasParams ? '&' : '?';

    
    return `${baseUrl}${separator}token=${encodeURIComponent(this.token)}&sdkVersion=${this.sdkVersion}`;
  }

  /**
   * 渲染内容
   * @param type 内容类型
   */
  private async renderContent(type: PlasoContentType): Promise<void> {
    if (!this.root) {
      throw new Error('Plaso客户端未正确初始化');
    }

    if (this.onLoading) {
      this.onLoading(true);
    }

    try {
      const url = this.buildUrl(type);

      this.root.render(
        React.createElement(PlasoViewer, {
          url,
          token: this.token,
          type,
          devTools: this.devTools,
          onError: this.handleError.bind(this)
        })
      );
    } catch (error) {
      this.handleError(error as Error);
      throw error;
    } finally {
      if (this.onLoading) {
        this.onLoading(false);
      }
    }
  }

  /**
   * 创建指定类型的模块
   * @param module 模块类型
   */
  public async createModule(module: PlasoContentType): Promise<void> {
    try {
      await this.renderContent(module);
    } catch (error) {
      this.handleError(error as Error);
      throw error;
    }
  }

  /**
   * 创建作业
   */
  public async createAssignment(): Promise<void> {
    try {
      await this.createModule(PlasoContentType.NHOMEWORK);
    } catch (error) {
      this.handleError(error as Error);
      throw error;
    }
  }

  /**
   * 创建课堂
   */
  public async createClassroom(): Promise<void> {
    try {
      await this.createModule(PlasoContentType.LIVECLASS);
    } catch (error) {
      this.handleError(error as Error);
      throw error;
    }
  }

  /**
   * 渲染自定义内容
   * @param type 内容类型
   */
  public async renderCustomContent(type: PlasoContentType): Promise<void> {
    try {
      await this.createModule(type);
    } catch (error) {
      this.handleError(error as Error);
      throw error;
    }
  }

  /**
   * 销毁客户端实例
   */
  public destroy(): void {
    if (this.root) {
      this.root.unmount();
      this.root = null;
    }
  }
} 