/**
 * interests.service tenant-FK validation tests.
 *
 * Covers the security fix that pins clientId/berthId/yachtId on interest
 * create/update + linkBerth to the caller's port. Without these guards a
 * port-A caller could splice a port-B FK onto their own interest and
 * surface foreign-tenant data through the join surfaces in getInterestById.
 */
import { describe, it, expect, beforeAll } from 'vitest';

describe('interests.service - port-scope FK validation', () => {
  let createInterest: typeof import('@/lib/services/interests.service').createInterest;
  let updateInterest: typeof import('@/lib/services/interests.service').updateInterest;
  let linkBerth: typeof import('@/lib/services/interests.service').linkBerth;

  let makePort: typeof import('../helpers/factories').makePort;
  let makeClient: typeof import('../helpers/factories').makeClient;
  let makeBerth: typeof import('../helpers/factories').makeBerth;
  let makeYacht: typeof import('../helpers/factories').makeYacht;
  let makeAuditMeta: typeof import('../helpers/factories').makeAuditMeta;

  beforeAll(async () => {
    const svc = await import('@/lib/services/interests.service');
    createInterest = svc.createInterest;
    updateInterest = svc.updateInterest;
    linkBerth = svc.linkBerth;

    const factories = await import('../helpers/factories');
    makePort = factories.makePort;
    makeClient = factories.makeClient;
    makeBerth = factories.makeBerth;
    makeYacht = factories.makeYacht;
    makeAuditMeta = factories.makeAuditMeta;
  });

  it('rejects createInterest with a foreign-port clientId', async () => {
    const portA = await makePort();
    const portB = await makePort();
    const foreignClient = await makeClient({ portId: portB.id });

    await expect(
      createInterest(
        portA.id,
        {
          clientId: foreignClient.id,
          pipelineStage: 'enquiry',
          tagIds: [],
          reminderEnabled: false,
        },
        makeAuditMeta({ portId: portA.id }),
      ),
    ).rejects.toThrow(/clientId not found in this port/);
  });

  it('rejects createInterest with a foreign-port berthId', async () => {
    const portA = await makePort();
    const portB = await makePort();
    const localClient = await makeClient({ portId: portA.id });
    const foreignBerth = await makeBerth({ portId: portB.id });

    await expect(
      createInterest(
        portA.id,
        {
          clientId: localClient.id,
          berthId: foreignBerth.id,
          pipelineStage: 'enquiry',
          tagIds: [],
          reminderEnabled: false,
        },
        makeAuditMeta({ portId: portA.id }),
      ),
    ).rejects.toThrow(/berthId not found in this port/);
  });

  it('rejects createInterest with a foreign-port yachtId', async () => {
    const portA = await makePort();
    const portB = await makePort();
    const localClient = await makeClient({ portId: portA.id });
    const foreignClient = await makeClient({ portId: portB.id });
    const foreignYacht = await makeYacht({
      portId: portB.id,
      ownerType: 'client',
      ownerId: foreignClient.id,
    });

    await expect(
      createInterest(
        portA.id,
        {
          clientId: localClient.id,
          yachtId: foreignYacht.id,
          pipelineStage: 'enquiry',
          tagIds: [],
          reminderEnabled: false,
        },
        makeAuditMeta({ portId: portA.id }),
      ),
    ).rejects.toThrow(/yachtId not found in this port/);
  });

  it('rejects updateInterest swapping in a foreign-port berthId', async () => {
    const portA = await makePort();
    const portB = await makePort();
    const localClient = await makeClient({ portId: portA.id });
    const foreignBerth = await makeBerth({ portId: portB.id });

    const interest = await createInterest(
      portA.id,
      {
        clientId: localClient.id,
        pipelineStage: 'enquiry',
        tagIds: [],
        reminderEnabled: false,
      },
      makeAuditMeta({ portId: portA.id }),
    );

    await expect(
      updateInterest(
        interest.id,
        portA.id,
        { berthId: foreignBerth.id },
        makeAuditMeta({ portId: portA.id }),
      ),
    ).rejects.toThrow(/berthId not found in this port/);
  });

  it('rejects linkBerth with a foreign-port berthId', async () => {
    const portA = await makePort();
    const portB = await makePort();
    const localClient = await makeClient({ portId: portA.id });
    const foreignBerth = await makeBerth({ portId: portB.id });

    const interest = await createInterest(
      portA.id,
      {
        clientId: localClient.id,
        pipelineStage: 'enquiry',
        tagIds: [],
        reminderEnabled: false,
      },
      makeAuditMeta({ portId: portA.id }),
    );

    await expect(
      linkBerth(interest.id, portA.id, foreignBerth.id, makeAuditMeta({ portId: portA.id })),
    ).rejects.toThrow(/berthId not found in this port/);
  });
});
