"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from __future__ import annotations
from datetime import datetime
from pydantic import model_serializer
from tofupilot.v2.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from typing import Any, Dict, List, Literal, Optional, Union
from typing_extensions import NotRequired, TypeAliasType, TypedDict


RunCreateOutcome = Literal["PASS", "FAIL", "ERROR", "TIMEOUT", "ABORTED"]
r"""Overall test result. Use PASS when test succeeds, FAIL when test fails but script execution completed successfully, ERROR when script execution fails, TIMEOUT when test exceeds time limit, ABORTED for manual script interruption."""

RunCreatePhaseOutcome = Literal["PASS", "FAIL", "SKIP", "ERROR"]
r"""Overall result of the phase execution. Use PASS when phase succeeds, FAIL when phase fails but execution completed successfully, ERROR when phase execution fails, SKIP when phase was not executed."""

MeasurementOutcome = Literal["PASS", "FAIL", "UNSET"]
r"""Result of the measurement validation. Use PASS when measurement meets all criteria, FAIL when measurement is outside acceptable limits or validation fails, UNSET when no validation was performed."""

MeasuredValue2TypedDict = TypeAliasType(
    "MeasuredValue2TypedDict", Union[Dict[str, Any], List[Any]]
)


MeasuredValue2 = TypeAliasType("MeasuredValue2", Union[Dict[str, Any], List[Any]])


MeasuredValue1TypedDict = TypeAliasType(
    "MeasuredValue1TypedDict",
    Union[float, str, bool, List[List[float]], MeasuredValue2TypedDict],
)
r"""The actual value captured during measurement. Can be numeric, string, boolean, multi-dimensional array, or JSON object. The measurement type will be determined automatically by the server based on the measured_value type. If no value is provided, an empty measurement will be created."""


MeasuredValue1 = TypeAliasType(
    "MeasuredValue1", Union[float, str, bool, List[List[float]], MeasuredValue2]
)
r"""The actual value captured during measurement. Can be numeric, string, boolean, multi-dimensional array, or JSON object. The measurement type will be determined automatically by the server based on the measured_value type. If no value is provided, an empty measurement will be created."""


RunCreateUnitsTypedDict = TypeAliasType(
    "RunCreateUnitsTypedDict", Union[str, List[str]]
)
r"""Units of measurement for display purposes. Can be a single string for simple measurements or an array of strings for multi-dimensional measurements. Units help interpret and display the measured values correctly."""


RunCreateUnits = TypeAliasType("RunCreateUnits", Union[str, List[str]])
r"""Units of measurement for display purposes. Can be a single string for simple measurements or an array of strings for multi-dimensional measurements. Units help interpret and display the measured values correctly."""


class RunCreateMeasurementTypedDict(TypedDict):
    name: str
    r"""Name identifier for the measurement. Each measurement should have a descriptive name that identifies the specific data point being captured. Analytics at measurement level are computed using this name as unique identifier."""
    outcome: MeasurementOutcome
    r"""Result of the measurement validation. Use PASS when measurement meets all criteria, FAIL when measurement is outside acceptable limits or validation fails, UNSET when no validation was performed."""
    measured_value: NotRequired[Nullable[MeasuredValue1TypedDict]]
    r"""The actual value captured during measurement. Can be numeric, string, boolean, multi-dimensional array, or JSON object. The measurement type will be determined automatically by the server based on the measured_value type. If no value is provided, an empty measurement will be created."""
    units: NotRequired[Nullable[RunCreateUnitsTypedDict]]
    r"""Units of measurement for display purposes. Can be a single string for simple measurements or an array of strings for multi-dimensional measurements. Units help interpret and display the measured values correctly."""
    lower_limit: NotRequired[float]
    r"""Lower specification limit for numeric measurements. Used for limit checking and Cpk calculations. Must be specified manually when calling the API directly. During OpenHTF import, may be automatically extracted from validators field."""
    upper_limit: NotRequired[float]
    r"""Upper specification limit for numeric measurements. Used for limit checking and Cpk calculations. Must be specified manually when calling the API directly. During OpenHTF import, may be automatically extracted from validators field."""
    validators: NotRequired[Nullable[List[str]]]
    r"""Array of validation rules as string expressions for display purposes. Common formats include range checks (3.0 <= x <= 3.6), equality (x == 5), comparisons (x > 10), percentage tolerance (x is within 5% of 100), and regex patterns."""
    docstring: NotRequired[Nullable[str]]
    r"""Additional notes or documentation about this measurement."""


