import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { SysMenu } from '../../entities/SysMenu';
import { CoreMenuService } from '../core/CoreMenuService';
import { CreateMenuDto, UpdateMenuDto, QueryMenuDto, BatchUpdateStatusDto } from '../../dto/admin/MenuDto';

@Injectable()
export class MenuAdminService {
  constructor(
    @InjectRepository(SysMenu)
    private sysMenuRepository: Repository<SysMenu>,
    private coreMenuService: CoreMenuService,
  ) {}

  async getMenuList(query: QueryMenuDto): Promise<{ list: SysMenu[]; total: number }> {
    const { page = 1, limit = 10, app_type, menu_name, status } = query;
    
    const queryBuilder = this.sysMenuRepository
      .createQueryBuilder('sys_menu')
      .where('sys_menu.delete_time = :delete_time', { delete_time: 0 });

    if (app_type) {
      queryBuilder.andWhere('sys_menu.app_type = :app_type', { app_type });
    }

    if (menu_name) {
      queryBuilder.andWhere('sys_menu.menu_name LIKE :menu_name', { menu_name: `%${menu_name}%` });
    }

    if (status !== undefined) {
      queryBuilder.andWhere('sys_menu.status = :status', { status });
    }

    const [list, total] = await queryBuilder
      .skip((page - 1) * limit)
      .take(limit)
      .orderBy('sys_menu.sort', 'DESC')
      .getManyAndCount();

    return { list, total };
  }

  async getMenuDetail(id: number): Promise<SysMenu> {
    const menu = await this.sysMenuRepository.findOne({
      where: { id, delete_time: 0 },
    });
    
    if (!menu) {
      throw new NotFoundException('菜单不存在');
    }
    
    return menu;
  }

  async createMenu(menuData: CreateMenuDto): Promise<SysMenu> {
    // 检查菜单名称是否已存在
    const existingMenu = await this.sysMenuRepository.findOne({
      where: { menu_name: menuData.menu_name, app_type: menuData.app_type, delete_time: 0 }, 
    });

    if (existingMenu) {
      throw new Error('菜单名称已存在');
    }

    const menu = this.sysMenuRepository.create({
      ...menuData,
      create_time: Math.floor(Date.now() / 1000),
    });

    return await this.sysMenuRepository.save(menu);
  }

  async updateMenu(id: number, updateData: UpdateMenuDto): Promise<SysMenu> {
    const menu = await this.sysMenuRepository.findOne({
      where: { id, delete_time: 0 },
    });
    
    if (!menu) {
      throw new NotFoundException('菜单不存在');
    }

    // 检查菜单名称是否已存在（排除自己）
    if (updateData.menu_name && updateData.menu_name !== menu.menu_name) {
      const existingMenu = await this.sysMenuRepository.findOne({
        where: { menu_name: updateData.menu_name, app_type: menu.app_type, delete_time: 0 }, 
      });

      if (existingMenu && existingMenu.id !== id) {
        throw new Error('菜单名称已存在');
      }
    }

    Object.assign(menu, updateData);
    return await this.sysMenuRepository.save(menu);
  }

  async deleteMenu(id: number): Promise<void> {
    const menu = await this.sysMenuRepository.findOne({
      where: { id, delete_time: 0 },
    });
    
    if (!menu) {
      throw new NotFoundException('菜单不存在');
    }

    // 检查是否有子菜单
    const childCount = await this.sysMenuRepository.count({
      where: { parent_key: menu.menu_key, delete_time: 0 },
    });

    if (childCount > 0) {
      throw new Error('存在子菜单，无法删除');
    }

    menu.delete_time = Math.floor(Date.now() / 1000);
    await this.sysMenuRepository.save(menu);
  }

  async updateMenuStatus(id: number, status: number): Promise<void> {
    const menu = await this.sysMenuRepository.findOne({
      where: { id, delete_time: 0 },
    });
    
    if (!menu) {
      throw new NotFoundException('菜单不存在');
    }

    menu.status = status;
    await this.sysMenuRepository.save(menu);
  }

  async getMenusByAppType(app_type: string): Promise<SysMenu[]> {
    return await this.sysMenuRepository.find({
      where: { app_type, status: 1, delete_time: 0 },
      order: { sort: 'DESC' },
    });
  }

  async getAllMenus(): Promise<SysMenu[]> {
    return await this.sysMenuRepository.find({
      where: { delete_time: 0 },
      order: { sort: 'DESC' },
    });
  }

  async getActiveMenus(): Promise<SysMenu[]> {
    return await this.sysMenuRepository.find({
      where: { status: 1, delete_time: 0 },
      order: { sort: 'DESC' },
    });
  }

  async getInactiveMenus(): Promise<SysMenu[]> {
    return await this.sysMenuRepository.find({
      where: { status: 0, delete_time: 0 },
      order: { sort: 'DESC' },
    });
  }

  async getMenuStats(): Promise<any> {
    const total = await this.sysMenuRepository.count({ where: { delete_time: 0 } });
    const active = await this.sysMenuRepository.count({ where: { status: 1, delete_time: 0 } });
    const inactive = await this.sysMenuRepository.count({ where: { status: 0, delete_time: 0 } });

    return {
      total,
      active,
      inactive,
    };
  }

  /**
   * 获取菜单树
   */
  async getMenuTree(appType: string): Promise<any[]> {
    const menus = await this.sysMenuRepository.find({
      where: { app_type: appType, is_del: 0 },
      order: { sort: 'ASC' },
    });
    
    return this.buildMenuTree(menus);
  }

  /**
   * 批量删除菜单
   */
  async batchDeleteMenus(menuIds: number[]): Promise<{ success: boolean; message: string }> {
    try {
      await this.sysMenuRepository.update(menuIds, {
        is_del: 1,
                  delete_time: Math.floor(Date.now() / 1000),
      });
      return { success: true, message: '批量删除成功' };
    } catch (error) {
      return { success: false, message: '批量删除失败' };
    }
  }

  /**
   * 批量更新菜单状态
   */
  async batchUpdateMenuStatus(menuIds: number[], status: number): Promise<{ success: boolean; message: string }> {
    try {
      await this.sysMenuRepository.update(menuIds, { status });
      return { success: true, message: '批量更新状态成功' };
    } catch (error) {
      return { success: false, message: '批量更新状态失败' };
    }
  }

  /**
   * 导出菜单
   */
  async exportMenus(): Promise<any[]> {
    return await this.sysMenuRepository.find({
      where: { is_del: 0 },
      order: { sort: 'ASC' },
    });
  }

  /**
   * 构建菜单树
   */
  private buildMenuTree(menus: any[], parentId: number = 0): any[] {
    const tree: any[] = [];
    
    for (const menu of menus) {
      if (menu.parent_id === parentId) {
        const children = this.buildMenuTree(menus, menu.menu_id);
        if (children.length > 0) {
          menu.children = children;
        }
        tree.push(menu);
      }
    }
    
    return tree;
  }
} 