"""Tests for chest deflection, femur load, tibia index, 3ms clip, viscous criterion."""

import numpy as np
import pytest

from impakt.criteria import chest_deflection, clip_3ms, femur_load, tibia_index, viscous_criterion


class TestChestDeflection:
    def test_basic(self, chest_deflection_channel):
        result = chest_deflection(channel=chest_deflection_channel)
        assert result.criterion == "Chest Deflection"
        assert result.unit == "mm"
        assert 30.0 < result.value < 40.0  # ~35mm in fixture

    def test_peak_time(self, chest_deflection_channel):
        result = chest_deflection(channel=chest_deflection_channel)
        assert result.time_of_peak is not None
        assert 0.0 < result.time_of_peak < 0.1


class TestClip3ms:
    def test_basic(self, head_accel_x):
        result = clip_3ms(head_accel_x)
        assert result.criterion == "3ms Clip"
        assert result.value > 0

    def test_body_region(self, head_accel_x):
        result = clip_3ms(head_accel_x)
        assert result.body_region == "Chest"


class TestFemurLoad:
    def test_single_channel(self, femur_left_channel):
        result = femur_load(channel=femur_left_channel, side="left")
        assert result.criterion == "Femur Load Left"
        assert result.unit == "kN"
        assert result.value > 0

    def test_peak_time(self, femur_left_channel):
        result = femur_load(channel=femur_left_channel, side="left")
        assert result.time_of_peak is not None


class TestTibiaIndex:
    def test_with_all_components(self, time_array, sample_rate):
        from impakt.channel.code import ChannelCode
        from impakt.channel.model import Channel

        t = time_array
        fz = np.zeros_like(t)
        mx = np.zeros_like(t)
        my = np.zeros_like(t)
        mask = (t >= 0.02) & (t <= 0.08)
        fz[mask] = -5000 * np.sin(np.pi * (t[mask] - 0.02) / 0.06)
        mx[mask] = 50 * np.sin(np.pi * (t[mask] - 0.02) / 0.06)
        my[mask] = 80 * np.sin(np.pi * (t[mask] - 0.02) / 0.06)

        fz_ch = Channel(
            name="TIBFZ",
            code=ChannelCode.parse("TIBFZ"),
            data=fz,
            time=t,
            unit="N",
            sample_rate=sample_rate,
        )
        mx_ch = Channel(
            name="TIBMX",
            code=ChannelCode.parse("TIBMX"),
            data=mx,
            time=t,
            unit="N·m",
            sample_rate=sample_rate,
        )
        my_ch = Channel(
            name="TIBMY",
            code=ChannelCode.parse("TIBMY"),
            data=my,
            time=t,
            unit="N·m",
            sample_rate=sample_rate,
        )

        result = tibia_index(fz_channel=fz_ch, mx_channel=mx_ch, my_channel=my_ch)
        assert result.value > 0


class TestViscousCriterion:
    def test_basic(self, chest_deflection_channel):
        result = viscous_criterion(channel=chest_deflection_channel)
        assert result.criterion == "Viscous Criterion"
        assert result.unit == "m/s"
        assert result.value >= 0
