import zoneinfo

from ..config import (
    Application,
    Array,
    Boolean,
    DevicesConfig,
    Enum,
    GroupsConfig,
    Integer,
    Object,
    String,
)


class ManySubscriptionConfig(Array):
    def __init__(
        self,
        display_name: str = "Subscription",
        *,
        description: str = "A list of channels to subscribe to.",
        **kwargs,
    ):
        super().__init__(
            display_name,
            element=SubscriptionConfig(name="dv_proc_subscription"),
            description=description,
            name="dv_proc_subscriptions",
            **kwargs,
        )


class SubscriptionConfig(String):
    def __init__(
        self,
        display_name: str = "Channel Subscription",
        *,
        description: str = "The name of the channel to subscribe to",
        name: str = "dv_proc_subscriptions",
        **kwargs,
    ):
        super().__init__(
            display_name,
            description=description,
            name=name,
            **kwargs,
        )


class ScheduleConfig(String):
    def __init__(
        self,
        display_name: str = "Schedule",
        *,
        description: str = "Specify a schedule to run this task.",
        allowed_modes: list[str] | None = None,
        **kwargs,
    ):
        allowed_modes = allowed_modes or ["cron", "rate", "disabled"]
        if len(allowed_modes) >= 3:
            format_value = "doover-schedule"
        else:
            format_value = "doover-schedule-" + "-".join(allowed_modes)
        super().__init__(
            display_name,
            description=description,
            format=format_value,
            name="dv_proc_schedules",
            **kwargs,
        )


class IngestionEndpointConfig(Object):
    cidr_ranges = Array(
        display_name="CIDR Ranges",
        element=String(
            "IP Range", description="IP Range, e.g. 1.234.56.78/24 or 110.220.120.1/32"
        ),
        description="Accepted CIDR ranges for incoming requests",
    )
    signing_key = String(
        display_name="Signing Key",
        description="Private SHA256 signing key for the request. "
        "While not recommended, this may be `None` if no signed hash verification is required.",
        default="",
    )
    signing_key_hash_header = String(
        display_name="SHA256 Hash Header",
        description="Header key for the hash of the signed payload (defaults to x-hmac-sha256 if signing_key is present)",
        default="x-hmac-sha256",
    )
    throttle = Integer(
        display_name="Throttle",
        description="The number of requests to allow per second. Due to internal limits, this cannot exceed 30.",
        default=10,
        maximum=30,
    )
    never_replace_token = Boolean(
        display_name="Never Replace Token",
        description="Enable this if the token is difficult to change and must never change. "
        "This is not recommended from a security standpoint, however may be necessary in some situations."
        "If this option is disabled and then enabled, a new token will be generated at that point.",
        default=False,
    )
    mini_token = Boolean(
        display_name="Mini Token",
        description="Enable this to generate a mini token for use with the ingestion endpoint. "
        "Mini tokens are ~70 bytes, compared with the ~900 bytes of a regular token. "
        "Generally, this is not advised as it adds complexity and latency to ingestion calls, "
        "however may be desirable in especially low-bandwidth and embedded environments. "
        "There is no security difference in the two tokens.",
        default=False,
    )

    def __init__(
        self,
        display_name: str = "Ingestion Endpoint",
        *,
        description: str = "Ingestion Endpoint configuration",
        **kwargs,
    ):
        super().__init__(
            display_name,
            description=description,
            name="dv_proc_ingestion",
            **kwargs,
        )


class ExtendedPermissionsConfig(Object):
    devices = DevicesConfig(
        description="List of devices to grant extended permissions to."
    )
    groups = GroupsConfig()
    apps_installed = Array(
        display_name="Apps Installed",
        element=Application("Application"),
        description="Permission will be given to any devices which have any of the apps listed installed.",
    )
    all_devices = Boolean(
        display_name="All Devices",
        description="Permission will be given for all devices in this organisation. This is a very far-reaching permission to grant!",
        default=False,
    )

    def __init__(self):
        super().__init__(
            "Devices",
            description="Give Permission to access devices.",
            name="dv_proc_extended_permissions",
        )


class TimezoneConfig(Enum):
    def __init__(
        self,
        display_name: str = "Timezone",
        *,
        description: str = "The timezone to use for the report.",
        default="Australia/Brisbane",
        **kwargs,
    ):
        super().__init__(
            display_name,
            choices=list(zoneinfo.available_timezones()),
            description=description,
            default=default,
            name="dv_proc_timezone",
            **kwargs,
        )


class SerialNumberConfig(String):
    def __init__(
        self,
        display_name: str = "Serial Number",
        *,
        description: str = "Device Serial Number",
        **kwargs,
    ):
        super().__init__(
            display_name,
            description=description,
            name="dv_serial_number",
            **kwargs,
        )
