import { Injectable, NotFoundException } from '@nestjs/common';
import { Prisma, PartnerRole } from '@prisma/client';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { SkipAssertAccess } from '@common/decorators/skip-assert-access.decorator';

export interface PartnerInput {
  code?: string;
  name: string;
  role: PartnerRole;
  countryCode?: string;
  currencyCode?: string;
  enabled?: boolean;
}

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

  async list(query: { search?: string; role?: PartnerRole; enabledOnly?: boolean }) {
    const where: Prisma.PartnerWhereInput = { deletedAt: null };
    if (query.enabledOnly) where.enabled = true;
    if (query.role) where.role = query.role;
    if (query.search) {
      where.OR = [
        { code: { contains: query.search, mode: 'insensitive' } },
        { name: { contains: query.search, mode: 'insensitive' } },
      ];
    }
    return this.prisma.partner.findMany({ where, orderBy: { code: 'asc' } });
  }

  async findOne(id: string) {
    const p = await this.prisma.partner.findFirst({
      where: { id, deletedAt: null },
      include: { contacts: true },
    });
    if (!p) throw new NotFoundException(`Partner ${id} not found`);
    return p;
  }

  async create(input: PartnerInput, userId: string, organizationId: string) {
    const code = input.code ?? `P-${Date.now()}`;
    return this.prisma.partner.create({
      data: {
        code,
        name: input.name,
        role: input.role,
        countryCode: input.countryCode,
        currencyCode: input.currencyCode,
        enabled: input.enabled ?? true,
        organizationId,
        createdById: userId,
      },
    });
  }

  @SkipAssertAccess('上方 findOne({ id }) 已抓到对象')
  async update(id: string, input: Partial<PartnerInput>) {
    await this.findOne(id);
    return this.prisma.partner.update({ where: { id }, data: input });
  }

  @SkipAssertAccess('updateMany 单 round-trip')
  async softDelete(id: string) {
    const r = await this.prisma.partner.updateMany({
      where: { id, deletedAt: null },
      data: { deletedAt: new Date() },
    });
    if (r.count === 0) throw new NotFoundException(`Partner ${id} not found`);
    return { id, deleted: true };
  }

  @SkipAssertAccess('updateMany 单 round-trip')
  async restore(id: string) {
    const r = await this.prisma.partner.updateMany({
      where: { id, deletedAt: { not: null } },
      data: { deletedAt: null },
    });
    if (r.count === 0) throw new NotFoundException(`Partner ${id} not found or not deleted`);
    return this.findOne(id);
  }
}
