import { Injectable } from '@nestjs/common';
import { BaseQueryDto, FilterDto, FilterOperator, SortOrder } from '../dto/base-query.dto';

@Injectable()
export class QueryBuilderService {
  /**
   * 构建 Prisma where 条件
   */
  buildWhereClause(query: BaseQueryDto, modelFields: Record<string, any> = {}): any {
    const where: any = {};

    // 处理全文搜索
    if (query.search) {
      const searchConditions = this.buildSearchConditions(query.search, modelFields);
      if (searchConditions.length > 0) {
        where.OR = searchConditions;
      }
    }

    // 处理日期范围
    if (query.dateFrom || query.dateTo) {
      where.createdAt = {};
      if (query.dateFrom) {
        where.createdAt.gte = new Date(query.dateFrom);
      }
      if (query.dateTo) {
        where.createdAt.lte = new Date(query.dateTo);
      }
    }

    // 处理高级过滤条件
    if (query.filters && query.filters.length > 0) {
      query.filters.forEach((filter) => {
        const condition = this.buildFilterCondition(filter);
        if (condition) {
          where[filter.field] = condition;
        }
      });
    }

    // 处理软删除
    if (!query.includeDeleted) {
      where.deletedAt = null;
    }

    // 合并模型特定的字段过滤
    Object.keys(modelFields).forEach((field) => {
      if (modelFields[field] !== undefined && modelFields[field] !== null) {
        // 对字符串字段使用包含查询
        if (typeof modelFields[field] === 'string') {
          where[field] = {
            contains: modelFields[field],
            mode: 'insensitive',
          };
        } else {
          where[field] = modelFields[field];
        }
      }
    });

    return where;
  }

  /**
   * 构建搜索条件
   */
  private buildSearchConditions(search: string, modelFields: Record<string, any>): any[] {
    const searchableFields = ['name', 'title', 'description', 'content', 'key', 'code'];
    const conditions: any[] = [];

    searchableFields.forEach((field) => {
      // 只对模型中实际存在的字段进行搜索
      if (modelFields[field] !== undefined || !Object.keys(modelFields).length) {
        conditions.push({
          [field]: {
            contains: search,
            mode: 'insensitive',
          },
        });
      }
    });

    return conditions;
  }

  /**
   * 构建单个过滤条件
   */
  private buildFilterCondition(filter: FilterDto): any {
    const { operator, value } = filter;

    switch (operator) {
      case FilterOperator.EQUALS:
        return value;

      case FilterOperator.NOT_EQUALS:
        return { not: value };

      case FilterOperator.CONTAINS:
        return { contains: value, mode: 'insensitive' };

      case FilterOperator.STARTS_WITH:
        return { startsWith: value, mode: 'insensitive' };

      case FilterOperator.ENDS_WITH:
        return { endsWith: value, mode: 'insensitive' };

      case FilterOperator.GT:
        return { gt: value };

      case FilterOperator.GTE:
        return { gte: value };

      case FilterOperator.LT:
        return { lt: value };

      case FilterOperator.LTE:
        return { lte: value };

      case FilterOperator.IN:
        return { in: Array.isArray(value) ? value : [value] };

      case FilterOperator.NOT_IN:
        return { notIn: Array.isArray(value) ? value : [value] };

      case FilterOperator.IS_NULL:
        return null;

      case FilterOperator.IS_NOT_NULL:
        return { not: null };

      default:
        return value;
    }
  }

  /**
   * 构建排序条件
   */
  buildOrderBy(query: BaseQueryDto): any {
    if (!query.sortBy) {
      return { createdAt: SortOrder.DESC };
    }

    // 支持多字段排序 (e.g., "name,createdAt")
    if (query.sortBy.includes(',')) {
      const fields = query.sortBy.split(',');
      return fields.reduce(
        (acc, field) => {
          acc[field.trim()] = query.sortOrder || SortOrder.DESC;
          return acc;
        },
        {} as Record<string, SortOrder>,
      );
    }

    return { [query.sortBy]: query.sortOrder || SortOrder.DESC };
  }

  /**
   * 构建分页参数
   */
  buildPagination(query: BaseQueryDto): { skip: number; take: number } {
    const page = query.page || 1;
    const pageSize = query.pageSize || 10;

    return {
      skip: (page - 1) * pageSize,
      take: pageSize,
    };
  }

  /**
   * 构建选择字段
   */
  buildSelect(query: BaseQueryDto): any {
    if (!query.select || query.select.length === 0) {
      return undefined;
    }

    return query.select.reduce(
      (acc, field) => {
        acc[field] = true;
        return acc;
      },
      {} as Record<string, boolean>,
    );
  }

  /**
   * 构建包含关系
   */
  buildInclude(query: BaseQueryDto, defaultInclude?: any): any {
    if (!query.include || query.include.length === 0) {
      return defaultInclude;
    }

    // 支持嵌套关系 (e.g., "project.team")
    const include: any = {};

    query.include.forEach((relation) => {
      if (relation.includes('.')) {
        const parts = relation.split('.');
        let current = include;

        parts.forEach((part, index) => {
          if (index === parts.length - 1) {
            current[part] = true;
          } else {
            current[part] = current[part] || { include: {} };
            current = current[part].include;
          }
        });
      } else {
        include[relation] = true;
      }
    });

    // 合并默认包含
    if (defaultInclude) {
      Object.keys(defaultInclude).forEach((key) => {
        if (!include[key]) {
          include[key] = defaultInclude[key];
        }
      });
    }

    return include;
  }

  /**
   * 构建响应元数据
   */
  buildResponseMeta(
    query: BaseQueryDto,
    total: number,
  ): {
    total: number;
    page: number;
    pageSize: number;
    totalPages: number;
    hasNext: boolean;
    hasPrevious: boolean;
  } {
    const page = query.page || 1;
    const pageSize = query.pageSize || 10;
    const totalPages = Math.ceil(total / pageSize);

    return {
      total,
      page,
      pageSize,
      totalPages,
      hasNext: page < totalPages,
      hasPrevious: page > 1,
    };
  }
}