import { describe, it, expect } from 'vitest';
import {
    classifyPointer,
    detectInputCapabilities,
    getGestureThresholds,
    getHitTargetSize,
    HIT_TARGET_SIZES,
} from '../core/input-classifier';
import type { ClassifiedPointer, InputSource } from '../core/input-classifier';

// =============================================================================
// classifyPointer
// =============================================================================

describe('classifyPointer', () => {
    function createMockPointerEvent(overrides: Partial<PointerEvent> = {}): PointerEvent {
        return {
            pointerType: 'mouse',
            pointerId: 1,
            pressure: 0.5,
            tiltX: 0,
            tiltY: 0,
            isPrimary: true,
            ...overrides,
        } as PointerEvent;
    }

    it('classifies mouse pointer', () => {
        const event = createMockPointerEvent({ pointerType: 'mouse' });
        const result = classifyPointer(event);
        expect(result.source).toBe('mouse');
        expect(result.pointerId).toBe(1);
    });

    it('classifies touch pointer as finger', () => {
        const event = createMockPointerEvent({ pointerType: 'touch', pointerId: 2 });
        const result = classifyPointer(event);
        expect(result.source).toBe('finger');
        expect(result.pointerId).toBe(2);
    });

    it('classifies pen pointer as pencil', () => {
        const event = createMockPointerEvent({
            pointerType: 'pen',
            pointerId: 3,
            pressure: 0.75,
            tiltX: 15,
            tiltY: -10,
        });
        const result = classifyPointer(event);
        expect(result.source).toBe('pencil');
        expect(result.pressure).toBe(0.75);
        expect(result.tiltX).toBe(15);
        expect(result.tiltY).toBe(-10);
    });

    it('falls back to mouse for unknown pointer types', () => {
        const event = createMockPointerEvent({ pointerType: 'unknown-future-device' } as any);
        const result = classifyPointer(event);
        expect(result.source).toBe('mouse');
    });

    it('preserves isPrimary flag', () => {
        const primary = createMockPointerEvent({ isPrimary: true });
        const secondary = createMockPointerEvent({ isPrimary: false });
        expect(classifyPointer(primary).isPrimary).toBe(true);
        expect(classifyPointer(secondary).isPrimary).toBe(false);
    });
});

// =============================================================================
// getGestureThresholds
// =============================================================================

describe('getGestureThresholds', () => {
    it('finger has largest thresholds', () => {
        const finger = getGestureThresholds('finger');
        const mouse = getGestureThresholds('mouse');
        const pencil = getGestureThresholds('pencil');
        expect(finger.dragThreshold).toBeGreaterThan(mouse.dragThreshold);
        expect(finger.dragThreshold).toBeGreaterThan(pencil.dragThreshold);
    });

    it('pencil has smallest drag threshold', () => {
        const pencil = getGestureThresholds('pencil');
        expect(pencil.dragThreshold).toBeLessThanOrEqual(3);
    });

    it('mouse has no long-press (uses right-click)', () => {
        const mouse = getGestureThresholds('mouse');
        expect(mouse.longPressDuration).toBe(0);
    });

    it('finger and pencil have long-press durations', () => {
        const finger = getGestureThresholds('finger');
        const pencil = getGestureThresholds('pencil');
        expect(finger.longPressDuration).toBeGreaterThan(0);
        expect(pencil.longPressDuration).toBeGreaterThan(0);
    });
});

// =============================================================================
// getHitTargetSize
// =============================================================================

describe('getHitTargetSize', () => {
    it('finger target meets Apple HIG minimum (44pt)', () => {
        expect(getHitTargetSize('finger')).toBeGreaterThanOrEqual(44);
    });

    it('pencil target is smaller than finger', () => {
        expect(getHitTargetSize('pencil')).toBeLessThan(getHitTargetSize('finger'));
    });

    it('mouse target is smallest', () => {
        expect(getHitTargetSize('mouse')).toBeLessThan(getHitTargetSize('pencil'));
    });
});

// =============================================================================
// detectInputCapabilities
// =============================================================================

describe('detectInputCapabilities', () => {
    it('detects capabilities without crashing', () => {
        const caps = detectInputCapabilities();
        expect(caps).toHaveProperty('hasTouch');
        expect(caps).toHaveProperty('hasStylus');
        expect(caps).toHaveProperty('hasMouse');
        expect(caps).toHaveProperty('hasCoarsePointer');
    });

    it('stylus defaults to false (detected on first pen event)', () => {
        const caps = detectInputCapabilities();
        expect(caps.hasStylus).toBe(false);
    });
});
