import { DataSource, Repository, ObjectLiteral, DeepPartial, In } from 'typeorm';
import { z } from '@hono/zod-openapi';

export abstract class GenericCrudService<T extends ObjectLiteral> {
  protected repository: Repository<T>;
  private userTrackingOptions?: UserTrackingOptions;

  protected relationFields?: RelationFieldOptions;

  constructor(
    protected dataSource: DataSource,
    protected entity: new () => T,
    options?: {
      userTracking?: UserTrackingOptions;
      relationFields?: RelationFieldOptions;
    }
  ) {
    this.repository = this.dataSource.getRepository(entity);
    this.userTrackingOptions = options?.userTracking;
    this.relationFields = options?.relationFields;
  }

  /**
   * 获取分页列表
   */
  async getList(
    page: number = 1,
    pageSize: number = 10,
    keyword?: string,
    searchFields?: string[],
    where?: Partial<T>,
    relations: string[] = [],
    order: { [P in keyof T]?: 'ASC' | 'DESC' } = {},
    filters?: {
      [key: string]: any;
    }
  ): Promise<[T[], number]> {
    const skip = (page - 1) * pageSize;
    const query = this.repository.createQueryBuilder('entity');

    // 添加关联关系（支持嵌套关联，如 ['contract.client']）
    // 使用一致的别名生成策略，确保搜索时能正确引用关联字段
    if (relations.length > 0) {
      relations.forEach((relation) => {
        const parts = relation.split('.');
        let currentAlias = 'entity';
        
        parts.forEach((part, index) => {
          // 生成一致的别名：对于嵌套关联，使用下划线连接路径
          const newAlias = index === 0 ? part : parts.slice(0, index + 1).join('_');
          query.leftJoinAndSelect(`${currentAlias}.${part}`, newAlias);
          currentAlias = newAlias;
        });
      });
    }

    // 关键词搜索 - 支持关联字段搜索（格式：relation.field 或 relation.nestedRelation.field）
    if (keyword && searchFields && searchFields.length > 0) {
      const searchConditions: string[] = [];
      const searchParams: Record<string, string> = { keyword: `%${keyword}%` };

      searchFields.forEach((field) => {
        // 检查是否为关联字段（包含点号）
        if (field.includes('.')) {
          const parts = field.split('.');
          const alias = parts.slice(0, -1).join('_'); // 使用下划线连接关系路径作为别名
          const fieldName = parts[parts.length - 1];
          
          searchConditions.push(`${alias}.${fieldName} LIKE :keyword`);
        } else {
          // 普通字段搜索
          searchConditions.push(`entity.${field} LIKE :keyword`);
        }
      });

      if (searchConditions.length > 0) {
        query.andWhere(`(${searchConditions.join(' OR ')})`, searchParams);
      }
    }

    // 条件查询
    if (where) {
      Object.entries(where).forEach(([key, value]) => {
        if (value !== undefined && value !== null) {
          query.andWhere(`entity.${key} = :${key}`, { [key]: value });
        }
      });
    }

    // 扩展筛选条件
    if (filters) {
      Object.entries(filters).forEach(([key, value]) => {
        if (value !== undefined && value !== null && value !== '') {
          const fieldName = key.startsWith('_') ? key.substring(1) : key;
          
          // 检查是否为关联字段（包含点号）
          let tableAlias = 'entity';
          let actualFieldName = fieldName;
          
          if (fieldName.includes('.')) {
            const parts = fieldName.split('.');
            tableAlias = parts.slice(0, -1).join('_'); // 使用下划线连接关系路径作为别名
            actualFieldName = parts[parts.length - 1];
          }
          
          // 支持不同类型的筛选
          if (Array.isArray(value)) {
            // 数组类型：IN查询
            if (value.length > 0) {
              query.andWhere(`${tableAlias}.${actualFieldName} IN (:...${key})`, { [key]: value });
            }
          } else if (typeof value === 'string' && value.includes('%')) {
            // 模糊匹配
            query.andWhere(`${tableAlias}.${actualFieldName} LIKE :${key}`, { [key]: value });
          } else if (typeof value === 'object' && value !== null) {
            // 范围查询
            if ('gte' in value) {
              query.andWhere(`${tableAlias}.${actualFieldName} >= :${key}_gte`, { [`${key}_gte`]: value.gte });
            }
            if ('gt' in value) {
              query.andWhere(`${tableAlias}.${actualFieldName} > :${key}_gt`, { [`${key}_gt`]: value.gt });
            }
            if ('lte' in value) {
              query.andWhere(`${tableAlias}.${actualFieldName} <= :${key}_lte`, { [`${key}_lte`]: value.lte });
            }
            if ('lt' in value) {
              query.andWhere(`${tableAlias}.${actualFieldName} < :${key}_lt`, { [`${key}_lt`]: value.lt });
            }
            if ('between' in value && Array.isArray(value.between) && value.between.length === 2) {
              query.andWhere(`${tableAlias}.${actualFieldName} BETWEEN :${key}_start AND :${key}_end`, {
                [`${key}_start`]: value.between[0],
                [`${key}_end`]: value.between[1]
              });
            }
          } else {
            // 精确匹配
            query.andWhere(`${tableAlias}.${actualFieldName} = :${key}`, { [key]: value });
          }
        }
      });
    }

    // 排序
    Object.entries(order).forEach(([key, direction]) => {
      query.orderBy(`entity.${key}`, direction);
    });

    const finalQuery = query.skip(skip).take(pageSize);

    // console.log(finalQuery.getSql())

    return finalQuery.getManyAndCount();
  }

