/**
 * 统一 DataSource 工厂模式
 * 消除前端数据源重复代码，提供统一的创建和管理机制
 */

import { IDataSource } from '@/types/datasource';

// 环境变量判断
const useMock = process.env.REACT_APP_USE_MOCK === 'true';

/**
 * 基础 DataSource 抽象类
 * 提供通用的 CRUD 方法实现
 */
export abstract class BaseDataSource<T, P = any> implements IDataSource<T, P> {
  protected baseUrl: string;

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl;
  }

  async list(params?: P): Promise<T[]> {
    const query = this.buildQueryParams(params);
    const response = await fetch(`${this.baseUrl}?${query}`, {
      headers: {
        'Content-Type': 'application/json',
      },
    });

    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }

    const result = await response.json();
    return result.data || [];
  }

  async detail(id: string): Promise<T | null> {
    const response = await fetch(`${this.baseUrl}/${id}`, {
      headers: {
        'Content-Type': 'application/json',
      },
    });

    if (!response.ok) {
      if (response.status === 404) return null;
      throw new Error(`API Error: ${response.status}`);
    }

    const result = await response.json();
    return result.data || null;
  }

  async create(data: Partial<T>): Promise<T> {
    const response = await fetch(this.baseUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    });

    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }

    const result = await response.json();
    
    // 创建成功后获取完整数据
    if (result.data?.id) {
      const created = await this.detail(result.data.id);
      if (created) return created;
    }
    
    return result.data;
  }

  async update(id: string, data: Partial<T>): Promise<T> {
    const response = await fetch(`${this.baseUrl}/${id}`, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    });

    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }

    const result = await response.json();
    
    // 更新成功后获取完整数据
    const updated = await this.detail(id);
    if (updated) return updated;
    
    return result.data;
  }

  async delete(id: string): Promise<void> {
    const response = await fetch(`${this.baseUrl}/${id}`, {
      method: 'DELETE',
      headers: {
        'Content-Type': 'application/json',
      },
    });

    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }
  }

  /**
   * 构建查询参数
   */
  protected buildQueryParams(params?: P): string {
    const query = new URLSearchParams();
    if (params) {
      Object.entries(params).forEach(([key, value]) => {
        if (value !== undefined && value !== null) {
          query.append(key, String(value));
        }
      });
    }
    return query.toString();
  }

  /**
   * 模拟延迟（用于 Mock 实现）
   */
  protected delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

/**
 * 基础 Mock DataSource 类
 */
export abstract class BaseMockDataSource<T, P = any> implements IDataSource<T, P> {
  /** Mock标记 */
  readonly __MOCK__ = true as const;
  /** Mock数据源名称 */
  abstract readonly __MOCK_NAME__: string;
  /** Mock数据 */
  protected abstract mockData: T[];

  async list(params?: P): Promise<T[]> {
    await this.delay(200);
    return this.mockData;
  }

  async detail(id: string): Promise<T | null> {
    await this.delay(100);
    return this.mockData.find(item => (item as any).id === id) || null;
  }

  async create(data: Partial<T>): Promise<T> {
    await this.delay(300);
    
    const newItem = {
      id: `${Date.now()}`,
      ...data,
    } as T;

    this.mockData.unshift(newItem);
    return newItem;
  }

  async update(id: string, data: Partial<T>): Promise<T> {
    await this.delay(300);

    const index = this.mockData.findIndex(item => (item as any).id === id);
    if (index === -1) {
      throw new Error('Item not found');
    }

    this.mockData[index] = { ...this.mockData[index], ...data };
    return this.mockData[index];
  }

  async delete(id: string): Promise<void> {
    await this.delay(200);
    this.mockData = this.mockData.filter(item => (item as any).id !== id);
  }

  /**
   * 模拟延迟
   */
  protected delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

/**
 * DataSource 工厂类
 * 负责根据环境变量创建相应的 DataSource 实例
 */
export class DataSourceFactory {
  /**
   * 创建 DataSource 实例
   * @param apiDataSource API实现类
   * @param mockDataSource Mock实现类
   * @returns DataSource 实例
   */
  static create<T, P = any>(
    apiDataSource: new () => IDataSource<T, P>,
    mockDataSource: new () => IDataSource<T, P>
  ): IDataSource<T, P> {
    return useMock ? new mockDataSource() : new apiDataSource();
  }

  /**
   * 创建带有自定义方法的 DataSource 实例
   * @param apiDataSource API实现类
   * @param mockDataSource Mock实现类
   * @returns DataSource 实例
   */
  static createWithMethods<T, P = any, M extends Record<string, any>>({
    apiDataSource,
    mockDataSource,
  }: {
    apiDataSource: new () => IDataSource<T, P> & M;
    mockDataSource: new () => IDataSource<T, P> & M;
  }): IDataSource<T, P> & M {
    return useMock ? new mockDataSource() : new apiDataSource();
  }
}

/**
 * Mock状态标记
 * 用于调试和开发环境识别
 */
export const __MOCK__ = useMock;

/**
 * 当前数据源类型
 */
export const __DATA_SOURCE_TYPE__ = useMock ? 'mock' : 'api';
