/**
 * CM-9: proxy service — per-entity CRUD/upsert, tenant guard, and the
 * yacht → interest → client resolution precedence.
 */
import { describe, it, expect } from 'vitest';

import { createInterest } from '@/lib/services/interests.service';
import {
  clearProxy,
  getProxy,
  resolveEffectiveProxy,
  setProxy,
} from '@/lib/services/proxies.service';
import { makeAuditMeta, makeClient, makePort, makeYacht } from '../helpers/factories';

describe('proxies.service (CM-9)', () => {
  it('sets, reads, upserts and clears a client proxy', async () => {
    const port = await makePort();
    const meta = makeAuditMeta({ portId: port.id });
    const client = await makeClient({ portId: port.id });

    expect(await getProxy(port.id, 'client', client.id)).toBeNull();

    const p = await setProxy(
      port.id,
      'client',
      client.id,
      { name: 'Broker Bob', email: 'bob@example.com' },
      meta,
    );
    expect(p.name).toBe('Broker Bob');
    expect(p.email).toBe('bob@example.com');

    // Upsert: one proxy per entity — setting again updates the same row.
    const p2 = await setProxy(
      port.id,
      'client',
      client.id,
      { name: 'Broker Bob', email: '', phone: '+100' },
      meta,
    );
    expect(p2.id).toBe(p.id);
    expect(p2.email).toBeNull(); // empty string normalised to null
    expect(p2.phone).toBe('+100');

    await clearProxy(port.id, 'client', client.id, meta);
    expect(await getProxy(port.id, 'client', client.id)).toBeNull();
  });

  it('rejects an entity from a foreign port', async () => {
    const portA = await makePort();
    const portB = await makePort();
    const meta = makeAuditMeta({ portId: portA.id });
    const foreign = await makeClient({ portId: portB.id });
    await expect(setProxy(portA.id, 'client', foreign.id, { name: 'X' }, meta)).rejects.toThrow(
      /not found in this port/,
    );
  });

  it('resolves the most specific proxy: yacht → interest → client', async () => {
    const port = await makePort();
    const meta = makeAuditMeta({ portId: port.id });
    const client = await makeClient({ portId: port.id });
    const interest = await createInterest(
      port.id,
      { clientId: client.id, pipelineStage: 'enquiry', tagIds: [], reminderEnabled: false },
      meta,
    );
    const yacht = await makeYacht({ portId: port.id, ownerType: 'client', ownerId: client.id });

    await setProxy(port.id, 'client', client.id, { name: 'Client PoC' }, meta);
    await setProxy(port.id, 'interest', interest.id, { name: 'Deal PoC' }, meta);
    await setProxy(port.id, 'yacht', yacht.id, { name: 'Vessel PoC' }, meta);

    const ctx = {
      portId: port.id,
      clientId: client.id,
      interestId: interest.id,
      yachtId: yacht.id,
    };
    expect((await resolveEffectiveProxy(ctx))?.source).toBe('yacht');

    await clearProxy(port.id, 'yacht', yacht.id, meta);
    expect((await resolveEffectiveProxy(ctx))?.source).toBe('interest');

    await clearProxy(port.id, 'interest', interest.id, meta);
    const eff = await resolveEffectiveProxy(ctx);
    expect(eff?.source).toBe('client');
    expect(eff?.proxy.name).toBe('Client PoC');

    await clearProxy(port.id, 'client', client.id, meta);
    expect(await resolveEffectiveProxy(ctx)).toBeNull();
  });
});
