# -*- coding: utf-8 -*-

# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code

from ccxt.base.exchange import Exchange
from ccxt.abstract.mazdax import ImplicitAPI
from ccxt.base.types import Any, Int, Market, OrderBook, Strings, Ticker, Tickers
from typing import List


class mazdax(Exchange, ImplicitAPI):

    def describe(self) -> Any:
        return self.deep_extend(super(mazdax, self).describe(), {
            'id': 'mazdax',
            'name': 'Mazdax',
            'countries': ['IR'],
            'rateLimit': 1000,
            'version': '1',
            'certified': False,
            'pro': False,
            'has': {
                'CORS': None,
                'spot': True,
                'margin': False,
                'swap': False,
                'future': False,
                'option': False,
                'addMargin': False,
                'cancelAllOrders': False,
                'cancelOrder': False,
                'cancelOrders': False,
                'createDepositAddress': False,
                'createOrder': False,
                'createStopLimitOrder': False,
                'createStopMarketOrder': False,
                'createStopOrder': False,
                'editOrder': False,
                'fetchBalance': False,
                'fetchBorrowInterest': False,
                'fetchBorrowRateHistories': False,
                'fetchBorrowRateHistory': False,
                'fetchClosedOrders': False,
                'fetchCrossBorrowRate': False,
                'fetchCrossBorrowRates': False,
                'fetchCurrencies': False,
                'fetchDepositAddress': False,
                'fetchDeposits': False,
                'fetchFundingHistory': False,
                'fetchFundingRate': False,
                'fetchFundingRateHistory': False,
                'fetchFundingRates': False,
                'fetchIndexOHLCV': False,
                'fetchIsolatedBorrowRate': False,
                'fetchIsolatedBorrowRates': False,
                'fetchL2OrderBook': False,
                'fetchL3OrderBook': False,
                'fetchLedger': False,
                'fetchLedgerEntry': False,
                'fetchLeverageTiers': False,
                'fetchMarkets': True,
                'fetchMarkOHLCV': False,
                'fetchMyTrades': False,
                'fetchOHLCV': True,
                'fetchOpenInterestHistory': False,
                'fetchOpenOrders': False,
                'fetchOrder': False,
                'fetchOrderBook': True,
                'fetchOrders': False,
                'fetchOrderTrades': 'emulated',
                'fetchPositions': False,
                'fetchPremiumIndexOHLCV': False,
                'fetchTicker': True,
                'fetchTickers': True,
                'fetchTime': False,
                'fetchTrades': False,
                'fetchTradingFee': False,
                'fetchTradingFees': False,
                'fetchWithdrawals': False,
                'setLeverage': False,
                'setMarginMode': False,
                'transfer': False,
                'withdraw': False,
            },
            'comment': 'Mazdax SPOT Exchange',
            'urls': {
                'logo': 'https://cdn.arz.digital/cr-odin/img/exchanges/mazdax/64x64.png',
                'api': {
                    'public': 'https://api.mazdax.ir',
                },
                'www': 'https://mazdax.ir',
                'doc': [
                    'https://api.mazdax.ir',
                ],
            },
            'timeframes': {
                '1m': '1m',
                '5m': '5m',
                '15m': '15m',
                '30m': '30m',
                '1h': '1h',
                '4h': '4h',
                '1d': '1d',
                '1w': '1w',
            },
            'api': {
                'public': {
                    'get': {
                        'market/symbols': 1,
                        'market/rollingprice': 1,
                        'market/candle': 1,
                        'market/order': 1,
                    },
                },
            },
            'fees': {
                'trading': {
                    'tierBased': False,
                    'percentage': True,
                    'maker': self.parse_number('0.001'),
                    'taker': self.parse_number('0.001'),
                },
            },
        })

    def fetch_markets(self, params={}) -> List[Market]:
        """
        retrieves data on all markets for mazdax
        https://api.mazdax.ir/market/symbols
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict[]: an array of objects representing market data
        """
        response = self.publicGetMarketSymbols(params)
        # Response is an array of market objects:
        # [
        #   {
        #     "id": 67,
        #     "createdAt": "2022-12-26T07:33:25Z",
        #     "updatedAt": "2025-07-04T16:18:57Z",
        #     "order": 2,
        #     "symbol": "AHRM1IRR",
        #     "baseAsset": "AHRM1",
        #     "baseAssetTranslate": "AHRM1",
        #     "baseAssetPrecision": 0,
        #     "quoteAsset": "IRR",
        #     "quoteAssetTranslate": "IRR",
        #     "takerFee": "0.00116",
        #     "makerFee": "0.001044",
        #     "quoteAssetPrecision": 0,
        #     "isTradable": True,
        #     "isActive": True,
        #     "isPublic": True,
        #     "minimumOrderSize": "100000",
        #     "maximumOrderSize": "0",
        #     "minimumPrice": "0",
        #     "maximumPrice": "0",
        #     "marketCOV": "0.01",
        #     "marketCap": "10",
        #     "tickSize": "1",
        #     "stepSize": "1",
        #     ...
        #   }
        # ]
        result = []
        for i in range(0, len(response)):
            market = self.parse_market(response[i])
            result.append(market)
        return result

    def parse_market(self, market) -> Market:
        #  {
        #    "id": 67,
        #    "createdAt": "2022-12-26T07:33:25Z",
        #    "updatedAt": "2025-07-04T16:18:57Z",
        #    "order": 2,
        #    "symbol": "AHRM1IRR",
        #    "baseAsset": "AHRM1",
        #    "baseAssetTranslate": "AHRM1",
        #    "baseAssetPrecision": 0,
        #    "quoteAsset": "IRR",
        #    "quoteAssetTranslate": "IRR",
        #    "takerFee": "0.00116",
        #    "makerFee": "0.001044",
        #    "quoteAssetPrecision": 0,
        #    "isTradable": True,
        #    "isActive": True,
        #    "isPublic": True,
        #    "minimumOrderSize": "100000",
        #    "maximumOrderSize": "0",
        #    "minimumPrice": "0",
        #    "maximumPrice": "0",
        #    "marketCOV": "0.01",
        #    "marketCap": "10",
        #    "tickSize": "1",
        #    "stepSize": "1",
        #    ...
        #  }
        id = self.safe_string(market, 'symbol')
        baseId = self.safe_string(market, 'baseAsset')
        quoteId = self.safe_string(market, 'quoteAsset')
        base = self.safe_currency_code(baseId)
        quote = self.safe_currency_code(quoteId)
        baseId = baseId.lower()
        quoteId = quoteId.lower()
        isActive = self.safe_bool(market, 'isActive', False)
        isTradable = self.safe_bool(market, 'isTradable', False)
        active = isActive and isTradable
        return {
            'id': id,
            'symbol': base + '/' + quote,
            'base': base,
            'quote': quote,
            'settle': None,
            'baseId': baseId,
            'quoteId': quoteId,
            'settleId': None,
            'type': 'spot',
            'spot': False,
            'margin': False,
            'swap': False,
            'future': False,
            'option': False,
            'active': active,
            'contract': False,
            'linear': None,
            'inverse': None,
            'contractSize': None,
            'expiry': None,
            'expiryDatetime': None,
            'strike': None,
            'optionType': None,
            'precision': {
                'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'baseAssetPrecision'))),
                'price': self.parse_number(self.parse_precision(self.safe_string(market, 'quoteAssetPrecision'))),
            },
            'limits': {
                'leverage': {
                    'min': None,
                    'max': None,
                },
                'amount': {
                    'min': self.safe_number(market, 'minimumOrderSize'),
                    'max': self.safe_number(market, 'maximumOrderSize'),
                },
                'price': {
                    'min': self.safe_number(market, 'minimumPrice'),
                    'max': self.safe_number(market, 'maximumPrice'),
                },
                'cost': {
                    'min': None,
                    'max': None,
                },
            },
            'created': self.parse8601(self.safe_string(market, 'createdAt')),
            'info': market,
        }

    def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
        """
        fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
        https://api.mazdax.ir/market/rollingprice
        :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
        """
        self.load_markets()
        if symbols is not None:
            symbols = self.market_symbols(symbols)
        markets = self.fetch_markets()
        result = {}
        for i in range(0, len(markets)):
            market = markets[i]
            marketId = market['id']
            request = {
                'from': 'mazdax',
                'symbol': marketId,
            }
            try:
                response = self.publicGetMarketRollingprice(request)
                # {
                #   "AHRM1IRR": {
                #     "symbol": "AHRM1IRR",
                #     "priceChange": "525",
                #     "priceChangePercent": "2.077",
                #     "weightedAvgPrice": "0",
                #     "prevClosePrice": "0",
                #     "lastPrice": "25800",
                #     "lastQty": "14050",
                #     "bidPrice": "0",
                #     "askPrice": "0",
                #     "openPrice": "25275",
                #     "highPrice": "26200",
                #     "lowPrice": "25274",
                #     "volume": "1076873",
                #     "valueIrr": "55104642690",
                #     "openTime": 1760271737577,
                #     "closeTime": 1760351215075,
                #     "count": 348
                #   }
                # }
                tickerData = self.safe_dict(response, marketId)
                if tickerData is not None:
                    ticker = self.parse_ticker(tickerData, market)
                    symbol = ticker['symbol']
                    result[symbol] = ticker
            except Exception as e:
                # Skip markets that fail
                continue
        return self.filter_by_array_tickers(result, 'symbol', symbols)

    def fetch_ticker(self, symbol: str, params={}) -> Ticker:
        """
        fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
        https://api.mazdax.ir/market/rollingprice
        :param str symbol: unified symbol of the market to fetch the ticker for
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        request = {
            'from': 'mazdax',
            'symbol': market['id'],
        }
        response = self.publicGetMarketRollingprice(request)
        # {
        #   "AHRM1IRR": {
        #     "symbol": "AHRM1IRR",
        #     "priceChange": "525",
        #     "priceChangePercent": "2.077",
        #     "weightedAvgPrice": "0",
        #     "prevClosePrice": "0",
        #     "lastPrice": "25800",
        #     "lastQty": "14050",
        #     "bidPrice": "0",
        #     "askPrice": "0",
        #     "openPrice": "25275",
        #     "highPrice": "26200",
        #     "lowPrice": "25274",
        #     "volume": "1076873",
        #     "valueIrr": "55104642690",
        #     "openTime": 1760271737577,
        #     "closeTime": 1760351215075,
        #     "count": 348
        #   }
        # }
        tickerData = self.safe_dict(response, market['id'])
        return self.parse_ticker(tickerData, market)

    def parse_ticker(self, ticker, market: Market = None) -> Ticker:
        # {
        #   "symbol": "AHRM1IRR",
        #   "priceChange": "525",
        #   "priceChangePercent": "2.077",
        #   "weightedAvgPrice": "0",
        #   "prevClosePrice": "0",
        #   "lastPrice": "25800",
        #   "lastQty": "14050",
        #   "bidPrice": "0",
        #   "askPrice": "0",
        #   "openPrice": "25275",
        #   "highPrice": "26200",
        #   "lowPrice": "25274",
        #   "volume": "1076873",
        #   "valueIrr": "55104642690",
        #   "openTime": 1760271737577,
        #   "closeTime": 1760351215075,
        #   "count": 348
        # }
        marketType = 'spot'
        marketId = self.safe_string(ticker, 'symbol')
        symbol = self.safe_symbol(marketId, market, None, marketType)
        timestamp = self.safe_integer(ticker, 'closeTime')
        high = self.safe_string(ticker, 'highPrice')
        low = self.safe_string(ticker, 'lowPrice')
        bid = self.safe_string(ticker, 'bidPrice')
        ask = self.safe_string(ticker, 'askPrice')
        last = self.safe_string(ticker, 'lastPrice')
        open = self.safe_string(ticker, 'openPrice')
        baseVolume = self.safe_string(ticker, 'volume')
        quoteVolume = self.safe_string(ticker, 'valueIrr')
        priceChange = self.safe_string(ticker, 'priceChange')
        percentage = self.safe_string(ticker, 'priceChangePercent')
        return self.safe_ticker({
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'high': high,
            'low': low,
            'bid': bid,
            'bidVolume': None,
            'ask': ask,
            'askVolume': None,
            'vwap': None,
            'open': open,
            'close': last,
            'last': last,
            'previousClose': None,
            'change': priceChange,
            'percentage': percentage,
            'average': None,
            'baseVolume': baseVolume,
            'quoteVolume': quoteVolume,
            'info': ticker,
        }, market)

    def fetch_ohlcv(self, symbol: str, timeframe='1d', since: Int = None, limit: Int = None, params={}) -> List[list]:
        """
        fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
        https://api.mazdax.ir/market/candle
        :param str symbol: unified symbol of the market to fetch OHLCV data for
        :param str timeframe: the length of time each candle represents
        :param int [since]: timestamp in ms of the earliest candle to fetch
        :param int [limit]: the maximum amount of candles to fetch
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns int[][]: A list of candles ordered, open, high, low, close, volume
        """
        self.load_markets()
        market = self.market(symbol)
        endTime = Date.now()
        request = {
            'from': 'binance',
            'symbol': market['id'],
            'interval': self.safe_string(self.timeframes, timeframe, timeframe),
            'limit': limit is not limit if None else 1000,
            'starttime': (endTime) - (30 * 24 * 60 * 60 * 1000),  # 30 days ago
            'endtime': endTime,
        }
        if since is not None:
            request['starttime'] = since / 1000
        response = self.publicGetMarketCandle(request)
        # {
        #   "Candles": [
        #     {
        #       "openTime": "2021-12-20T03:30:00+03:30",
        #       "openPrice": "10000",
        #       "highPrice": "10000",
        #       "lowPrice": "10000",
        #       "closePrice": "10000",
        #       "volume": "490000000",
        #       "closeTime": "2021-12-20T03:30:00+03:30",
        #       "quoteAssetVolume": "0",
        #       "numberOfTrades": 0,
        #       "takerBuyBaseAssetVolume": "0",
        #       "takerBuyQuoteAssetVolume": "0",
        #       "ignore": "0"
        #     },
        #     ...
        #   ]
        # }
        candles = self.safe_list(response, 'Candles', [])
        ohlcvs = []
        for i in range(0, len(candles)):
            candle = candles[i]
            timestamp = self.parse8601(self.safe_string(candle, 'openTime'))
            open = self.safe_string(candle, 'openPrice')
            high = self.safe_string(candle, 'highPrice')
            low = self.safe_string(candle, 'lowPrice')
            close = self.safe_string(candle, 'closePrice')
            volume = self.safe_string(candle, 'volume')
            ohlcvs.append([
                timestamp,
                open,
                high,
                low,
                close,
                volume,
            ])
        return self.parse_ohlcvs(ohlcvs, market, timeframe, since, limit)

    def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
        """
        fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
        https://api.mazdax.ir/market/order
        :param str symbol: unified symbol of the market to fetch the order book for
        :param int [limit]: the maximum amount of order book entries to return
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
        """
        self.load_markets()
        market = self.market(symbol)
        request = {
            'from': 'mazdax',
            'symbol': market['id'],
            'limit': limit is not limit if None else 25,
        }
        response = self.publicGetMarketOrder(request)
        # {
        #   "timestamp": "0001-01-01T00:00:00Z",
        #   "bids": [
        #     ["25321", "9344"],
        #     ["25320", "15000"],
        #     ...
        #   ],
        #   "asks": [
        #     ["26190", "5341"],
        #     ["26195", "2310"],
        #     ...
        #   ]
        # }
        timestamp = self.parse8601(self.safe_string(response, 'timestamp'))
        return self.parse_order_book(response, symbol, timestamp, 'bids', 'asks', 0, 1)

    def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
        query = self.omit(params, self.extract_params(path))
        url = self.urls['api']['public'] + '/' + path
        if query:
            url = url + '?' + self.urlencode(query)
        headers = {'Content-Type': 'application/json'}
        return {'url': url, 'method': method, 'body': body, 'headers': headers}
