import { Test } from '@nestjs/testing';
import { FamilyRecomputeService } from './family-recompute.service';
import { ProductFamiliesService } from './product-families.service';
import { OrganizeService } from './organize.service';
import { OriginGoodsService } from '../origin-goods/origin-goods.service';
import { PrismaService } from '../prisma/prisma.service';

/**
 * 整理服务（解析去运行时化后的唯一派生入口）：
 * 1) 链接级：未人工接管的 SDS 链接按名称派生 origin_good_tags（manual=false）；
 * 2) 商品级：good 标签镜像其链接的有效标签（保留非自动组人工标签）；
 * 3) 人工接管（updateTags）后自动同步不再覆盖，恢复自动（resetTags）回到派生。
 */
describe('链接级标签：派生 / 人工接管 / 商品镜像', () => {
  let recompute: FamilyRecomputeService;
  let organize: OrganizeService;
  let originGoods: OriginGoodsService;
  let prisma: PrismaService;
  const stamp = Date.now();
  const ids = {
    originGood: [] as bigint[],
    family: [] as bigint[],
    good: [] as bigint[],
    country: [] as bigint[],
    category: [] as bigint[],
    group: [] as bigint[],
    tag: [] as bigint[],
  };

  beforeAll(async () => {
    const moduleRef = await Test.createTestingModule({
      providers: [FamilyRecomputeService, ProductFamiliesService, OrganizeService, OriginGoodsService, PrismaService],
    }).compile();
    recompute = moduleRef.get(FamilyRecomputeService);
    organize = moduleRef.get(OrganizeService);
    originGoods = moduleRef.get(OriginGoodsService);
    prisma = moduleRef.get(PrismaService);
    await prisma.onModuleInit();

    ids.country.push((await prisma.country.create({ data: { countryName: `标签同步国家-${stamp}` } })).id);
    ids.category.push((await prisma.category.create({ data: { categoryName: `标签同步分类-${stamp}` } })).id);
    // 人工分组（派生规则之外，标签应保留）
    ids.group.push((await prisma.tagGroup.create({ data: { groupName: `风格${stamp}`, sortOrder: 9 } })).id);
  });

  afterAll(async () => {
    await prisma.goodTag.deleteMany({ where: { goodId: { in: ids.good } } });
    await prisma.good.deleteMany({ where: { id: { in: ids.good } } });
    await prisma.originGoodTag.deleteMany({ where: { originGoodId: { in: ids.originGood } } });
    await prisma.originGood.deleteMany({ where: { id: { in: ids.originGood } } });
    await prisma.productFamily.deleteMany({ where: { id: { in: ids.family } } });
    await prisma.tag.deleteMany({ where: { id: { in: ids.tag } } });
    await prisma.tagGroup.deleteMany({ where: { id: { in: ids.group } } });
    await prisma.country.deleteMany({ where: { id: { in: ids.country } } });
    await prisma.category.deleteMany({ where: { id: { in: ids.category } } });
    await prisma.$disconnect();
  });

  async function goodTagNames(goodId: bigint): Promise<string[]> {
    const rows = await prisma.goodTag.findMany({ where: { goodId }, include: { tag: true } });
    return rows.map((r) => r.tag.tagName);
  }

  async function linkTagNames(ogId: bigint): Promise<string[]> {
    const rows = await prisma.originGoodTag.findMany({ where: { originGoodId: ogId }, include: { tag: true } });
    return rows.map((r) => r.tag.tagName);
  }

  it('链接派生标签落在链接上，商品镜像链接标签；旧自动组标签剔除、人工分组保留', async () => {
    const styleTag = await prisma.tag.create({ data: { tagName: `潮流${stamp}`, tagGroupId: ids.group[0] } });
    ids.tag.push(styleTag.id);
    const legacyPositionTag = await prisma.tag.findFirst({
      where: { tagName: '单面印', tagGroup: { groupName: { contains: '印刷位置' } } },
    });

    const og1 = await prisma.originGood.create({
      data: {
        sdsGoodId: `tagsync-${stamp}-1`,
        goodName: `美国（包邮）180g纯棉T恤成人款-DG${stamp}-单面印花`,
        logisticsLabel: '包邮',
        craftLabel: '单面印花',
      },
    });
    const og2 = await prisma.originGood.create({
      data: {
        sdsGoodId: `tagsync-${stamp}-2`,
        goodName: `美国（不包邮光板）180GT恤成人款-JS${stamp}-不打印·美西洛杉矶二仓`,
        logisticsLabel: '不包邮光板',
        craftLabel: '不打印',
      },
    });
    ids.originGood.push(og1.id, og2.id);
    const family = await prisma.productFamily.create({
      data: { familyName: `标签同步族-${stamp}`, primaryOriginGoodId: og1.id },
    });
    ids.family.push(family.id);
    await prisma.originGood.updateMany({
      where: { id: { in: [og1.id, og2.id] } },
      data: { familyId: family.id },
    });

    const good1 = await prisma.good.create({
      data: {
        originGoodId: og1.id,
        familyId: family.id,
        countryId: ids.country[0],
        categoryId: ids.category[0],
        goodName: `标签同步商品1-${stamp}`,
      },
    });
    const good2 = await prisma.good.create({
      data: {
        originGoodId: og2.id,
        familyId: family.id,
        countryId: ids.country[0],
        categoryId: ids.category[0],
        goodName: `标签同步商品2-${stamp}`,
      },
    });
    ids.good.push(good1.id, good2.id);
    await prisma.goodTag.create({ data: { goodId: good1.id, tagId: styleTag.id } });
    if (legacyPositionTag) {
      await prisma.goodTag.create({ data: { goodId: good1.id, tagId: legacyPositionTag.id } });
    }

    const r1 = await organize.deriveFamilyTags(family.id);
    expect(r1.linksUpdated).toBe(2);
    expect(r1.goodsUpdated).toBe(2);

    // 链接级：og1 → 单面印花/烫画/包邮；og2 → 不打印（光板归并为不打印）/不包邮
    expect(await linkTagNames(og1.id)).toEqual(['包邮', '烫画', '单面印花']);
    expect(await linkTagNames(og2.id)).toEqual(['不包邮', '不打印']);

    // 商品级：镜像各自链接（+人工分组保留，旧自动组剔除）
    const names1 = await goodTagNames(good1.id);
    expect(names1).toEqual(expect.arrayContaining(['包邮', '烫画', '单面印花', `潮流${stamp}`]));
    expect(names1).not.toContain('单面印');
    const names2 = await goodTagNames(good2.id);
    expect(names2).toEqual(['不包邮', '不打印']);
    expect(names2).not.toContain('光板');
    expect(names2).not.toContain('烫画');

    // 幂等
    const r2 = await organize.deriveFamilyTags(family.id);
    expect(r2.linksUpdated).toBe(0);
    expect(r2.goodsUpdated).toBe(0);
  });

  it('人工接管链接标签后自动同步不覆盖，商品跟随；恢复自动回到派生', async () => {
    const og = await prisma.originGood.create({
      data: {
        sdsGoodId: `tagsync-manual-${stamp}`,
        goodName: `美国（包邮）卫衣-DGM${stamp}-单面印花`,
        logisticsLabel: '包邮',
        craftLabel: '单面印花',
      },
    });
    ids.originGood.push(og.id);
    const family = await prisma.productFamily.create({
      data: { familyName: `人工标签族-${stamp}`, primaryOriginGoodId: og.id },
    });
    ids.family.push(family.id);
    await prisma.originGood.update({ where: { id: og.id }, data: { familyId: family.id } });
    const good = await prisma.good.create({
      data: {
        originGoodId: og.id,
        familyId: family.id,
        countryId: ids.country[0],
        categoryId: ids.category[0],
        goodName: `人工标签商品-${stamp}`,
      },
    });
    ids.good.push(good.id);

    await organize.deriveFamilyTags(family.id);
    expect(await linkTagNames(og.id)).toEqual(['包邮', '烫画', '单面印花']);

    // 人工接管：解析错了（实际是直喷）→ 改成 直喷
    const zhpena = await prisma.tag.findFirst({ where: { tagName: '直喷' } });
    const baoyou = await prisma.tag.findFirst({ where: { tagName: '包邮' } });
    const result = await originGoods.updateTags(og.id, [Number(zhpena!.id), Number(baoyou!.id)]);
    expect(result.tagsManual).toBe(true);
    expect(result.tags.map((t) => t.tagName)).toEqual(['包邮', '直喷']);
    expect(result.tags.every((t) => t.manual)).toBe(true);
    // 商品镜像跟随人工修正
    expect(await goodTagNames(good.id)).toEqual(['包邮', '直喷']);

    // 再次族同步：人工行不被覆盖
    await organize.deriveFamilyTags(family.id);
    expect(await linkTagNames(og.id)).toEqual(['包邮', '直喷']);
    expect(await goodTagNames(good.id)).toEqual(['包邮', '直喷']);

    // 恢复自动 → 回到名称派生结果
    const reset = await originGoods.resetTags(og.id);
    expect(reset.tagsManual).toBe(false);
    expect(reset.tags.map((t) => t.tagName)).toEqual(['包邮', '烫画', '单面印花']);
    expect(await goodTagNames(good.id)).toEqual(['包邮', '烫画', '单面印花']);
  });

  it('自定义来源链接不派生标签，仅镜像人工配置', async () => {
    const ogCustom = await prisma.originGood.create({
      data: {
        source: 'CUSTOM',
        sdsGoodId: `tagsync-custom-${stamp}`,
        goodName: `自定义包邮T恤${stamp}`,
      },
    });
    ids.originGood.push(ogCustom.id);
    const family = await prisma.productFamily.create({
      data: { familyName: `自定义标签族-${stamp}`, primaryOriginGoodId: ogCustom.id },
    });
    ids.family.push(family.id);
    await prisma.originGood.update({ where: { id: ogCustom.id }, data: { familyId: family.id } });
    const good = await prisma.good.create({
      data: {
        originGoodId: ogCustom.id,
        familyId: family.id,
        countryId: ids.country[0],
        categoryId: ids.category[0],
        goodName: `自定义标签商品-${stamp}`,
      },
    });
    ids.good.push(good.id);

    const r = await organize.deriveFamilyTags(family.id);
    expect(r.linksUpdated).toBe(0);
    expect(await goodTagNames(good.id)).toEqual([]);

    // 自定义链接同样可人工配置标签
    const baoyou = await prisma.tag.findFirst({ where: { tagName: '包邮' } });
    await originGoods.updateTags(ogCustom.id, [Number(baoyou!.id)]);
    expect(await goodTagNames(good.id)).toEqual(['包邮']);
  });

  it('族重算不解析不触碰标签：上游改名后重算，标签/矩阵维度保持不变（防倒灌）', async () => {
    const og = await prisma.originGood.create({
      data: {
        sdsGoodId: `tagsync-nodrift-${stamp}`,
        goodName: `美国（包邮）防倒灌T恤-ND${stamp}-单面印花`,
      },
    });
    ids.originGood.push(og.id);
    await prisma.originGoodVariant.create({
      data: {
        originGoodId: og.id,
        sdsVariantId: `nd-v-${stamp}`,
        sku: `ND${stamp}`,
        sizeName: 'S',
        price: 21,
      },
    });
    const family = await prisma.productFamily.create({
      data: { familyName: `防倒灌族-${stamp}`, primaryOriginGoodId: og.id },
    });
    ids.family.push(family.id);
    await prisma.originGood.update({ where: { id: og.id }, data: { familyId: family.id } });

    // 整理派生一次 → 标签就位，矩阵有格子
    await organize.deriveFamilyTags(family.id);
    await recompute.recomputeFamily(family.id);
    const tagsBefore = await linkTagNames(og.id);
    expect(tagsBefore).toEqual(['包邮', '烫画', '单面印花']);
    let fam = await prisma.productFamily.findUniqueOrThrow({ where: { id: family.id } });
    expect((fam.priceMatrix as any).rows).toHaveLength(1);

    // 模拟上游改名（同步镜像只更新 goodName）→ 仅重算、不整理
    await prisma.originGood.update({
      where: { id: og.id },
      data: { goodName: '美国（包邮）防倒灌T恤-ND0000-直喷双面' },
    });
    await recompute.recomputeFamily(family.id);

    // 标签与矩阵维度保持派生时的快照，不随名称漂移
    expect(await linkTagNames(og.id)).toEqual(tagsBefore);
    fam = await prisma.productFamily.findUniqueOrThrow({ where: { id: family.id } });
    const row = (fam.priceMatrix as any).rows[0];
    expect(row.printCount).toBe('单面印花');
    expect(row.craft).toBe('烫画');

    // 显式整理后才按新名称刷新
    await organize.deriveFamilyTags(family.id);
    const refreshed = await linkTagNames(og.id);
    expect(refreshed).toHaveLength(3);
    expect(refreshed).toEqual(expect.arrayContaining(['包邮', '双面印花', '直喷']));
  });
});
