/**
 * Integration test: berth maintenance-log service (add / get / update / delete).
 *
 * The schema + add/get already existed; this covers the new update + delete
 * paths and the tenant guard (an entry can only be reached through its own
 * berth + port). Runs against the real test DB.
 */

import { beforeAll, describe, expect, it } from 'vitest';

import { db } from '@/lib/db';
import { berthMaintenanceLog } from '@/lib/db/schema/berths';
import { eq } from 'drizzle-orm';

let svc: typeof import('@/lib/services/berths.service');
let makePort: typeof import('../helpers/factories').makePort;
let makeBerth: typeof import('../helpers/factories').makeBerth;
let makeAuditMeta: typeof import('../helpers/factories').makeAuditMeta;

beforeAll(async () => {
  svc = await import('@/lib/services/berths.service');
  const f = await import('../helpers/factories');
  makePort = f.makePort;
  makeBerth = f.makeBerth;
  makeAuditMeta = f.makeAuditMeta;
});

describe('berth maintenance log', () => {
  async function setup() {
    const port = await makePort();
    const berth = await makeBerth({ portId: port.id });
    const meta = makeAuditMeta({ portId: port.id });
    return { port, berth, meta };
  }

  it('adds, lists (newest first), updates, and deletes an entry', async () => {
    const { port, berth, meta } = await setup();

    const created = await svc.addMaintenanceLog(
      berth.id,
      port.id,
      {
        category: 'repair',
        description: 'Replaced cleat bolt',
        cost: 120.5,
        costCurrency: 'EUR',
        responsibleParty: 'Dockside Ltd',
        performedDate: '2026-05-10',
      },
      meta,
    );
    expect(created.category).toBe('repair');
    expect(created.cost).toBe('120.5');

    // A second, more recent entry to assert ordering.
    await svc.addMaintenanceLog(
      berth.id,
      port.id,
      { category: 'inspection', description: 'Annual check', performedDate: '2026-05-20' },
      meta,
    );

    const list = await svc.getMaintenanceLogs(berth.id, port.id);
    expect(list).toHaveLength(2);
    // Newest performedDate first.
    expect(list[0]!.performedDate).toBe('2026-05-20');
    expect(list[1]!.performedDate).toBe('2026-05-10');

    const updated = await svc.updateMaintenanceLog(
      berth.id,
      created.id,
      port.id,
      { description: 'Replaced cleat bolt + washer', cost: null },
      meta,
    );
    expect(updated.description).toBe('Replaced cleat bolt + washer');
    // cost cleared to null
    expect(updated.cost).toBeNull();

    await svc.deleteMaintenanceLog(berth.id, created.id, port.id, meta);
    const afterDelete = await db
      .select()
      .from(berthMaintenanceLog)
      .where(eq(berthMaintenanceLog.id, created.id));
    expect(afterDelete).toHaveLength(0);

    const remaining = await svc.getMaintenanceLogs(berth.id, port.id);
    expect(remaining).toHaveLength(1);
    expect(remaining[0]!.category).toBe('inspection');
  });

  it('refuses to update or delete an entry through a different port (tenant guard)', async () => {
    const { port, berth, meta } = await setup();
    const otherPort = await makePort();

    const entry = await svc.addMaintenanceLog(
      berth.id,
      port.id,
      { category: 'routine', description: 'Pressure wash', performedDate: '2026-05-15' },
      meta,
    );

    await expect(
      svc.updateMaintenanceLog(berth.id, entry.id, otherPort.id, { description: 'hijack' }, meta),
    ).rejects.toThrow();

    await expect(
      svc.deleteMaintenanceLog(berth.id, entry.id, otherPort.id, meta),
    ).rejects.toThrow();

    // Untouched.
    const [row] = await db
      .select()
      .from(berthMaintenanceLog)
      .where(eq(berthMaintenanceLog.id, entry.id));
    expect(row!.description).toBe('Pressure wash');
  });
});
