import assert from 'node:assert/strict';
import test from 'node:test';

import { minDistSqEffectToPoint, pickEraseTargetId } from './effectEraserHitTest';
import type { EffectInstance } from './types/effects';

const base = { seed: 1, createdAtMs: 0 };

void test('pickEraseTargetId: fire/rain/water — кистью, не целиком', () => {
  const fire: EffectInstance = {
    ...base,
    id: 'f1',
    type: 'fire',
    points: [{ x: 0.5, y: 0.5, tMs: 0 }],
    radiusN: 0.05,
    opacity: 1,
    lifetimeMs: null,
  };
  const id = pickEraseTargetId([fire], { x: 0.51, y: 0.5 }, 0.05);
  assert.equal(id, null);
});

void test('pickEraseTargetId: вода — кистью, не целиком', () => {
  const water: EffectInstance = {
    ...base,
    id: 'w1',
    type: 'water',
    points: [{ x: 0.4, y: 0.55, tMs: 0 }],
    radiusN: 0.06,
    opacity: 0.5,
    lifetimeMs: null,
  };
  const id = pickEraseTargetId([water], { x: 0.41, y: 0.55 }, 0.05);
  assert.equal(id, null);
});

void test('pickEraseTargetId: тьма как заморозка — точка удара', () => {
  const darkness: EffectInstance = {
    ...base,
    id: 'd1',
    type: 'darkness',
    at: { x: 0.4, y: 0.55 },
    intensity: 1,
    lifetimeMs: 820,
  };
  const id = pickEraseTargetId([darkness], { x: 0.41, y: 0.55 }, 0.05);
  assert.equal(id, 'd1');
});

void test('pickEraseTargetId: shadow с учётом inst.radiusN', () => {
  const shadow: EffectInstance = {
    ...base,
    id: 's1',
    type: 'shadow',
    at: { x: 0.5, y: 0.5 },
    radiusN: 0.08,
    opacity: 1,
    lifetimeMs: null,
  };
  const id = pickEraseTargetId([shadow], { x: 0.59, y: 0.5 }, 0.02);
  assert.equal(id, 's1');
});

void test('minDistSqEffectToPoint: молния — расстояние до отрезка', () => {
  const bolt: EffectInstance = {
    ...base,
    id: 'L1',
    type: 'lightning',
    start: { x: 0, y: 0 },
    end: { x: 1, y: 0 },
    widthN: 0.02,
    intensity: 1,
    lifetimeMs: 500,
  };
  const mid = minDistSqEffectToPoint(bolt, { x: 0.5, y: 0.1 });
  assert.ok(Math.abs(mid - 0.01) < 1e-9);
  const end = minDistSqEffectToPoint(bolt, { x: 1, y: 0 });
  assert.equal(end, 0);
});

void test('minDistSqEffectToPoint: луч света — как у молнии, отрезок', () => {
  const beam: EffectInstance = {
    ...base,
    id: 'S1',
    type: 'sunbeam',
    start: { x: 0.5, y: 0 },
    end: { x: 0.5, y: 0.8 },
    widthN: 0.04,
    intensity: 1,
    lifetimeMs: 220,
  };
  const onBeam = minDistSqEffectToPoint(beam, { x: 0.5, y: 0.4 });
  assert.equal(onBeam, 0);
  const aside = minDistSqEffectToPoint(beam, { x: 0.52, y: 0.4 });
  assert.ok(aside > 0 && aside < 0.01);
});

void test('pickEraseTargetId: scorch с учётом inst.radiusN', () => {
  const sc: EffectInstance = {
    ...base,
    id: 's1',
    type: 'scorch',
    at: { x: 0.5, y: 0.5 },
    radiusN: 0.08,
    opacity: 1,
    lifetimeMs: 1000,
  };
  const id = pickEraseTargetId([sc], { x: 0.59, y: 0.5 }, 0.02);
  assert.equal(id, 's1');
});

void test('pickEraseTargetId: яд с учётом inst.radiusN', () => {
  const pc: EffectInstance = {
    ...base,
    id: 'pc',
    type: 'poisonCloud',
    at: { x: 0.5, y: 0.5 },
    radiusN: 0.08,
    intensity: 1,
    lifetimeMs: 1000,
  };
  const id = pickEraseTargetId([pc], { x: 0.59, y: 0.5 }, 0.02);
  assert.equal(id, 'pc');
});
