"""
Support to interface with Alexa Devices.

SPDX-License-Identifier: Apache-2.0

For more details about this platform, please refer to the documentation at
https://community.home-assistant.io/t/echo-devices-alexa-as-media-player-testers-needed/58639
"""

from __future__ import annotations

from datetime import timedelta

from homeassistant.const import (
    CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
    CONCENTRATION_PARTS_PER_MILLION,
    PERCENTAGE,
)

PROJECT_URL = "https://github.com/alandtse/alexa_media_player/"
ISSUE_URL = f"{PROJECT_URL}issues"
NOTIFY_URL = f"{PROJECT_URL}wiki/Configuration%3A-Notification-Component#use-the-notifyalexa_media-service"

DOMAIN = "alexa_media"
DATA_ALEXAMEDIA = "alexa_media"

PLAY_SCAN_INTERVAL = 20
SCAN_INTERVAL = timedelta(seconds=60)
MIN_TIME_BETWEEN_SCANS = SCAN_INTERVAL
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1)

ALEXA_COMPONENTS = [
    "media_player",
]
DEPENDENT_ALEXA_COMPONENTS = [
    "notify",
    "switch",
    "sensor",
    "alarm_control_panel",
    "light",
    "binary_sensor",
]

HTTP_COOKIE_HEADER = "# HTTP Cookie File"
CONF_ACCOUNTS = "accounts"
CONF_DEBUG = "debug"
CONF_HASS_URL = "hass_url"
CONF_INCLUDE_DEVICES = "include_devices"
CONF_EXCLUDE_DEVICES = "exclude_devices"
CONF_QUEUE_DELAY = "queue_delay"
CONF_PUBLIC_URL = "public_url"
CONF_EXTENDED_ENTITY_DISCOVERY = "extended_entity_discovery"
CONF_SECURITYCODE = "securitycode"
CONF_OTPSECRET = "otp_secret"
CONF_PROXY = "proxy"
CONF_PROXY_WARNING = "proxy_warning"
CONF_SCAN_INTERVAL = (
    "scan_interval"  # local definition; HA's CONF_SCAN_INTERVAL is deprecated
)
CONF_TOTP_REGISTER = "registered"
CONF_OAUTH = "oauth"
DATA_LISTENER = "listener"

EXCEPTION_TEMPLATE = "An exception of type {0} occurred. Arguments:\n{1!r}"

DEFAULT_DEBUG = False
DEFAULT_EXTENDED_ENTITY_DISCOVERY = False
DEFAULT_HASS_URL = "http://homeassistant.local:8123"
DEFAULT_PUBLIC_URL = ""
DEFAULT_QUEUE_DELAY = 1.5
DEFAULT_SCAN_INTERVAL = 60

EPOCH_MS_THRESHOLD = 10_000_000_000

# Service name constants used by services.py SERVICE_DEFS
SERVICE_UPDATE_LAST_CALLED = "update_last_called"
SERVICE_RESTORE_VOLUME = "restore_volume"
SERVICE_GET_HISTORY_RECORDS = "get_history_records"
SERVICE_FORCE_LOGOUT = "force_logout"
SERVICE_ENABLE_NETWORK_DISCOVERY = "enable_network_discovery"

# Backoff durations for the last-called probe worker
LAST_CALLED_429_BACKOFF_INITIAL_S = 30.0
LAST_CALLED_429_BACKOFF_MAX_S = 15 * 60.0
LAST_CALLED_CONN_BACKOFF_S = 10.0
LAST_CALLED_LOGIN_BACKOFF_S = 30.0

# Tuning constants for the per-account last-called probe worker
LAST_CALLED_DEBOUNCE_S = 3.5  # coalesce bursty pushes, but stay snappy
LAST_CALLED_RETRY_DELAY_S = 4.0  # wider retry cadence for delayed routine history
LAST_CALLED_RETRY_LIMIT = 2  # total attempts = 1 + retries (3 attempts)
LAST_CALLED_STALE_FUDGE_MS = 5_000  # allow some clock/ordering jitter
LAST_CALLED_SUCCESS_PACE_S = 4.0  # post-success pacing to avoid hammering
LAST_CALLED_LOOKBACK_MS = 60_000
LAST_CALLED_ITEMS = 10
LAST_CALLED_COALESCE_WINDOW_MS = 2000

# Tuning constants for notification retries
NOTIFICATION_COOLDOWN = 60
NOTIFY_REFRESH_BACKOFF = 15.0
NOTIFY_REFRESH_MAX_RETRIES = 3