  /**
   * 根据ID获取单个实体
   */
  async getById(id: number, relations: string[] = []): Promise<T | null> {
    return this.repository.findOne({
      where: { id } as any,
      relations
    });
  }

  /**
   * 设置用户跟踪字段
   */
  private setUserFields(data: any, userId?: string | number, isCreate: boolean = true): void {
    if (!this.userTrackingOptions || !userId) {
      return;
    }

    const {
      createdByField = 'createdBy',
      updatedByField = 'updatedBy',
      userIdField = 'userId'
    } = this.userTrackingOptions;

    // 设置创建人
    if (isCreate && createdByField) {
      data[createdByField] = userId;
    }

    // 设置更新人
    if (updatedByField) {
      data[updatedByField] = userId;
    }

    // 设置关联的用户ID（如userId字段）
    if (isCreate && userIdField) {
      data[userIdField] = userId;
    }
  }

  /**
   * 创建实体
   */
  /**
   * 处理关联字段
   */
  private async handleRelationFields(data: any, entity: T, _isUpdate: boolean = false): Promise<void> {
    if (!this.relationFields) return;

    for (const [fieldName, config] of Object.entries(this.relationFields)) {
      if (data[fieldName] !== undefined) {
        const ids = data[fieldName];
        const relationRepository = this.dataSource.getRepository(config.targetEntity);
        
        if (ids && Array.isArray(ids) && ids.length > 0) {
          const relatedEntities = await relationRepository.findBy({ id: In(ids) });
          (entity as any)[config.relationName] = relatedEntities;
        } else {
          (entity as any)[config.relationName] = [];
        }
        
        // 清理原始数据中的关联字段
        delete data[fieldName];
      }
    }
  }

  /**
   * 创建实体
   */
  async create(data: DeepPartial<T>, userId?: string | number): Promise<T> {
    const entityData = { ...data };
    this.setUserFields(entityData, userId, true);
    
    // 分离关联字段数据
    const relationData: any = {};
    if (this.relationFields) {
      for (const fieldName of Object.keys(this.relationFields)) {
        if (fieldName in entityData) {
          relationData[fieldName] = (entityData as any)[fieldName];
          delete (entityData as any)[fieldName];
        }
      }
    }

    const entity = this.repository.create(entityData as DeepPartial<T>);
    
    // 处理关联字段
    await this.handleRelationFields(relationData, entity);
    
    return this.repository.save(entity);
  }

  /**
   * 更新实体
   */
  async update(id: number, data: Partial<T>, userId?: string | number): Promise<T | null> {
    const updateData = { ...data };
    this.setUserFields(updateData, userId, false);
    
    // 分离关联字段数据
    const relationData: any = {};
    if (this.relationFields) {
      for (const fieldName of Object.keys(this.relationFields)) {
        if (fieldName in updateData) {
          relationData[fieldName] = (updateData as any)[fieldName];
          delete (updateData as any)[fieldName];
        }
      }
    }

    // 先更新基础字段
    await this.repository.update(id, updateData);
    
    // 获取完整实体并处理关联字段
    const entity = await this.getById(id);
    if (!entity) return null;
    
    // 处理关联字段
    await this.handleRelationFields(relationData, entity, true);
    
    return this.repository.save(entity);
  }

  /**
   * 删除实体
   */
  async delete(id: number): Promise<boolean> {
    const result = await this.repository.delete(id);
    return result.affected === 1;
  }

  /**
   * 高级查询方法
   */
  createQueryBuilder(alias: string = 'entity') {
    return this.repository.createQueryBuilder(alias);
  }
}

export interface UserTrackingOptions {
  createdByField?: string;
  updatedByField?: string;
  userIdField?: string;
}

export interface RelationFieldOptions {
  [fieldName: string]: {
    relationName: string;
    targetEntity: new () => any;
    joinTableName?: string;
  };
}

export type CrudOptions<
  T extends ObjectLiteral,
  CreateSchema extends z.ZodSchema = z.ZodSchema,
  UpdateSchema extends z.ZodSchema = z.ZodSchema,
  GetSchema extends z.ZodSchema = z.ZodSchema,
  ListSchema extends z.ZodSchema = z.ZodSchema
> = {
  entity: new () => T;
  createSchema: CreateSchema;
  updateSchema: UpdateSchema;
  getSchema: GetSchema;
  listSchema: ListSchema;
  searchFields?: string[];
  relations?: string[];
  middleware?: any[];
  userTracking?: UserTrackingOptions;
  relationFields?: RelationFieldOptions;
  readOnly?: boolean;
};