import time

import pytest
import serial

from ecu_framework.power import OwonPSU, SerialParams
from ecu_framework.config import EcuTestConfig


pytestmark = [pytest.mark.hardware]


def test_owon_psu_idn_and_optional_set(config: EcuTestConfig, rp):
    """
    Title: Owon PSU - IDN, Output Status, Set/Measure Verification

    Description:
        Validates serial SCPI control of an Owon PSU: IDN retrieval, output status query,
        and optional set/measure cycle using values from central configuration.

    Test Steps:
    1. Load PSU config from EcuTestConfig.power_supply
    2. Open serial connection and query *IDN?
    3. Query output status (output?) and record initial state
    4. If configured, set voltage/current, enable output briefly, measure V/I, then disable output
    5. Record IDN, output status before/after, set values, and measured values in the report

    Expected Result:
        *IDN? returns a non-empty string (containing idn_substr if configured), serial operations succeed,
        and, when enabled, the output toggles on then off with measurements returned.
    """
    psu_cfg = config.power_supply
    if not psu_cfg.enabled:
        pytest.skip("Power supply tests disabled in config.power_supply.enabled")
    if not psu_cfg.port:
        pytest.skip("No power supply 'port' configured (config.power_supply.port)")

    # Serial params (with sensible defaults via central config)
    baud = int(psu_cfg.baudrate)
    timeout = float(psu_cfg.timeout)
    parity = psu_cfg.parity or "N"
    stopbits = psu_cfg.stopbits or 1
    xonxoff = bool(psu_cfg.xonxoff)
    rtscts = bool(psu_cfg.rtscts)
    dsrdtr = bool(psu_cfg.dsrdtr)
    eol = psu_cfg.eol or "\n"

    ps = SerialParams(
        baudrate=baud,
        timeout=timeout,
        parity={"N": serial.PARITY_NONE, "E": serial.PARITY_EVEN, "O": serial.PARITY_ODD}.get(str(parity).upper(), serial.PARITY_NONE),
        stopbits={1: serial.STOPBITS_ONE, 2: serial.STOPBITS_TWO}.get(int(float(stopbits)), serial.STOPBITS_ONE),
        xonxoff=xonxoff,
        rtscts=rtscts,
        dsrdtr=dsrdtr,
    )

    want_substr = psu_cfg.idn_substr
    do_set = bool(psu_cfg.do_set)
    set_v = float(psu_cfg.set_voltage)
    set_i = float(psu_cfg.set_current)

    port = str(psu_cfg.port).strip()

    with OwonPSU(port, ps, eol=eol) as psu:
        # Step 2: IDN
        idn = psu.idn()
        rp("psu_idn", idn)
        print(f"PSU IDN: {idn}")
        assert isinstance(idn, str)
        assert idn != "", "*IDN? returned empty response"
        if want_substr:
            assert str(want_substr).lower() in idn.lower(), f"IDN does not contain expected substring: {want_substr}. Got: {idn}"

        # Step 3: Output status before
        out_before = psu.output_status()
        rp("output_status_before", str(out_before))
        print(f"Output status (before): {out_before}")

        if do_set:
            # Step 4: Set and measure
            rp("set_voltage", set_v)
            rp("set_current", set_i)
            print(f"Setting: voltage={set_v}V, current={set_i}A")

            psu.set_voltage(1, set_v)
            psu.set_current(1, set_i)
            psu.set_output(True)
            time.sleep(1.0)  # allow settling

            try:
                mv = psu.measure_voltage()
                mi = psu.measure_current()
                rp("measured_voltage", mv)
                rp("measured_current", mi)
                print(f"Measured: voltage={mv}V, current={mi}A")
            finally:
                psu.set_output(False)

            out_after = psu.output_status()
            rp("output_status_after", str(out_after))
            print(f"Output status (after): {out_after}")
