import requests
import json
import datetime
from typing import Dict, Any, Optional, List
from tonsdk.utils import Address
from ..dollers import Dollers


class EventResolver:
    TON_DECIMALS = 1_000_000_000

    def __init__(self, *, event_address: str):
        self.event_address = event_address
        self.event_url = f"https://tonapi.io/v2/events/{event_address}"
        self._cached_event: Optional[Dict[str, Any]] = None
        self._doller = Dollers()._TON_USDT()


    def _fetch_event(self) -> Dict[str, Any]:
        if self._cached_event:
            return self._cached_event

        r = requests.get(self.event_url, timeout=10)
        r.raise_for_status()
        self._cached_event = r.json()
        return self._cached_event

    @staticmethod
    def normalize(addr: str, name: Optional[str] = None) -> str:
        if name:
            return name
        try:
            return Address(addr).to_string(
                is_user_friendly=True,
                is_url_safe=True,
                is_bounceable=False,
                is_test_only=False
            )
        except Exception:
            return addr

    @staticmethod
    def format_time(timestamp: int) -> str:
        return datetime.datetime.fromtimestamp(
            timestamp
        ).strftime("%Y-%m-%d %I:%M:%S %p")

    @staticmethod
    def format_action_name(status: str, action_type: str) -> str:
        return f"{status.upper()} {action_type.upper().replace('_', ' ')}"


    def _parse_gas_relay(
        self,
        action: Dict[str, Any],
        timestamp: int
    ) -> Dict[str, Any]:

        relay = action["GasRelay"]
        preview = action.get("simple_preview", {})

        return {
            "Time": self.format_time(timestamp),
            "Action": self.format_action_name(
                action.get("status", "ok"),
                action.get("type", "GasRelay")
            ),
            "From": self.normalize(
                relay["relayer"]["address"],
                relay["relayer"].get("name")
            ),
            "To": self.normalize(
                relay["target"]["address"],
                relay["target"].get("name")
            ),
            "Price": preview.get("value"),
            "Comment": preview.get("description"),
            "Status": "SUCCESS"
        }

    def _parse_jetton_transfer(
        self,
        action: Dict[str, Any],
        timestamp: int
    ) -> Dict[str, Any]:

        transfer = action["JettonTransfer"]
        preview = action.get("simple_preview", {})

        sender = transfer["sender"]
        recipient = transfer["recipient"]

        result = {
            "Time": self.format_time(timestamp),
            "Action": self.format_action_name(
                action.get("status", "ok"),
                action.get("type", "JettonTransfer")
            ),
            "From": self.normalize(
                sender["address"],
                sender.get("name")
            ),
            "To": self.normalize(
                recipient["address"],
                recipient.get("name")
            ),
            "Price": preview.get("value"),
            "Status": "SUCCESS"
        }

        comment = transfer.get("comment")
        if comment:
            result["Comment"] = comment

        return result

    def _parse_generic_action(
        self,
        action: Dict[str, Any],
        timestamp: int
    ) -> Dict[str, Any]:

        preview = action.get("simple_preview", {})
        accounts = preview.get("accounts", [])

        sender = accounts[0] if len(accounts) > 0 else {}
        receiver = accounts[1] if len(accounts) > 1 else {}

        status = action.get("status", "ok")
        action_type = action.get("type", "UNKNOWN")

        return {
            "Time": self.format_time(timestamp),
            "Action": self.format_action_name(status, action_type),
            "From": self.normalize(
                sender.get("address", ""),
                sender.get("name")
            ),
            "To": self.normalize(
                receiver.get("address", ""),
                receiver.get("name")
            ),
            "Price": preview.get("value"),
            "Comment": preview.get("description"),
            "Status": "SUCCESS" if status == "ok" else "FAILED"
        }


    def extract_info(self) -> Dict[str, Any]:
        try:
            data = self._fetch_event()
            timestamp = data.get("timestamp", 0)
            actions = data.get("actions", [])

            if not actions:
                return {"Error": "No actions found"}

            results: List[Dict[str, Any]] = []

            for action in actions:

                action_type = action.get("type")

                if action_type == "GasRelay":
                    results.append(
                        self._parse_gas_relay(action, timestamp)
                    )
                    continue

                if action_type == "JettonTransfer":
                    results.append(
                        self._parse_jetton_transfer(action, timestamp)
                    )
                    continue

                results.append(
                    self._parse_generic_action(action, timestamp)
                )

            cleaned = [
                {k: v for k, v in r.items() if v is not None}
                for r in results
            ]

            return {"actions": cleaned}

        except requests.HTTPError:
            return {
                "Error":
                "Invalid transaction address."
            }

        except Exception as e:
            return {"Error": f"Parsing error: {e}"}

    def result(self) -> str:
        return json.dumps(
            self.extract_info(),
            indent=2,
            ensure_ascii=False
        )
