"""
actions/forward_manager.py

Universal Forward / Copy Manager
(Internal Flood Handling Version)

Features:
- Message link (public + private)
- chat_id + message_id
- Batch forward / copy
- Silent mode
- Delay integration
- Internal Flood handling
- SafeExecutor protection
- Structured logging
"""

import re
import asyncio
from typing import List, Union, Tuple

from pyrogram.errors import FloodWait, RPCError

from ..core.safe_executor import SafeExecutor
from ..core.delay_engine import DelayEngine
from ..core.logger import get_action_logger


# --------------------------------------------------
# REGEX
# --------------------------------------------------

PUBLIC_LINK_REGEX = re.compile(
    r"(?:https?://)?t\.me/([^/]+)/(\d+)"
)

PRIVATE_LINK_REGEX = re.compile(
    r"(?:https?://)?t\.me/c/(\d+)/(\d+)"
)


# --------------------------------------------------
# MANAGER
# --------------------------------------------------

class ForwardManager:

    def __init__(self, client, session_name: str):
        self.client = client
        self.session_name = session_name
        self.logger = get_action_logger(
            "ForwardManager",
            session_name
        )

    # --------------------------------------------------
    # LINK PARSER
    # --------------------------------------------------

    def parse_message_link(
        self,
        link: str
    ) -> Tuple[Union[str, int], int]:

        match = PUBLIC_LINK_REGEX.search(link)
        if match:
            chat = match.group(1)
            message_id = int(match.group(2))

            self.logger.debug(
                f"[{self.session_name}] "
                f"Parsed public link → {chat}/{message_id}"
            )

            return chat, message_id

        match = PRIVATE_LINK_REGEX.search(link)
        if match:
            chat_id = int(f"-100{match.group(1)}")
            message_id = int(match.group(2))

            self.logger.debug(
                f"[{self.session_name}] "
                f"Parsed private link → {chat_id}/{message_id}"
            )

            return chat_id, message_id

        raise ValueError("Invalid message link")

    # --------------------------------------------------
    # NORMALIZE IDS
    # --------------------------------------------------

    def _normalize_ids(
        self,
        message_ids: Union[int, List[int]]
    ) -> List[int]:

        if isinstance(message_ids, int):
            return [message_ids]

        if not message_ids:
            raise ValueError("message_ids is empty")

        return list(message_ids)

    # --------------------------------------------------
    # EXEC FORWARD
    # --------------------------------------------------

    async def _forward_exec(
        self,
        from_chat,
        message_ids,
        to_chat,
        silent: bool
    ):
        return await self.client.forward_messages(
            chat_id=to_chat,
            from_chat_id=from_chat,
            message_ids=message_ids,
            disable_notification=silent
        )

    # --------------------------------------------------
    # EXEC COPY
    # --------------------------------------------------

    async def _copy_exec(
        self,
        from_chat,
        message_ids,
        to_chat,
        silent: bool
    ):
        return await self.client.copy_messages(
            chat_id=to_chat,
            from_chat_id=from_chat,
            message_ids=message_ids,
            disable_notification=silent
        )

    # --------------------------------------------------
    # INTERNAL FLOOD HANDLER
    # --------------------------------------------------

    async def _handle_flood(self, e: FloodWait):

        wait_time = int(e.value)

        self.logger.warning(
            f"[{self.session_name}] "
            f"FloodWait detected → sleeping {wait_time}s"
        )

        await asyncio.sleep(wait_time)

        self.logger.info(
            f"[{self.session_name}] "
            f"FloodWait finished → retry allowed"
        )

    # --------------------------------------------------
    # PUBLIC API
    # --------------------------------------------------

    async def forward(
        self,
        source: Union[str, int],
        message_ids: Union[int, List[int]],
        target: Union[str, int],
        silent: bool = False,
        copy_mode: bool = False,
        use_delay: bool = True
    ) -> bool:

        success_count = 0
        fail_count = 0

        try:

            self.logger.info(
                f"[{self.session_name}] "
                f"Forward start → target={target}"
            )

            # Parse link if needed
            if isinstance(source, str) and "t.me" in source:
                source, message_ids = (
                    self.parse_message_link(source)
                )

            # Normalize IDs
            message_ids = self._normalize_ids(
                message_ids
            )

            # Delay
            if use_delay:
                await DelayEngine.forward_delay()

            executor = (
                self._copy_exec
                if copy_mode
                else self._forward_exec
            )

            mode = "COPY" if copy_mode else "FORWARD"

            # Execute safely
            await SafeExecutor.run(
                executor(
                    source,
                    message_ids,
                    target,
                    silent
                ),
                session_name=self.session_name,
                action_name="forward_message"
            )

            success_count += len(message_ids)

            self.logger.info(
                f"[{self.session_name}] ✅ "
                f"{mode} success → {target} "
                f"count={success_count}"
            )

            return True

        # --------------------------------------------------
        # FLOOD
        # --------------------------------------------------

        except FloodWait as e:

            await self._handle_flood(e)

            fail_count += 1
            return False

        # --------------------------------------------------
        # RPC
        # --------------------------------------------------

        except RPCError as e:

            self.logger.error(
                f"[{self.session_name}] "
                f"RPC Error → {e}"
            )

            fail_count += 1
            return False

        # --------------------------------------------------
        # GENERIC
        # --------------------------------------------------

        except Exception as e:

            self.logger.exception(
                f"[{self.session_name}] "
                f"Unhandled Error → {e}"
            )

            fail_count += 1
            return False

        finally:

            self.logger.info(
                f"[{self.session_name}] "
                f"Forward finished | "
                f"success={success_count} "
                f"fail={fail_count}"
            )