# push-health magic numbers
HTTP2_ERROR_THRESHOLD = 5
LAST_PUSH_INACTIVITY_SECONDS = 600.0
LAST_PING_MAX_AGE_SECONDS = 900.0

RECURRING_PATTERN = {
    None: "Never Repeat",
    "P1D": "Every day",
    "P1M": "Every month",
    "XXXX-WE": "Weekends",
    "XXXX-WD": "Weekdays",
    "XXXX-WXX-1": "Every Monday",
    "XXXX-WXX-2": "Every Tuesday",
    "XXXX-WXX-3": "Every Wednesday",
    "XXXX-WXX-4": "Every Thursday",
    "XXXX-WXX-5": "Every Friday",
    "XXXX-WXX-6": "Every Saturday",
    "XXXX-WXX-7": "Every Sunday",
}

RECURRING_DAY = {
    "MO": 1,
    "TU": 2,
    "WE": 3,
    "TH": 4,
    "FR": 5,
    "SA": 6,
    "SU": 7,
}
RECURRING_PATTERN_ISO_SET = {
    None: {},
    "P1D": {1, 2, 3, 4, 5, 6, 7},
    "XXXX-WE": {6, 7},
    "XXXX-WD": {1, 2, 3, 4, 5},
    "XXXX-WXX-1": {1},
    "XXXX-WXX-2": {2},
    "XXXX-WXX-3": {3},
    "XXXX-WXX-4": {4},
    "XXXX-WXX-5": {5},
    "XXXX-WXX-6": {6},
    "XXXX-WXX-7": {7},
}

ATTR_MESSAGE = "message"
ATTR_EMAIL = "email"
ATTR_ENTITY_ID = "entity_id"
ATTR_NUM_ENTRIES = "entries"
COMMON_BUCKET_COUNTS = (
    "accounts",
    "devices",
    "media_players",
    "players",
    "notifications",
    "entities",
)
COMMON_DIAGNOSTIC_BUCKETS = (
    "account",
    "accounts",
    "login",
    "logins",
    "session",
    "sessions",
)
COMMON_DIAGNOSTIC_NAMES = (
    "name",
    "deviceName",
    "accountName",
    "friendlyName",
    "title",
)
DEVICE_PLAYER_BUCKETS = ("devices", "media_players", "players")
TO_REDACT: set[str] = {
    "email",
    "password",
    "access_token",
    "refresh_token",
    "token",
    "csrf",
    "cookie",
    "cookies",
    "session",
    "sessionid",
    "macDms",
    "mac_dms",
    "otp_secret",
    "authorization_code",
    "securitycode",
    "code_verifier",
    "adp_token",
    "device_private_key",
    "customerId",
}
STREAMING_ERROR_MESSAGE = (
    "Sorry, direct music streaming isn't supported. "
    "This limitation is set by Amazon, and not by Alexa-Media-Player, Music-Assistant, nor Home-Assistant."
)
PUBLIC_URL_ERROR_MESSAGE = (
    "To send TTS, please set the public URL in integration configuration."
)
STARTUP_MESSAGE = """
{name} Version Info
{DOMAIN}: v{version}
alexapy API: v{alexapy_version}
If you have any issues with this custom component, you need to open an issue here: {ISSUE_URL}
"""

AUTH_CALLBACK_PATH = "/auth/alexamedia/callback"
AUTH_CALLBACK_NAME = "auth:alexamedia:callback"
AUTH_PROXY_PATH = "/auth/alexamedia/proxy"
AUTH_PROXY_NAME = "auth:alexamedia:proxy"

ALEXA_UNIT_CONVERSION = {
    "Alexa.Unit.Percent": PERCENTAGE,
    "Alexa.Unit.PartsPerMillion": CONCENTRATION_PARTS_PER_MILLION,
    "Alexa.Unit.Density.MicroGramsPerCubicMeter": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
}

ALEXA_ICON_CONVERSION = {
    "Alexa.AirQuality.CarbonMonoxide": "mdi:molecule-co",
    "Alexa.AirQuality.Humidity": "mdi:water-percent",
    "Alexa.AirQuality.IndoorAirQuality": "mdi:numeric",
    "Alexa.AirQuality.ParticulateMatter": "mdi:blur",
    "Alexa.AirQuality.VolatileOrganicCompounds": "mdi:air-filter",
}
ALEXA_ICON_DEFAULT = "mdi:molecule"

