# -----------------------------------------------------------
# Astra - WhatsApp Client Framework
# Licensed under the MIT License.
# -----------------------------------------------------------

"""
Central registry of all Astra error codes.

Error codes follow Exxx numbering by category:
  E1xxx  Authentication
  E2xxx  Connection & Browser
  E3xxx  Messaging & Chat
  E4xxx  Groups
  E5xxx  Account & Profile
  E6xxx  Bridge & Engine
  E7xxx  Validation
  E8xxx  WhatsApp-Side (rate limits, bans, server)
"""

from enum import Enum
from typing import NamedTuple


class _CodeDef(NamedTuple):
    code: str
    category: str
    message: str
    hint: str
    retryable: bool


class ErrorCode(Enum):
    """
    Every known Astra error code.

    Usage::

        from astra.errors.codes import ErrorCode
        raise LoginFailedError(ErrorCode.AUTH_FAILED)
    """

    # ── E1xxx · Authentication ─────────────────────────────
    AUTH_FAILED = _CodeDef(
        "E1001", "Auth",
        "Authentication failed.",
        "Check your internet and try scanning the QR code again.",
        True
    )
    AUTH_QR_TIMEOUT = _CodeDef(
        "E1002", "Auth",
        "QR code scan timed out.",
        "Restart the client to generate a new QR code.",
        True
    )
    AUTH_PAIRING_FAILED = _CodeDef(
        "E1003", "Auth",
        "Phone pairing failed.",
        "Ensure the phone number is correct and WhatsApp is installed.",
        True
    )
    AUTH_SESSION_EXPIRED = _CodeDef(
        "E1004", "Auth",
        "Session has expired.",
        "Re-authenticate by scanning the QR code.",
        True
    )
    AUTH_RATE_LIMITED = _CodeDef(
        "E1005", "Auth",
        "Too many login attempts.",
        "Wait 5-10 minutes before trying again. Avoid rapid re-logins.",
        False
    )
    AUTH_PHONE_DISCONNECTED = _CodeDef(
        "E1006", "Auth",
        "Primary phone lost connection.",
        "Ensure your phone has an active internet connection.",
        True
    )

    # ── E2xxx · Connection & Browser ───────────────────────
    CONN_BROWSER_START = _CodeDef(
        "E2001", "Connection",
        "Failed to launch browser.",
        "Check that Playwright browsers are installed: python -m playwright install",
        False
    )
    CONN_BROWSER_CRASH = _CodeDef(
        "E2002", "Connection",
        "Browser process crashed.",
        "This is usually a resource issue. Try reducing headless=False for debugging.",
        True
    )
    CONN_BROWSER_LIMIT = _CodeDef(
        "E2003", "Connection",
        "Another browser instance is using this session profile.",
        "Close other Astra instances or WhatsApp tabs using this session.",
        False
    )
    CONN_PAGE_UNRESPONSIVE = _CodeDef(
        "E2004", "Connection",
        "Browser page is unresponsive.",
        "The page may have frozen. Astra will attempt recovery.",
        True
    )
    CONN_LOST = _CodeDef(
        "E2005", "Connection",
        "Lost connection to the browser.",
        "The browser might have crashed. Astra will attempt to reconnect.",
        True
    )
    CONN_WS_DISCONNECT = _CodeDef(
        "E2006", "Connection",
        "WebSocket connection to WhatsApp dropped.",
        "Check your internet connection. This may also indicate a server-side issue.",
        True
    )
    CONN_NAVIGATION_FAILED = _CodeDef(
        "E2007", "Connection",
        "Failed to navigate to WhatsApp Web.",
        "Check your internet connection and firewall settings.",
        True
    )
    CONN_STARTUP_FAILED = _CodeDef(
        "E2008", "Connection",
        "Client startup failed.",
        "Check the error log for details. Usually a browser or auth issue.",
        True
    )

    # ── E3xxx · Messaging & Chat ───────────────────────────
    MSG_SEND_FAILED = _CodeDef(
        "E3001", "Messaging",
        "Message failed to send.",
        "Ensure the recipient JID is correct and you have an active connection.",
        True
    )
    MSG_SEND_TIMEOUT = _CodeDef(
        "E3002", "Messaging",
        "Message send timed out.",
        "WhatsApp server did not acknowledge. The message may still deliver.",
        True
    )
    MSG_INVALID_RECIPIENT = _CodeDef(
        "E3003", "Messaging",
        "Invalid recipient.",
        "JID must end with @c.us (contacts) or @g.us (groups).",
        False
    )
    MSG_MEDIA_UPLOAD = _CodeDef(
        "E3004", "Messaging",
        "Media upload failed.",
        "Check file path, format, and size (max 64MB for documents).",
        True
    )
    MSG_MEDIA_DOWNLOAD = _CodeDef(
        "E3005", "Messaging",
        "Media download failed.",
        "The media may have expired or the sender deleted it.",
        True
    )
    MSG_EDIT_FAILED = _CodeDef(
        "E3006", "Messaging",
        "Failed to edit message.",
        "Only your own messages sent within 15 minutes can be edited.",
        False
    )
    MSG_DELETE_FAILED = _CodeDef(
        "E3007", "Messaging",
        "Failed to delete message.",
        "You can only delete your own messages. 'Delete for everyone' has a time limit.",
        False
    )
    MSG_REACT_FAILED = _CodeDef(
        "E3008", "Messaging",
        "Failed to react to message.",
        "The message might have been deleted or the chat is read-only.",
        False
    )
    MSG_POLL_FAILED = _CodeDef(
        "E3010", "Messaging",
        "Failed to create poll.",
        "Polls need a question and at least 2 options (max 12).",
        False
    )
    MSG_POLL_VOTE_FAILED = _CodeDef(
        "E3011", "Messaging",
        "Failed to vote on poll.",
        "The poll may have been deleted or you already voted.",
        False
    )
    MSG_FORWARD_FAILED = _CodeDef(
        "E3012", "Messaging",
        "Failed to forward message.",
        "The original message may have been deleted.",
        False
    )
    MSG_CHAT_NOT_FOUND = _CodeDef(
        "E3020", "Messaging",
        "Chat not found.",
        "The chat ID may be incorrect or the chat was deleted.",
        False
    )
    MSG_CHAT_ARCHIVE = _CodeDef(
        "E3021", "Messaging",
        "Chat archive/unarchive failed.",
        "Ensure the chat exists and you have the correct permissions.",
        False
    )
    MSG_CHAT_MUTE = _CodeDef(
        "E3022", "Messaging",
        "Chat mute/unmute failed.",
        "Ensure the chat exists.",
        False
    )
    MSG_CHAT_PIN = _CodeDef(
        "E3023", "Messaging",
        "Chat pin/unpin failed.",
        "Maximum 3 chats can be pinned. Unpin one first.",
        False
    )
    MSG_SEEN_FAILED = _CodeDef(
        "E3024", "Messaging",
        "Failed to mark chat as seen.",
        "The chat may not exist.",
        False
    )
    MSG_SYNC_FAILED = _CodeDef(
        "E3025", "Messaging",
        "Chat history sync failed.",
        "WhatsApp may be throttling requests. Try again later.",
        True
    )

    # ── E4xxx · Groups ─────────────────────────────────────
    GRP_CREATE_FAILED = _CodeDef(
        "E4001", "Group",
        "Failed to create group.",
        "You need at least one other participant. Check JID formats.",
        False
    )
    GRP_ADD_FAILED = _CodeDef(
        "E4002", "Group",
        "Failed to add member(s) to group.",
        "You must be an admin. The user may have privacy settings preventing this.",
        False
    )
    GRP_REMOVE_FAILED = _CodeDef(
        "E4003", "Group",
        "Failed to remove member(s) from group.",
        "You must be an admin to remove participants.",
        False
    )
    GRP_PROMOTE_FAILED = _CodeDef(
        "E4004", "Group",
        "Failed to promote member to admin.",
        "Only group admins can promote other members.",
        False
    )
    GRP_DEMOTE_FAILED = _CodeDef(
        "E4005", "Group",
        "Failed to demote admin.",
        "You cannot demote the group creator.",
        False
    )
    GRP_JOIN_FAILED = _CodeDef(
        "E4006", "Group",
        "Failed to join group via invite link.",
        "The invite link may have expired or been revoked.",
        False
    )
    GRP_INFO_FAILED = _CodeDef(
        "E4007", "Group",
        "Failed to get group info.",
        "You may not be a member of this group anymore.",
        False
    )
    GRP_LEAVE_FAILED = _CodeDef(
        "E4008", "Group",
        "Failed to leave group.",
        "An internal error occurred. Try again.",
        True
    )
    GRP_SETTINGS_FAILED = _CodeDef(
        "E4010", "Group",
        "Failed to update group settings.",
        "Only admins can change group settings.",
        False
    )
    GRP_PERMISSION_DENIED = _CodeDef(
        "E4020", "Group",
        "Permission denied for group action.",
        "This action requires admin privileges.",
        False
    )

    # ── E5xxx · Account & Profile ──────────────────────────
    ACCT_PROFILE_READ = _CodeDef(
        "E5001", "Account",
        "Failed to read profile.",
        "WhatsApp may still be loading. Try again in a few seconds.",
        True
    )
    ACCT_PROFILE_UPDATE = _CodeDef(
        "E5002", "Account",
        "Failed to update profile.",
        "Check that the value is within WhatsApp's limits.",
        False
    )
    ACCT_STATUS_POST = _CodeDef(
        "E5010", "Account",
        "Failed to post status/story.",
        "The Status tab may not be accessible. Try opening it manually first.",
        True
    )
    ACCT_STATUS_MEDIA = _CodeDef(
        "E5011", "Account",
        "Failed to post media status.",
        "Check file format and size. Images: JPEG/PNG. Videos: MP4 (max 30s).",
        True
    )
    ACCT_PRIVACY_FAILED = _CodeDef(
        "E5020", "Account",
        "Failed to read/update privacy settings.",
        "Privacy settings require navigating the Settings UI. Ensure no dialogs are open.",
        True
    )
    ACCT_BLOCK_FAILED = _CodeDef(
        "E5030", "Account",
        "Failed to block/unblock contact.",
        "The contact JID may be invalid.",
        False
    )
    ACCT_PP_FAILED = _CodeDef(
        "E5040", "Account",
        "Failed to get/set profile picture.",
        "The contact may have disabled profile picture visibility.",
        False
    )
    ACCT_LOGOUT_FAILED = _CodeDef(
        "E5050", "Account",
        "Logout failed.",
        "The session may already be disconnected.",
        False
    )

    # ── E6xxx · Bridge & Engine ────────────────────────────
    BRIDGE_METHOD_NOT_FOUND = _CodeDef(
        "E6001", "Bridge",
        "Bridge method not found.",
        "The requested function does not exist in the JS engine. Check method name.",
        False
    )
    BRIDGE_CALL_FAILED = _CodeDef(
        "E6002", "Bridge",
        "Bridge call failed.",
        "A JavaScript error occurred in the browser. Check the inner error.",
        True
    )
    BRIDGE_EVAL_FAILED = _CodeDef(
        "E6003", "Bridge",
        "JavaScript evaluation failed.",
        "The browser context may have been destroyed. Astra will attempt recovery.",
        True
    )
    BRIDGE_NOT_CONNECTED = _CodeDef(
        "E6004", "Bridge",
        "Bridge is not connected.",
        "Wait for the client to finish starting before making calls.",
        True
    )
    BRIDGE_ENGINE_STALL = _CodeDef(
        "E6005", "Bridge",
        "Engine stall detected.",
        "No events received for an extended period. Astra is attempting recovery.",
        True
    )
    BRIDGE_MODULE_MISSING = _CodeDef(
        "E6006", "Bridge",
        "Required WA module not found.",
        "WhatsApp may have updated its internal structure. Check for Astra updates.",
        False
    )
    BRIDGE_INJECTION_FAILED = _CodeDef(
        "E6007", "Bridge",
        "Script injection failed.",
        "The page may not be on the correct origin yet.",
        True
    )
    BRIDGE_STORE_UNAVAILABLE = _CodeDef(
        "E6008", "Bridge",
        "WhatsApp Store object is unavailable.",
        "Modules haven't loaded yet. Wait for full initialization.",
        True
    )

    # ── E7xxx · Validation ─────────────────────────────────
    VAL_INVALID_JID = _CodeDef(
        "E7001", "Validation",
        "Invalid JID format.",
        "JID must match: number@c.us or number@g.us",
        False
    )
    VAL_EMPTY_TEXT = _CodeDef(
        "E7002", "Validation",
        "Text content cannot be empty.",
        "Provide a non-empty text string.",
        False
    )
    VAL_MISSING_KEYS = _CodeDef(
        "E7003", "Validation",
        "Required parameters are missing.",
        "Check the function signature for required arguments.",
        False
    )
    VAL_INVALID_PHONE = _CodeDef(
        "E7004", "Validation",
        "Invalid phone number format.",
        "Use international format without + or spaces: e.g., 14155552671",
        False
    )
    VAL_INVALID_MEDIA = _CodeDef(
        "E7005", "Validation",
        "Invalid media input.",
        "Provide a valid file path, URL, or base64 string.",
        False
    )
    VAL_PAYLOAD_TOO_LARGE = _CodeDef(
        "E7006", "Validation",
        "Payload exceeds maximum size.",
        "Reduce the size of the data being sent.",
        False
    )

    # ── E8xxx · WhatsApp-Side ──────────────────────────────
    WA_RATE_LIMITED = _CodeDef(
        "E8001", "WhatsApp",
        "Rate limited by WhatsApp.",
        "You are sending too many requests. Wait 5-10 minutes before retrying.",
        True
    )
    WA_ECOSYSTEM_BLOCK = _CodeDef(
        "E8002", "WhatsApp",
        "Message blocked for ecosystem protection.",
        "WhatsApp has flagged this as potential spam. Reduce automation frequency.",
        False
    )
    WA_ACCOUNT_BANNED = _CodeDef(
        "E8003", "WhatsApp",
        "Account temporarily or permanently banned.",
        "Contact WhatsApp support. Avoid using unofficial automation on this number.",
        False
    )
    WA_SERVER_DOWN = _CodeDef(
        "E8004", "WhatsApp",
        "WhatsApp servers are experiencing issues.",
        "Wait and try again. Check https://downdetector.com/status/whatsapp/",
        True
    )
    WA_VERSION_MISMATCH = _CodeDef(
        "E8005", "WhatsApp",
        "WhatsApp Web version mismatch.",
        "Clear browser cache and reload. WhatsApp may have pushed an update.",
        True
    )
    WA_MULTIDEVICE_LIMIT = _CodeDef(
        "E8006", "WhatsApp",
        "Maximum linked devices reached.",
        "Remove old linked devices from WhatsApp → Settings → Linked Devices.",
        False
    )
    WA_ENCRYPTION_ERROR = _CodeDef(
        "E8007", "WhatsApp",
        "End-to-end encryption error.",
        "This usually resolves on its own. Try restarting the client.",
        True
    )
    WA_CONTACT_NOT_ON_WA = _CodeDef(
        "E8008", "WhatsApp",
        "Contact is not registered on WhatsApp.",
        "Verify the phone number and ensure they have WhatsApp installed.",
        False
    )

    # --- Accessors ---
    @property
    def id(self) -> str:
        return self.value.code

    @property
    def category(self) -> str:
        return self.value.category

    @property
    def default_message(self) -> str:
        return self.value.message

    @property
    def default_hint(self) -> str:
        return self.value.hint

    @property
    def retryable(self) -> bool:
        return self.value.retryable