class RunCreateMeasurement(BaseModel):
    name: str
    r"""Name identifier for the measurement. Each measurement should have a descriptive name that identifies the specific data point being captured. Analytics at measurement level are computed using this name as unique identifier."""

    outcome: MeasurementOutcome
    r"""Result of the measurement validation. Use PASS when measurement meets all criteria, FAIL when measurement is outside acceptable limits or validation fails, UNSET when no validation was performed."""

    measured_value: OptionalNullable[MeasuredValue1] = UNSET
    r"""The actual value captured during measurement. Can be numeric, string, boolean, multi-dimensional array, or JSON object. The measurement type will be determined automatically by the server based on the measured_value type. If no value is provided, an empty measurement will be created."""

    units: OptionalNullable[RunCreateUnits] = UNSET
    r"""Units of measurement for display purposes. Can be a single string for simple measurements or an array of strings for multi-dimensional measurements. Units help interpret and display the measured values correctly."""

    lower_limit: Optional[float] = None
    r"""Lower specification limit for numeric measurements. Used for limit checking and Cpk calculations. Must be specified manually when calling the API directly. During OpenHTF import, may be automatically extracted from validators field."""

    upper_limit: Optional[float] = None
    r"""Upper specification limit for numeric measurements. Used for limit checking and Cpk calculations. Must be specified manually when calling the API directly. During OpenHTF import, may be automatically extracted from validators field."""

    validators: OptionalNullable[List[str]] = UNSET
    r"""Array of validation rules as string expressions for display purposes. Common formats include range checks (3.0 <= x <= 3.6), equality (x == 5), comparisons (x > 10), percentage tolerance (x is within 5% of 100), and regex patterns."""

    docstring: OptionalNullable[str] = UNSET
    r"""Additional notes or documentation about this measurement."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "measured_value",
            "units",
            "lower_limit",
            "upper_limit",
            "validators",
            "docstring",
        ]
        nullable_fields = ["measured_value", "units", "validators", "docstring"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class RunCreatePhaseTypedDict(TypedDict):
    name: str
    r"""Name identifier for the test phase. Each phase should have a descriptive name that identifies the specific stage of testing being performed. Analytics at phase level are computed using this name as unique identifier."""
    outcome: RunCreatePhaseOutcome
    r"""Overall result of the phase execution. Use PASS when phase succeeds, FAIL when phase fails but execution completed successfully, ERROR when phase execution fails, SKIP when phase was not executed."""
    started_at: datetime
    r"""ISO 8601 timestamp when the phase execution began."""
    ended_at: datetime
    r"""ISO 8601 timestamp when the phase execution completed."""
    docstring: NotRequired[Nullable[str]]
    r"""Additional notes or documentation about this test phase."""
    measurements: NotRequired[Nullable[List[RunCreateMeasurementTypedDict]]]
    r"""Array of measurements collected during this phase. Each measurement captures specific test data points with values, limits, and validation results. If no measurements are specified, the phase will be created without measurement data."""


class RunCreatePhase(BaseModel):
    name: str
    r"""Name identifier for the test phase. Each phase should have a descriptive name that identifies the specific stage of testing being performed. Analytics at phase level are computed using this name as unique identifier."""

    outcome: RunCreatePhaseOutcome
    r"""Overall result of the phase execution. Use PASS when phase succeeds, FAIL when phase fails but execution completed successfully, ERROR when phase execution fails, SKIP when phase was not executed."""

    started_at: datetime
    r"""ISO 8601 timestamp when the phase execution began."""

    ended_at: datetime
    r"""ISO 8601 timestamp when the phase execution completed."""

    docstring: OptionalNullable[str] = UNSET
    r"""Additional notes or documentation about this test phase."""

    measurements: OptionalNullable[List[RunCreateMeasurement]] = UNSET
    r"""Array of measurements collected during this phase. Each measurement captures specific test data points with values, limits, and validation results. If no measurements are specified, the phase will be created without measurement data."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["docstring", "measurements"]
        nullable_fields = ["docstring", "measurements"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


RunCreateLevel = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
r"""Severity level of the log message following standard system logging levels. Use DEBUG for detailed diagnostic information, INFO for general execution information, WARNING for unexpected events or potential issues, ERROR for serious problems that prevented function execution, CRITICAL for severe errors that may cause program termination."""


class RunCreateLogTypedDict(TypedDict):
    level: RunCreateLevel
    r"""Severity level of the log message following standard system logging levels. Use DEBUG for detailed diagnostic information, INFO for general execution information, WARNING for unexpected events or potential issues, ERROR for serious problems that prevented function execution, CRITICAL for severe errors that may cause program termination."""
    timestamp: datetime
    r"""ISO 8601 timestamp when the log message was generated."""
    message: str
    r"""Content of the log message. Contains the actual log text describing the event, error, or information being logged."""
    source_file: str
    r"""Name or path of the source file where the log message originated. Helps identify the code location that generated the log entry."""
    line_number: float
    r"""Line number in the source file where the log message was generated. Used for debugging and tracing log origins."""


class RunCreateLog(BaseModel):
    level: RunCreateLevel
    r"""Severity level of the log message following standard system logging levels. Use DEBUG for detailed diagnostic information, INFO for general execution information, WARNING for unexpected events or potential issues, ERROR for serious problems that prevented function execution, CRITICAL for severe errors that may cause program termination."""

    timestamp: datetime
    r"""ISO 8601 timestamp when the log message was generated."""

    message: str
    r"""Content of the log message. Contains the actual log text describing the event, error, or information being logged."""

    source_file: str
    r"""Name or path of the source file where the log message originated. Helps identify the code location that generated the log entry."""

    line_number: float
    r"""Line number in the source file where the log message was generated. Used for debugging and tracing log origins."""


class RunCreateRequestTypedDict(TypedDict):
    outcome: RunCreateOutcome
    r"""Overall test result. Use PASS when test succeeds, FAIL when test fails but script execution completed successfully, ERROR when script execution fails, TIMEOUT when test exceeds time limit, ABORTED for manual script interruption."""
    procedure_id: str
    r"""Procedure ID. Create the procedure in the app first, then find the auto-generated ID on the procedure page."""
    started_at: datetime
    r"""ISO 8601 timestamp when the test run began execution. This timestamp will be used to track when the test execution started and for historical analysis of test runs. A separate created_at timestamp is stored internally server side to track upload date."""
    ended_at: datetime
    r"""ISO 8601 timestamp when the test run finished execution."""
    serial_number: str
    r"""Unique serial number of the unit under test. Matched case-insensitively. If no unit with this serial number exists, one will be created."""
    procedure_version: NotRequired[Nullable[str]]
    r"""Specific version of the test procedure used for the run. Matched case-insensitively. If none exist, a procedure with this procedure version will be created. If no procedure version is specified, the run will not be linked to any specific version."""
    operated_by: NotRequired[str]
    r"""Email address of the operator who executed the test run. The operator must exist as a user in the system. The run will be linked to this user to track who performed the test."""
    part_number: NotRequired[str]
    r"""Component part number for the unit. Matched case-insensitively. This field is required if the part number cannot be extracted from the serial number (as set in the settings). This field takes precedence over extraction from serial number. A component with the provided or extracted part number will be created if one does not exist."""
    revision_number: NotRequired[str]
    r"""Hardware revision identifier for the unit. Matched case-insensitively. If none exist, a revision with this number will be created. If no revision is specified, the unit will be linked to the default revision of the part number."""
    batch_number: NotRequired[str]
    r"""Production batch identifier for grouping units manufactured together. Matched case-insensitively. If none exist, a batch with this batch number will be created. If no batch number is specified, the unit will not be linked to any batch."""
    sub_units: NotRequired[List[str]]
    r"""Array of sub-unit serial numbers that are part of this main unit. Matched case-insensitively. Each sub-unit must already exist and will be linked as a sub-component of the main unit under test. If no sub-units are specified, the unit will be created without sub-unit relationships."""
    docstring: NotRequired[str]
    r"""Additional notes or documentation about this test run."""
    phases: NotRequired[List[RunCreatePhaseTypedDict]]
    r"""Array of test phases with measurements and results. Each phase represents a distinct stage of the test execution with timing information, outcome status, and optional measurements. If no phases are specified, the run will be created without phase-level organization of test data."""
    logs: NotRequired[List[RunCreateLogTypedDict]]
    r"""Array of log messages generated during the test execution. Each log entry captures events, errors, and diagnostic information with severity levels and source code references. If no logs are specified, the run will be created without log entries."""


class RunCreateRequest(BaseModel):
    outcome: RunCreateOutcome
    r"""Overall test result. Use PASS when test succeeds, FAIL when test fails but script execution completed successfully, ERROR when script execution fails, TIMEOUT when test exceeds time limit, ABORTED for manual script interruption."""

    procedure_id: str
    r"""Procedure ID. Create the procedure in the app first, then find the auto-generated ID on the procedure page."""

    started_at: datetime
    r"""ISO 8601 timestamp when the test run began execution. This timestamp will be used to track when the test execution started and for historical analysis of test runs. A separate created_at timestamp is stored internally server side to track upload date."""

    ended_at: datetime
    r"""ISO 8601 timestamp when the test run finished execution."""

    serial_number: str
    r"""Unique serial number of the unit under test. Matched case-insensitively. If no unit with this serial number exists, one will be created."""

    procedure_version: OptionalNullable[str] = UNSET
    r"""Specific version of the test procedure used for the run. Matched case-insensitively. If none exist, a procedure with this procedure version will be created. If no procedure version is specified, the run will not be linked to any specific version."""

    operated_by: Optional[str] = None
    r"""Email address of the operator who executed the test run. The operator must exist as a user in the system. The run will be linked to this user to track who performed the test."""

    part_number: Optional[str] = None
    r"""Component part number for the unit. Matched case-insensitively. This field is required if the part number cannot be extracted from the serial number (as set in the settings). This field takes precedence over extraction from serial number. A component with the provided or extracted part number will be created if one does not exist."""

    revision_number: Optional[str] = None
    r"""Hardware revision identifier for the unit. Matched case-insensitively. If none exist, a revision with this number will be created. If no revision is specified, the unit will be linked to the default revision of the part number."""

    batch_number: Optional[str] = None
    r"""Production batch identifier for grouping units manufactured together. Matched case-insensitively. If none exist, a batch with this batch number will be created. If no batch number is specified, the unit will not be linked to any batch."""

    sub_units: Optional[List[str]] = None
    r"""Array of sub-unit serial numbers that are part of this main unit. Matched case-insensitively. Each sub-unit must already exist and will be linked as a sub-component of the main unit under test. If no sub-units are specified, the unit will be created without sub-unit relationships."""

    docstring: Optional[str] = None
    r"""Additional notes or documentation about this test run."""

    phases: Optional[List[RunCreatePhase]] = None
    r"""Array of test phases with measurements and results. Each phase represents a distinct stage of the test execution with timing information, outcome status, and optional measurements. If no phases are specified, the run will be created without phase-level organization of test data."""

    logs: Optional[List[RunCreateLog]] = None
    r"""Array of log messages generated during the test execution. Each log entry captures events, errors, and diagnostic information with severity levels and source code references. If no logs are specified, the run will be created without log entries."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "procedure_version",
            "operated_by",
            "part_number",
            "revision_number",
            "batch_number",
            "sub_units",
            "docstring",
            "phases",
            "logs",
        ]
        nullable_fields = ["procedure_version"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class RunCreateResponseTypedDict(TypedDict):
    r"""Run created successfully"""

    id: str
    r"""Unique identifier of the created run."""


class RunCreateResponse(BaseModel):
    r"""Run created successfully"""

    id: str
    r"""Unique identifier of the created run."""
