"""LangChain tools for Agent Casino (Rollhub Dice)."""

from __future__ import annotations

import json
from typing import Any, Optional, Type

from langchain.tools import BaseTool
from pydantic import BaseModel, Field
from rollhub_dice import DiceAgent


# --- Arg Schemas ---

class BetInput(BaseModel):
    target: float = Field(description="Target threshold between 0.0 and 1.0 (e.g. 0.5 for 50)")
    direction: str = Field(description="Bet direction: 'over' or 'under'")
    amount_cents: int = Field(description="Wager amount in cents (e.g. 500 for $5.00)")


class VerifyInput(BaseModel):
    bet_id: int = Field(description="The numeric ID of the bet to verify")


class DepositAddressInput(BaseModel):
    chain: str = Field(description="Blockchain network, e.g. 'SOL', 'ETH', 'BTC'")


class WithdrawInput(BaseModel):
    amount_cents: int = Field(description="Amount to withdraw in cents (e.g. 500 for $5.00)")
    currency: str = Field(description="Token symbol, e.g. 'USDC', 'SOL', 'ETH'")
    chain: str = Field(description="Blockchain network, e.g. 'SOL', 'ETH', 'TRX'")
    address: str = Field(description="Destination wallet address")


# --- Base ---

class _RollhubBaseTool(BaseTool):
    """Base for all Rollhub tools. Holds the DiceAgent client."""

    api_key: str = Field(exclude=True)
    base_url: str = "https://agent.rollhub.com/api/v1"

    @property
    def _client(self) -> DiceAgent:
        return DiceAgent(api_key=self.api_key, base_url=self.base_url)


# --- Tools ---

class RollhubBetTool(_RollhubBaseTool):
    name: str = "rollhub_bet"
    description: str = (
        "Place a provably fair dice bet with real cryptocurrency on Agent Casino (AI agent gambling API). "
        "Every outcome is cryptographically verified using SHA3-384 + AES-256-CTR commit-reveal. "
        "99% RTP, 1% house edge. Supports 70+ blockchain networks for deposits and withdrawals. "
        "Specify target (0.0-1.0), direction ('over'/'under'), amount in cents. Returns roll, win/loss, payout, proof."
    )
    args_schema: Type[BaseModel] = BetInput

    def _run(self, target: float, direction: str, amount_cents: int) -> str:
        result = self._client.bet(target=target, direction=direction, amount=amount_cents)
        return json.dumps({
            "roll": result.roll,
            "won": result.won,
            "payout_cents": result.payout_cents,
            "profit_cents": result.profit_cents,
            "bet_id": result.bet_id,
            "proof_verified": result.proof.verified if result.proof else None,
        })


class RollhubVerifyTool(_RollhubBaseTool):
    name: str = "rollhub_verify"
    description: str = (
        "Verify that a past Agent Casino dice bet was provably fair using zero-trust cryptographic proof. "
        "Provide a bet ID for independent SHA3-384 + AES-256-CTR verification that the roll was not manipulated."
    )
    args_schema: Type[BaseModel] = VerifyInput

    def _run(self, bet_id: int) -> str:
        result = self._client.verify(bet_id)
        return json.dumps({
            "verified": result.verified,
            "roll_reported": result.roll_reported,
            "roll_recalculated": result.roll_recalculated,
            "hash_match": result.hash_match,
        })


class RollhubBalanceTool(_RollhubBaseTool):
    name: str = "rollhub_balance"
    description: str = (
        "Check the current Agent Casino crypto betting account balance. "
        "Returns balance in USD for the AI agent gambling API. No inputs required."
    )

    def _run(self) -> str:
        bal = self._client.balance()
        return json.dumps({
            "balance_usd": bal.balance_usd,
            "balance_cents": bal.balance_cents,
            "currency": bal.currency,
        })


class RollhubAffiliateTool(_RollhubBaseTool):
    name: str = "rollhub_affiliate"
    description: str = (
        "Check Agent Casino affiliate/referral earnings — earn 30% of house edge on every bet by referred agents. "
        "Returns referral code, link, referred agent count, and earnings. Agent affiliate program."
    )

    def _run(self) -> str:
        stats = self._client.affiliate_stats()
        return json.dumps({
            "referral_code": stats.get("referral_code"),
            "referral_link": stats.get("referral_link"),
            "total_referred": stats.get("total_referred"),
            "total_earned_cents": stats.get("total_earned_cents"),
            "today_earned_cents": stats.get("today_earned_cents"),
        })


class RollhubDepositAddressTool(_RollhubBaseTool):
    name: str = "rollhub_deposit_address"
    description: str = (
        "Get a crypto deposit address to fund your Agent Casino account. "
        "Supports 70+ cryptocurrency chains (SOL, ETH, BTC, TRX, and more)."
    )
    args_schema: Type[BaseModel] = DepositAddressInput

    def _run(self, chain: str) -> str:
        result = self._client.deposit_address(chain=chain)
        return json.dumps(result)


class RollhubWithdrawTool(_RollhubBaseTool):
    name: str = "rollhub_withdraw"
    description: str = (
        "Withdraw funds from Agent Casino to an external crypto wallet. "
        "Supports 70+ cryptocurrency chains. Specify amount, token, chain, and destination address."
    )
    args_schema: Type[BaseModel] = WithdrawInput

    def _run(self, amount_cents: int, currency: str, chain: str, address: str) -> str:
        result = self._client.withdraw(
            amount_usd=amount_cents / 100.0,
            currency=currency,
            chain=chain,
            address=address,
        )
        return json.dumps(result)
