const { TradingPair, MarketPair, Asset } = require("../../models");
const { Op } = require("sequelize");
const { BadRequestError, NotFoundError, ConflictError } = require("../../utils/errors");

class adminTradingPairService {
  async getTradingPairs(query = {}) {
    const { q, market, status, tradingEnabled, isFeatured, page = 1, limit = 20 } = query;

    const pageNum = Math.max(parseInt(page, 10) || 1, 1);
    const limitNum = Math.min(Math.max(parseInt(limit, 10) || 20, 1), 100);
    const offset = (pageNum - 1) * limitNum;

    const where = {};

    if (market) where.market = market;
    if (status) where.status = status;

    if (tradingEnabled === "true") where.tradingEnabled = true;
    if (tradingEnabled === "false") where.tradingEnabled = false;

    if (isFeatured === "true") where.isFeatured = true;
    if (isFeatured === "false") where.isFeatured = false;

    if (q && String(q).trim()) {
      const s = String(q).trim();
      where[Op.or] = [
        { symbol: { [Op.like]: `%${s}%` } },
        { name: { [Op.like]: `%${s}%` } },
        { baseAsset: { [Op.like]: `%${s}%` } },
        { quoteAsset: { [Op.like]: `%${s}%` } },
      ];
    }

    const { rows, count } = await MarketPair.findAndCountAll({
      where,
      order: [
        ["created_at", "DESC"],
      ],
      limit: limitNum,
      offset,
      include:[
        {model: Asset, as: 'base',require:true},
         {model: Asset, as: 'quote',require:true}
      ]
    });
    const assets = await Asset.findAll({

    })
    return {
      count,
      page: pageNum,
      limit: limitNum,
      pairs: rows,
      assets
    };
  }

  async getTradingPairById(pairId) {
    const pair = await MarketPair.findByPk(pairId);
    if (!pair) throw new NotFoundError("Trading pair not found");
    return { pair };
  }

  async createTradingPair(data) {
    const symbol = String(data?.symbol || "").trim();
    const baseAsset = String(data?.baseAsset || "").trim();
    const quoteAsset = String(data?.quoteAsset || "").trim();
    const market = String(data?.market || "").trim();

    if (!symbol) throw new BadRequestError("symbol is required");
    if (!baseAsset) throw new BadRequestError("baseAsset is required");
    if (!quoteAsset) throw new BadRequestError("quoteAsset is required");
    if (!market) throw new BadRequestError("market is required");

    const exists = await MarketPair.findOne({ where: { symbol } });
    if (exists) throw new ConflictError("symbol already exists");

    const payload = {
      name: data?.name ?? null,
      symbol,
      baseAsset,
      quoteAsset,
      market,

      status: data?.status ?? "active",
      tradingEnabled: data?.tradingEnabled ?? true,

      isFeatured: data?.isFeatured ?? false,
      sortOrder: Number.isFinite(Number(data?.sortOrder)) ? Number(data.sortOrder) : 0,

      makerFee: data?.makerFee ?? 0.001,
      takerFee: data?.takerFee ?? 0.001,

      pricePrecision: Number.isFinite(Number(data?.pricePrecision)) ? Number(data.pricePrecision) : 8,
      quantityPrecision: Number.isFinite(Number(data?.quantityPrecision)) ? Number(data.quantityPrecision) : 8,

      minNotional: data?.minNotional ?? 10,
      minQuantity: data?.minQuantity ?? 0,
      stepSize: data?.stepSize ?? 0.00000001,
      tickSize: data?.tickSize ?? 0.01,

      maxLeverage: Number.isFinite(Number(data?.maxLeverage)) ? Number(data.maxLeverage) : 1,

      tradeView: data?.tradeView ?? null,
      logo: data?.logo ?? null,
      metadata: data?.metadata ?? {},
    };

    const pair = await MarketPair.create(payload);
    return pair;
  }

  async updateTradingPair(pairId, data) {
    const pair = await MarketPair.findByPk(pairId);
    if (!pair) throw new NotFoundError("Trading pair not found");

    if (data?.symbol && String(data.symbol).trim() !== String(pair.symbol)) {
      const symbol = String(data.symbol).trim();
      const exists = await MarketPair.findOne({ where: { symbol } });
      if (exists) throw new ConflictError("symbol already exists");
    }

    const patch = { ...data };

    // Normalize some common numeric fields if provided
    const numFields = [
      "sortOrder",
      "makerFee",
      "takerFee",
      "pricePrecision",
      "quantityPrecision",
      "minNotional",
      "minQuantity",
      "stepSize",
      "tickSize",
      "maxLeverage",
    ];

    for (const k of numFields) {
      if (patch[k] !== undefined && patch[k] !== null && patch[k] !== "") {
        const n = Number(patch[k]);
        if (Number.isFinite(n)) patch[k] = n;
      }
    }

    await pair.update(patch);
    return pair;
  }

  async deleteTradingPair(pairId) {
    const pair = await MarketPair.findByPk(pairId);
    if (!pair) throw new NotFoundError("Trading pair not found");
    await pair.destroy();
    return true;
  }
}

module.exports = new adminTradingPairService();