import { Injectable } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service.js';
import { TranslationType } from '../../generated/prisma/client.js';

export interface EquipmentSearchParams {
  query?: string;
  category?: string;
  subcategory?: string;
  minLevel?: number;
  maxLevel?: number;
  traits?: string[];
  page?: number;
  limit?: number;
}

export interface EquipmentSearchResult {
  items: any[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
  categories: string[];
}

@Injectable()
export class EquipmentService {
  constructor(private readonly prisma: PrismaService) {}

  async search(params: EquipmentSearchParams): Promise<EquipmentSearchResult> {
    const {
      query,
      category,
      subcategory,
      minLevel,
      maxLevel,
      traits,
      page = 1,
      limit = 50,
    } = params;

    // Build where clause
    const where: any = {};

    // Text search on name
    if (query && query.trim()) {
      where.name = {
        contains: query.trim(),
        mode: 'insensitive',
      };
    }

    // Category filter
    if (category) {
      where.itemCategory = category;
    }

    // Subcategory filter
    if (subcategory) {
      where.itemSubcategory = subcategory;
    }

    // Level range
    if (minLevel !== undefined || maxLevel !== undefined) {
      where.level = {};
      if (minLevel !== undefined) {
        where.level.gte = minLevel;
      }
      if (maxLevel !== undefined) {
        where.level.lte = maxLevel;
      }
    }

    // Traits filter (has any of the specified traits)
    if (traits && traits.length > 0) {
      where.traits = {
        hasSome: traits,
      };
    }

    // Get total count
    const total = await this.prisma.equipment.count({ where });

    // Get paginated results
    const items = await this.prisma.equipment.findMany({
      where,
      orderBy: [
        { level: 'asc' },
        { name: 'asc' },
      ],
      skip: (page - 1) * limit,
      take: limit,
    });

    // Get all unique categories for filter UI
    const categoriesResult = await this.prisma.equipment.groupBy({
      by: ['itemCategory'],
      orderBy: { itemCategory: 'asc' },
    });
    const categories = categoriesResult.map(c => c.itemCategory);

    return {
      items,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
      categories,
    };
  }

  async getById(id: string) {
    const equipment = await this.prisma.equipment.findUnique({
      where: { id },
    });

    if (!equipment) return null;

    // Hole die Übersetzung aus dem Cache (falls vorhanden)
    const translation = await this.prisma.translation.findUnique({
      where: {
        type_englishName: {
          type: TranslationType.EQUIPMENT,
          englishName: equipment.name,
        },
      },
    });

    // Erweitere das Equipment um übersetzte Felder
    return {
      ...equipment,
      nameGerman: translation?.germanName || null,
      summaryGerman: translation?.germanDescription || null,
    };
  }

  async getByName(name: string) {
    return this.prisma.equipment.findUnique({
      where: { name },
    });
  }

  async getCategories(): Promise<string[]> {
    const result = await this.prisma.equipment.groupBy({
      by: ['itemCategory'],
      orderBy: { itemCategory: 'asc' },
    });
    return result.map(c => c.itemCategory);
  }

  async getSubcategories(category: string): Promise<string[]> {
    const result = await this.prisma.equipment.groupBy({
      by: ['itemSubcategory'],
      where: {
        itemCategory: category,
        itemSubcategory: { not: null },
      },
      orderBy: { itemSubcategory: 'asc' },
    });
    return result.map(c => c.itemSubcategory).filter((s): s is string => s !== null);
  }

  async getWeapons(params: Omit<EquipmentSearchParams, 'category'>) {
    return this.search({ ...params, category: 'Weapons' });
  }

  async getArmor(params: Omit<EquipmentSearchParams, 'category'>) {
    return this.search({ ...params, category: 'Armor' });
  }

  async getConsumables(params: Omit<EquipmentSearchParams, 'category'>) {
    return this.search({ ...params, category: 'Consumables' });
  }
}
