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

from __future__ import annotations
from enum import Enum
from gusto_embedded.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
import pydantic
from pydantic import model_serializer
from typing import List, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


class ValueTiersTypedDict(TypedDict):
    r"""A single tier of a tiered matching scheme."""

    rate: NotRequired[str]
    r"""The percentage of employee deduction within this tier the company contribution will match."""
    threshold: NotRequired[str]
    r"""The percentage threshold at which this tier ends (inclusive).

    For example, a value of \"5\" means the company contribution will match employee deductions from the previous tier's threshold up to and including 5% of payroll.

    If this is the first tier, a value of \"5\" means the company contribution will match employee deductions from 0% up to and including 5% of payroll.
    """
    threshold_delta: NotRequired[str]
    r"""The step up difference between this tier's threshold and the previous tier's threshold. In the first tier, this is equivalent to threshold."""


class ValueTiers(BaseModel):
    r"""A single tier of a tiered matching scheme."""

    rate: Optional[str] = None
    r"""The percentage of employee deduction within this tier the company contribution will match."""

    threshold: Optional[str] = None
    r"""The percentage threshold at which this tier ends (inclusive).

    For example, a value of \"5\" means the company contribution will match employee deductions from the previous tier's threshold up to and including 5% of payroll.

    If this is the first tier, a value of \"5\" means the company contribution will match employee deductions from 0% up to and including 5% of payroll.
    """

    threshold_delta: Optional[str] = None
    r"""The step up difference between this tier's threshold and the previous tier's threshold. In the first tier, this is equivalent to threshold."""


class Value2TypedDict(TypedDict):
    tiers: NotRequired[List[ValueTiersTypedDict]]


class Value2(BaseModel):
    tiers: Optional[List[ValueTiers]] = None


EmployeeBenefitForCompanyBenefitValueTypedDict = TypeAliasType(
    "EmployeeBenefitForCompanyBenefitValueTypedDict", Union[Value2TypedDict, str]
)
r"""For the `amount` and `percentage` contribution types, the value of the corresponding amount or percentage.

For the `tiered` contribution type, an array of tiers.
"""


EmployeeBenefitForCompanyBenefitValue = TypeAliasType(
    "EmployeeBenefitForCompanyBenefitValue", Union[Value2, str]
)
r"""For the `amount` and `percentage` contribution types, the value of the corresponding amount or percentage.

For the `tiered` contribution type, an array of tiers.
"""


class EmployeeBenefitForCompanyBenefitContributionTypedDict(TypedDict):
    r"""An object representing the type and value of the company contribution."""

    type: NotRequired[str]
    r"""The company contribution scheme.

    \"amount\": The company contributes a fixed amount per payroll. If elective is true, the contribution is matching, dollar-for-dollar.

    \"percentage\": The company contributes a percentage of the payroll amount per payroll period. If elective is true, the contribution is matching, dollar-for-dollar.

    \"tiered\": The company contribution varies according to the size of the employee deduction.
    """
    value: NotRequired[EmployeeBenefitForCompanyBenefitValueTypedDict]
    r"""For the `amount` and `percentage` contribution types, the value of the corresponding amount or percentage.

    For the `tiered` contribution type, an array of tiers.
    """


class EmployeeBenefitForCompanyBenefitContribution(BaseModel):
    r"""An object representing the type and value of the company contribution."""

    type: Optional[str] = None
    r"""The company contribution scheme.

    \"amount\": The company contributes a fixed amount per payroll. If elective is true, the contribution is matching, dollar-for-dollar.

    \"percentage\": The company contributes a percentage of the payroll amount per payroll period. If elective is true, the contribution is matching, dollar-for-dollar.

    \"tiered\": The company contribution varies according to the size of the employee deduction.
    """

    value: Optional[EmployeeBenefitForCompanyBenefitValue] = None
    r"""For the `amount` and `percentage` contribution types, the value of the corresponding amount or percentage.

    For the `tiered` contribution type, an array of tiers.
    """


class EmployeeBenefitForCompanyBenefitDeductionReducesTaxableIncome(str, Enum):
    r"""Whether the employee deduction reduces taxable income or not. Only valid for Group Term Life benefits. Note: when the value is not \"unset\", coverage amount and coverage salary multiplier are ignored."""

    UNSET = "unset"
    REDUCES_TAXABLE_INCOME = "reduces_taxable_income"
    DOES_NOT_REDUCE_TAXABLE_INCOME = "does_not_reduce_taxable_income"


