import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateProductDto } from './dto/create-product.dto';
import { UpdateProductDto } from './dto/update-product.dto';

type ProductOverviewItem = {
  id: string;
  name: string;
  description?: string;
  createdAt?: string;
  updatedAt?: string;
  projects?: { id: string; name: string; description?: string; createdAt?: string }[];
  versions?: { id: string; name: string; releaseDate?: string | null; createdAt?: string }[];
  _count?: { requirements?: number; projects?: number; versions?: number };
};

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

  create(dto: CreateProductDto) {
    return this.prisma.product.create({ data: dto });
  }

  async findAll() {
    const overview = await this.getAppDataOverview();
    if (overview) {
      return overview.map((product) => {
        const normalized = this.normalizeOverviewProduct(product);
        const { projects: _projects, versions: _versions, ...rest } = normalized;
        return rest;
      });
    }

    return this.prisma.product.findMany({
      orderBy: { createdAt: 'desc' },
      include: {
        _count: { select: { requirements: true, projects: true } },
      },
    });
  }

  async findAllWithChildren() {
    const overview = await this.getAppDataOverview();
    if (overview) {
      return overview.map((product) => this.normalizeOverviewProduct(product));
    }

    return this.prisma.product.findMany({
      orderBy: { createdAt: 'desc' },
      include: {
        projects: {
          orderBy: { createdAt: 'desc' },
          select: { id: true, name: true, description: true, createdAt: true },
        },
        versions: {
          orderBy: { createdAt: 'desc' },
          select: { id: true, name: true, releaseDate: true, createdAt: true },
        },
        _count: { select: { requirements: true, projects: true, versions: true } },
      },
    });
  }

  async findOne(id: string) {
    const overview = await this.getAppDataOverview();
    if (overview) {
      const product = overview.find((item) => item.id === id);
      if (!product) throw new NotFoundException('产品不存在');
      return {
        ...this.normalizeOverviewProduct(product),
        requirements: [],
      };
    }

    const product = await this.prisma.product.findUnique({
      where: { id },
      include: {
        requirements: { orderBy: { createdAt: 'desc' } },
        versions: { orderBy: { createdAt: 'desc' } },
        _count: { select: { projects: true } },
      },
    });
    if (!product) throw new NotFoundException('产品不存在');
    return product;
  }

  async update(id: string, dto: UpdateProductDto) {
    await this.ensureExists(id);
    return this.prisma.product.update({ where: { id }, data: dto });
  }

  async remove(id: string) {
    await this.ensureExists(id);
    return this.prisma.product.delete({ where: { id } });
  }

  private async ensureExists(id: string) {
    const exists = await this.prisma.product.findUnique({ where: { id } });
    if (!exists) throw new NotFoundException('产品不存在');
  }

  private async getAppDataOverview(): Promise<ProductOverviewItem[] | null> {
    const row = await this.prisma.appData.findUnique({
      where: { key: 'products-overview' },
    });
    if (!Array.isArray(row?.value)) return null;
    return row.value as unknown as ProductOverviewItem[];
  }

  private normalizeOverviewProduct(product: ProductOverviewItem) {
    const projects = product.projects ?? [];
    const versions = product.versions ?? [];
    return {
      ...product,
      description: product.description ?? '',
      projects,
      versions,
      _count: {
        requirements: product._count?.requirements ?? 0,
        projects: projects.length,
        versions: versions.length,
      },
    };
  }
}