# Device class mapping for air quality sensors
# Maps Alexa sensor types to Home Assistant SensorDeviceClass
ALEXA_AIR_QUALITY_DEVICE_CLASS = {
    "Alexa.AirQuality.ParticulateMatter": "pm25",
    "Alexa.AirQuality.CarbonMonoxide": "carbon_monoxide",
    "Alexa.AirQuality.IndoorAirQuality": "aqi",
    "Alexa.AirQuality.VolatileOrganicCompounds": "aqi",
    "Alexa.AirQuality.Humidity": "humidity",
}

UPLOAD_PATH = "www/alexa_tts"

# Note: Some of these are likely wrong
MODEL_IDS = {
    "A10A33FOX2NUBK": "Echo Spot (Gen1)",
    "A10L5JEZTKKCZ8": "Vobot Bunny",
    "A11QM4H9HGV71H": "Echo Show 5 (Gen3)",
    "A12GXV8XMS007S": "Fire TV (Gen1)",
    "A12IZU8NMHSY5U": "Generic Device",
    "A132LT22WVG6X5": "Samsung Soundbar Q700A",
    "A13B2WB920IZ7X": "Samsung HW-Q70T Soundbar",
    "A13W6HQIHKEN3Z": "Echo Auto",
    "A14ZH95E6SE9Z1": "Bose Home Speaker 300",
    "A15996VY63BQ2D": "Echo Show 8 (Gen2)",
    "A15ERDAKK5HQQG": "Sonos",
    "A15QWUTQ6FSMYX": "Echo Buds (Gen2)",
    "A16MZVIFVHX6P6": "Generic Echo",
    "A17LGWINFBUTZZ": "Anker Roav Viva",
    "A18BI6KPKDOEI4": "Ecobee4",
    "A18O6U1UQFJ0XK": "Echo Plus (Gen2)",
    "A18TCD9FP10WJ9": "Orbi Voice",
    "A18X8OBWBCSLD8": "Samsung Soundbar",
    "A195TXHV1M5D4A": "Echo Auto",
    "A1C66CX2XD756O": "Fire Tablet HD",
    "A1D54LQEG0OXJ2": "Denon Home 250",
    "A1EIANJ7PNB0Q7": "Echo Show 15 (Gen1)",
    "A1ENT81UXFMNNO": "Unknown",
    "A1ETW4IXK2PYBP": "Talk to Alexa",
    "A1F1F76XIW4DHQ": "Unknown TV",
    "A1F8D55J0FWDTN": "Fire TV (Toshiba)",
    "A1H0CMF1XM0ZP4": "Bose SoundTouch 30",
    "A1J16TEDOYCZTN": "Fire Tablet",
    "A1JJ0KFC4ZPNJ3": "Echo Input",
    "A1L4KDRIILU6N9": "Sony Speaker",
    "A1LOQ8ZHF4G510": "Samsung Soundbar Q990B",
    "A1M0A9L9HDBID3": "One-Link Safe and Sound",
    "A1MKGHX5VQBDWX": "Denon Home 150",
    "A1MUORL8FP149X": "Unknown",
    "A1N9SW0I0LUX5Y": "Ford/Lincoln Alexa App",
    "A1NL4BVLQ4L3N3": "Echo Show (Gen1)",
    "A1NQ0LXWBGVQS9": "2021 Samsung QLED TV",
    "A1P31Q3MOWSHOD": "Zolo Halo Speaker",
    "A1P7E7V3FCZKU6": "Fire TV (Gen3)",
    "A1Q69AKRWLJC0F": "TV",
    "A1Q7QCGNMXAKYW": "Generic Tablet",
    "A1QKZ9D0IJY332": "Samsung TV 2020-U",
    "A1RABVCI4QCIKC": "Echo Dot (Gen3)",
    "A1RTAM01W29CUP": "Windows App",
    "A1SCI5MODUBAT1": "Pioneer DMH-W466NEX",
    "A1TD5Z1R8IWBHA": "Tablet",
    "A1VGB7MHSIEYFK": "Fire TV Cube Gen3",
    "A1W2YILXTG9HA7": "Nextbase 522GW Dashcam",
    "A1W46V57KES4B5": "Cable TV box Brazil",
    "A1WZKXFLI43K86": "Fire TV Stick MAX",
    "A1XWJRHALS1REP": "Echo Show 5 (Gen2)",
    "A1Z88NGR2BK6A2": "Echo Show 8 (Gen1)",
    "A25EC4GIHFOCSG": "Unrecognized Media Player",
    "A25OJWHZA1MWNB": "2021 Samsung QLED TV",
    "A265XOI9586NML": "Fire TV Stick",
    "A27VEYGQBW3YR5": "Echo Link",
    "A2A3XFQ1AVYLHZ": "SONY WF-1000XM5",
    "A2BRQDVMSZD13S": "SURE Universal Remote",
    "A2C8J6UHV0KFCV": "Alexa Gear",
    "A2DS1Q2TPDJ48U": "Echo Dot Clock (Gen5)",
    "A2E0SNTXJVT7WK": "Fire TV (Gen2)",
    "A2E5N6DMWCW8MZ": "Brilliant Smart Switch",
    "A2EZ3TS0L1S2KV": "Sonos Beam",
    "A2GFL5ZMWNE0PX": "Fire TV (Gen3)",
    "A2H4LV5GIZ1JFT": "Echo Dot Clock (Gen4)",
    "A2HZENIFNYTXZD": "Facebook Portal",
    "A2I0SCCU3561Y8": "Samsung Soundbar Q800A",
    "A2IS7199CJBT71": "TV",
    "A2IVLV5VM2W81": "Alexa Mobile Voice iOS",
    "A2J0R2SD7G9LPA": "Lenovo SmartTab M10",
    "A2JKHJ0PX4J3L3": "Fire TV Cube (Gen2)",
    "A2LH725P8DQR2A": "Fabriq Riff",
    "A2LLN0UXRW4N50": "Echo Show 11 (Gen1)",
    "A2LWARUGJLBYEW": "Fire TV Stick (Gen2)",
    "A2M35JJZWCQOMZ": "Echo Plus (Gen1)",
    "A2M4YX06LWP8WI": "Fire Tablet",
    "A2N49KXGVA18AR": "Fire Tablet HD 10 Plus",
    "A2OSP3UA4VC85F": "Sonos",
    "A2R2GLZH1DFYQO": "Zolo Halo Speaker",
    "A2RU4B77X9R9NZ": "Echo Link Amp",
    "A2TF17PFR55MTB": "Alexa Mobile Voice Android",
    "A2TTLILJHVNI9X": "LG TV",
    "A2U21SRK4QGSE1": "Echo Dot (Gen4)",
    "A2UONLFQW0PADH": "Echo Show 8 (Gen3)",
    "A2V9UEGZ82H4KZ": "Fire Tablet HD 10",
    "A2VAXZ7UNGY4ZH": "Wyze Headphones",
    "A2WFDCBDEXOXR8": "Bose Soundbar 700",
    "A2WJ2CM9ARLMRH": "Rivian Electric Vehicle",
    "A2WN1FJ2HG09UN": "Ultimate Alexa App",
    "A2X8WT9JELC577": "Ecobee5",
    "A2XPGY5LRKB9BE": "Fitbit Versa 2",
    "A2Y04QPFCANLPQ": "Bose QuietComfort 35 II",
    "A303PJF6ISQ7IC": "Echo Auto",
    "A30YDR2MK8HMRV": "Echo (Gen3)",
    "A31DTMEEVDDOIV": "Fire TV Stick Lite",
    "A324YMIUSWQDGE": "Samsung 8K TV",
    "A32DDESGESSHZA": "Echo Dot (Gen3)",
    "A32DOYMUN6DTXA": "Echo Dot (Gen3)",
    "A339L426Y220I4": "Teufel Radio",
    "A347G2JC8I4HC7": "Roav Car Charger Pro",
    "A37CFAHI1O0CXT": "Logitech Blast",
    "A37M7RU8Z6ZFB": "Garmin Speak",
    "A37SHHQ3NUL7B5": "Bose Home Speaker 500",
    "A38949IHXHRQ5P": "Echo Tap",
    "A38BPK7OW001EX": "Raspberry Alexa",
    "A38EHHIB10L47V": "Fire Tablet HD 8",
    "A39BU42XNMN516": "Generic Device",
    "A3B50IC5QPZPWP": "Polk Command Bar",
    "A3B5K1G3EITBIF": "Facebook Portal",
    "A3BRT6REMPQWA8": "Bose Home Speaker 450",
    "A3BW5ZVFHRCQPO": "BMW Alexa Integration",
    "A3C9PE6TNYLTCH": "Speaker Group",
    "A3CY98NH016S5F": "Facebook Portal Mini",
    "A3D4YURNTARP5K": "Facebook Portal TV",
    "A3EH2E0YZ30OD6": "Echo Spot (Gen2)",
    "A3EVMLQTU6WL1W": "Fire TV Stick 4K Max (Gen1)",
    "A3F1S88NTZZXS9": "Dash Wand",
    "A3FX4UWTP28V1P": "Echo (Gen3)",
    "A3GFRGUNIGG1I5": "Samsung TV QN50Q60CAGXZD",
    "A3HF4YRA2L7XGC": "Fire TV Cube",
    "A3IYPH06PH1HRA": "Echo Frames",
    "A3K69RS3EIMXPI": "Hisense Smart TV",
    "A3KULB3NQN7Z1F": "Unknown TV",
    "A3L0T0VL9A921N": "Fire Tablet HD 8",
    "A3NPD82ABCPIDP": "Sonos Beam",
    "A3QPPX1R9W5RJV": "Fabriq Chorus",
    "A3QS1XP2U6UJX9": "SONY WF-1000XM4",
    "A3R9S4ZZECZ6YL": "Fire Tablet HD 10",
    "A3RBAYBE7VM004": "Echo Studio",
    "A3RCTOK2V0A4ZG": "LG TV",
    "A3RMGO6LYLH7YN": "Echo Dot (Gen4)",
    "A3S5BH2HU6VAYF": "Echo Dot (Gen2)",
    "A3SSG6GR8UU7SN": "Echo Sub",
    "A3SSWQ04XYPXBH": "Generic Tablet",
    "A3TCJ8RTT3NVI7": "Alexa Listens",
    "A3VRME03NAXFUB": "Echo Flex",
    "A4ZP7ZC4PI6TO": "Echo Show 5 (Gen1)",
    "A4ZXE0RM7LQ7A": "Echo Dot (Gen5)",
    "A52ARKF0HM2T4": "Facebook Portal+",
    "A6SIQKETF3L2E": "Unknown Device",
    "A7WXQPH584YP": "Echo (Gen2)",
    "A81PNL0A63P93": "Home Remote",
    "A8DM4FYR6D3HT": "TV",
    "AA1IN44SS3X6O": "Ecobee Thermostat Premium",
    "AB72C64C86AW2": "Echo (Gen1)",
    "ABJ2EHL7HQT4L": "Unknown Amplifier",
    "ADVBD696BHNV5": "Fire TV Stick (Gen1)",
    "AE7X7Z227NFNS": "HiMirror Mini",
    "AF473ZSOIRKFJ": "Onkyo VC-PX30",
    "AFF50AL5E3DIU": "Fire TV (Insignia)",
    "AFF5OAL5E3DIU": "Fire TV",
    "AGHZIK8D6X7QR": "Fire TV",
    "AHJYKVA63YCAQ": "Sonos",
    "AIPK7MM90V7TB": "Echo Show 10 (Gen3)",
    "AKKLQD9FZWWQS": "Jabra Elite",
    "AKNO1N0KSFN8L": "Echo Dot (Gen1)",
    "AKO51L5QAQKL2": "Alexa Jams",
    "AKPGW064GI9HE": "Fire TV Stick 4K (Gen3)",
    "ALCIV0P5M8TZ0": "Samsung Soundbar S800B",
    "ALT9P69K6LORD": "Echo Auto",
    "AMCZ48H33RCDF": "Samsung HW-Q910B 9.1.2 ch Soundbar",
    "AN630UQPG2CA4": "Fire TV (Toshiba)",
    "AO6HHP9UE6EOF": "Unknown Media Device",
    "AP1F6KUH00XPV": "Stereo/Subwoofer Pair",
    "AP4RS91ZQ0OOI": "Fire TV (Toshiba)",
    "APHEAY6LX7T13": "Samsung Smart Refrigerator",
    "AQCGW9PSYWRF": "TV",
    "AR6X0XNIME80V": "Unknown TV",
    "ASQZWP4GPYUT7": "Echo Pop",
    "ATNLRCEBX3W4P": "Generic Tablet",
    "AUPUQSVCVHXP0": "Ecobee Switch+",
    "AVD3HM0HOJAAL": "Sonos",
    "AVE5HX13UR5NO": "Logitech Zero Touch",
    "AVN2TMX8MU2YM": "Bose Home Speaker 500",
    "AVU7CPPF2ZRAS": "Fire Tablet HD 8",
    "AWZZ5CVHX2CD": "Echo Show (Gen2)",
}
