import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { In, LessThan, Like, MoreThan, Repository } from 'typeorm';
import { Menu } from '@/modules/menu/menu.entity';
import { SharedService } from '@/shared/shared.service';
import { Article } from '@/modules/article/article.entity';
import { Category } from '@/modules/category/category.entity';
import { getTopMenuFragment } from '@/common/utils';
import { CustomException, ErrorCode } from '@/common/exceptions/custom.exception';

@Injectable()
export class WebService {
  constructor(
    @InjectRepository(Menu)
    private menuRepo: Repository<Menu>,
    @InjectRepository(Article)
    private articleRepo: Repository<Article>,
    @InjectRepository(Category)
    private categoryRepo: Repository<Category>,
    private readonly sharedService: SharedService,
  ) {}

  async findMenuTree(locale?: string): Promise<Menu[]> {
    const lang = this.sharedService.handleValidLang(locale);
    const menus = await this.menuRepo.find({
      where: {
        enable: true,
        // isPublish: true,
      },
      order: {
        order: 'ASC',
        children: {
          order: 'ASC',
        },
      },
      relations: {
        children: true,
        category: true,
        translations: true,
      },
      select: {
        category: {
          id: true,
          title: true,
        },
      },
    });
    const allMenus = menus.map((menu) => (menu.translations?.length ? menu.translate(lang) : menu));
    // console.log('menus', lang, allMenus);
    return this.sharedService.handleTree(allMenus);
  }

  async findArticleDetail(id: number, locale?: string) {
    const lang = this.sharedService.handleValidLang(locale);
    const article = await this.articleRepo.findOne({
      where: { id, enable: true },
      relations: { user: true, translations: true, category: true },
      select: {
        user: {
          id: true,
          username: true,
        },
        category: {
          id: true,
          title: true,
        },
      },
    });
    return article ? article.translate(lang) : false;
  }

  async setArticleCount(id: number) {
    const article = await this.articleRepo.findOne({
      where: { id, enable: true },
    });
    if (!article) {
      return false;
    }
    article.readCount = article.readCount + 1;
    // console.log('article', article);
    await this.articleRepo.save(article);
    return true;
  }

  async getTopCategory1(id: number) {
    let currentCategory = await this.categoryRepo.findOne({
      where: { id, enable: true },
      relations: { parent: true },
    });

    if (!currentCategory) {
      return null; // 如果分类不存在，返回 null
    }
    // 递归查找顶层父分类
    while (currentCategory.parent) {
      currentCategory = await this.categoryRepo.findOne({
        where: { id: currentCategory.parent.id, enable: true },
        relations: { parent: true },
      });
    }
    console.log('currentCategory', currentCategory);
    return currentCategory.id
      ? this.categoryRepo.findOne({
          where: { id: currentCategory.id, enable: true },
          relations: { children: true },
        })
      : null;
  }

  async getCategoryTreeAndPath(id: number, locale: string) {
    const lang = this.sharedService.handleValidLang(locale);

    const categories = await this.categoryRepo.find({
      where: { enable: true },
      relations: { children: true, translations: true },
    });
    const data = this.sharedService.handleTree(categories.map((cate) => cate.translate(lang)));
    return getTopMenuFragment(data, id);
  }

  async searchArticles(key: string, locale?: string) {
    const lang = this.sharedService.handleValidLang(locale);
    const articles = await this.articleRepo.find({
      where: {
        enable: true,
        translations: [{
          locale: lang,
          title: Like(`%${key || ''}%`),
        },{
          locale: lang,
          content: Like(`%${key || ''}%`),
        }],
      },
      relations: { translations: true },
    });
    
    return articles.map((article) => article.translate(lang));
  }

  async findCateAllChildIds(parentId: number) {
    const childIds: number[] = [];
    // 递归查找所有子菜单的 id
    const findChildren = async (id: number) => {
      const children = await this.categoryRepo.find({ where: { parentId: id, enable: true } });
      for (const child of children) {
        childIds.push(child.id);
        await findChildren(child.id); // 递归查找子菜单的子菜单
      }
    };
    await findChildren(parentId);
    return childIds;
  }

  async getArticlesByCate(id: number, locale?: string) {
    const lang = this.sharedService.handleValidLang(locale);

    // 保留
    const category = await this.categoryRepo.findOne({
      where: { id: id, enable: true },
      relations: { children: true },
    });
    const ids = await this.findCateAllChildIds(category.id);
    // ids.push(category.id);
    // console.log('ids', ids);
    const articles = await this.articleRepo.find({
      where: {
        categoryId: id,
        enable: true,
      },
      relations: { translations: true },
      order: {
        order: 'DESC',
        createTime: 'DESC',
      },
    });
    const childArticles = await this.articleRepo.find({
      where: {
        categoryId: In(ids),
        enable: true,
      },
      relations: { translations: true },
      order: {
        order: 'DESC',
        createTime: 'DESC',
      },
    });
    // console.log('childArticles', childArticles);
    return articles.length > 0
      ? articles.map((article) => article.translate(lang))
      : childArticles.map((article) => article.translate(lang));
  }

  async getNearArticle(currentId: number, locale?: string) {
    const lang = this.sharedService.handleValidLang(locale);
    const currentEntity = await this.articleRepo.findOne({
      where: { id: currentId, enable: true },
    });
    if (!currentEntity) {
      // throw new CustomException(ErrorCode.ERR_4000, '当前数据不存在');
      return [];
    }

    const prevEntity = await this.articleRepo.findOne({
      where: { id: LessThan(currentId), categoryId: currentEntity.categoryId, enable: true },
      order: { id: 'DESC' },
      relations: { translations: true },
    });

    const nextEntity = await this.articleRepo.findOne({
      where: { id: MoreThan(currentId), categoryId: currentEntity.categoryId, enable: true },
      order: { id: 'ASC' },
      relations: { translations: true },
    });
    return [
      prevEntity ? prevEntity.translate(lang) : null,
      nextEntity ? nextEntity.translate(lang) : null,
    ];
  }
}