class EmployeeBenefitForCompanyBenefitTypedDict(TypedDict):
    r"""The representation of an employee benefit for a company benefit."""

    employee_uuid: str
    r"""The UUID of the employee to which the benefit belongs."""
    version: NotRequired[str]
    r"""The current version of the object. See the [versioning guide](https://docs.gusto.com/embedded-payroll/docs/idempotency) for information on how to use this field."""
    active: NotRequired[bool]
    r"""Whether the employee benefit is active."""
    employee_deduction: NotRequired[str]
    r"""The amount to be deducted, per pay period, from the employee's pay."""
    deduct_as_percentage: NotRequired[bool]
    r"""Whether the employee deduction amount should be treated as a percentage to be deducted from each payroll."""
    employee_deduction_annual_maximum: NotRequired[Nullable[str]]
    r"""The maximum employee deduction amount per year. A null value signifies no limit."""
    contribution: NotRequired[EmployeeBenefitForCompanyBenefitContributionTypedDict]
    r"""An object representing the type and value of the company contribution."""
    elective: NotRequired[bool]
    r"""Whether the company contribution is elective (aka matching). For \"tiered\" contribution types, this is always true."""
    company_contribution_annual_maximum: NotRequired[Nullable[str]]
    r"""The maximum company contribution amount per year. A null value signifies no limit."""
    limit_option: NotRequired[Nullable[str]]
    r"""Some benefits require additional information to determine their limit.

    `Family` and `Individual` are applicable to HSA benefit.

    `Joint Filing or Single` and `Married and Filing Separately` are applicable to Dependent Care FSA benefit.
    """
    catch_up: NotRequired[bool]
    r"""Whether the employee should use a benefit’s \"catch up\" rate. Only Roth 401k and 401k benefits use this value for employees over 50."""
    retirement_loan_identifier: NotRequired[str]
    r"""Identifier for a 401(k) loan assigned by the 401(k) provider"""
    coverage_amount: NotRequired[Nullable[str]]
    r"""The amount that the employee is insured for. Note: company contribution cannot be present if coverage amount is set."""
    deduction_reduces_taxable_income: NotRequired[
        Nullable[EmployeeBenefitForCompanyBenefitDeductionReducesTaxableIncome]
    ]
    r"""Whether the employee deduction reduces taxable income or not. Only valid for Group Term Life benefits. Note: when the value is not \"unset\", coverage amount and coverage salary multiplier are ignored."""
    coverage_salary_multiplier: NotRequired[str]
    r"""The coverage amount as a multiple of the employee’s salary. Only applicable for Group Term Life benefits. Note: cannot be set if coverage amount is also set."""
    company_contribution: NotRequired[str]
    r"""The amount to be paid, per pay period, by the company. This field will not appear for tiered contribution types."""
    contribute_as_percentage: NotRequired[bool]
    r"""Whether the company_contribution value should be treated as a percentage to be added to each payroll. This field will not appear for tiered contribution types."""


class EmployeeBenefitForCompanyBenefit(BaseModel):
    r"""The representation of an employee benefit for a company benefit."""

    employee_uuid: str
    r"""The UUID of the employee to which the benefit belongs."""

    version: Optional[str] = None
    r"""The current version of the object. See the [versioning guide](https://docs.gusto.com/embedded-payroll/docs/idempotency) for information on how to use this field."""

    active: Optional[bool] = True
    r"""Whether the employee benefit is active."""

    employee_deduction: Optional[str] = "0.00"
    r"""The amount to be deducted, per pay period, from the employee's pay."""

    deduct_as_percentage: Optional[bool] = False
    r"""Whether the employee deduction amount should be treated as a percentage to be deducted from each payroll."""

    employee_deduction_annual_maximum: OptionalNullable[str] = UNSET
    r"""The maximum employee deduction amount per year. A null value signifies no limit."""

    contribution: Optional[EmployeeBenefitForCompanyBenefitContribution] = None
    r"""An object representing the type and value of the company contribution."""

    elective: Optional[bool] = False
    r"""Whether the company contribution is elective (aka matching). For \"tiered\" contribution types, this is always true."""

    company_contribution_annual_maximum: OptionalNullable[str] = UNSET
    r"""The maximum company contribution amount per year. A null value signifies no limit."""

    limit_option: OptionalNullable[str] = UNSET
    r"""Some benefits require additional information to determine their limit.

    `Family` and `Individual` are applicable to HSA benefit.

    `Joint Filing or Single` and `Married and Filing Separately` are applicable to Dependent Care FSA benefit.
    """

    catch_up: Optional[bool] = False
    r"""Whether the employee should use a benefit’s \"catch up\" rate. Only Roth 401k and 401k benefits use this value for employees over 50."""

    retirement_loan_identifier: Optional[str] = None
    r"""Identifier for a 401(k) loan assigned by the 401(k) provider"""

    coverage_amount: OptionalNullable[str] = UNSET
    r"""The amount that the employee is insured for. Note: company contribution cannot be present if coverage amount is set."""

    deduction_reduces_taxable_income: OptionalNullable[
        EmployeeBenefitForCompanyBenefitDeductionReducesTaxableIncome
    ] = EmployeeBenefitForCompanyBenefitDeductionReducesTaxableIncome.UNSET
    r"""Whether the employee deduction reduces taxable income or not. Only valid for Group Term Life benefits. Note: when the value is not \"unset\", coverage amount and coverage salary multiplier are ignored."""

    coverage_salary_multiplier: Optional[str] = "0.00"
    r"""The coverage amount as a multiple of the employee’s salary. Only applicable for Group Term Life benefits. Note: cannot be set if coverage amount is also set."""

    company_contribution: Annotated[
        Optional[str],
        pydantic.Field(
            deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible."
        ),
    ] = "0.00"
    r"""The amount to be paid, per pay period, by the company. This field will not appear for tiered contribution types."""

    contribute_as_percentage: Annotated[
        Optional[bool],
        pydantic.Field(
            deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible."
        ),
    ] = False
    r"""Whether the company_contribution value should be treated as a percentage to be added to each payroll. This field will not appear for tiered contribution types."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "version",
            "active",
            "employee_deduction",
            "deduct_as_percentage",
            "employee_deduction_annual_maximum",
            "contribution",
            "elective",
            "company_contribution_annual_maximum",
            "limit_option",
            "catch_up",
            "retirement_loan_identifier",
            "coverage_amount",
            "deduction_reduces_taxable_income",
            "coverage_salary_multiplier",
            "company_contribution",
            "contribute_as_percentage",
        ]
        nullable_fields = [
            "employee_deduction_annual_maximum",
            "company_contribution_annual_maximum",
            "limit_option",
            "coverage_amount",
            "deduction_reduces_taxable_income",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in 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
