// src/services/perpsService.js
const { Op } = require("sequelize");
const {
  TradingPair,
  PerpOrder,
  PerpPosition,
  PerpTrade,
  PerpFunding,
  PerpLiquidation,
} = require("../models");
const { NotFoundError } = require("../utils/errors");

class PerpsService {
  /**
   * List perpetual contracts
   */
  async getPairs(filters = {}) {
    const { base, quote, status, search, page = 1, limit = 50 } = filters;

    const where = { market: "perps" };
    if (status) where.status = status;
    if (base) where.baseAsset = base.toUpperCase();
    if (quote) where.quoteAsset = quote.toUpperCase();
    if (search) where.symbol = { [Op.iLike]: `%${search}%` };

    const { count, rows } = await TradingPair.findAndCountAll({
      where,
      order: [["isFeatured", "DESC"], ["volume24h", "DESC"]],
      limit: Number(limit),
      offset: (Number(page) - 1) * Number(limit),
    });

    return {
      pairs: rows,
      pagination: {
        total: count,
        page: Number(page),
        limit: Number(limit),
        totalPages: Math.ceil(count / Number(limit)),
      },
    };
  }

  /**
   * Perps ticker(s): mark/index, funding, etc. will be joined later
   */
  async getTickers(symbol = null) {
    const where = { market: "perps", status: "active" };
    if (symbol) where.symbol = symbol.toUpperCase();

    return TradingPair.findAll({
      where,
      attributes: [
        "symbol",
        "price",
        "bidPrice",
        "askPrice",
        "markPrice",
        "indexPrice",
        "priceChange24h",
        "priceChangePercent24h",
        "high24h",
        "low24h",
        "volume24h",
        "priceUpdatedAt",
      ],
      order: [["volume24h", "DESC"]],
    });
  }

  async getTickerBySymbol(symbol) {
    const pair = await TradingPair.findOne({
      where: { market: "perps", symbol: symbol.toUpperCase() },
    });
    if (!pair) throw new NotFoundError("Perp contract not found");
    return pair;
  }

  async getOrderbook(symbol, limit = 50) {
    // logic later
    return { symbol: symbol.toUpperCase(), limit: Number(limit) };
  }

  async getRecentTrades(symbol, limit = 50) {
    // logic later
    return { symbol: symbol.toUpperCase(), limit: Number(limit) };
  }

  async getKlines(symbol, interval = "1h", limit = 200) {
    // logic later
    return { symbol: symbol.toUpperCase(), interval, limit: Number(limit) };
  }

  /**
   * Funding info for a contract
   */
  async getFunding(symbol) {
    // logic later (rate, next funding time, etc.)
    return { symbol: symbol.toUpperCase(), funding: {} };
  }

  /**
   * Account summary (cross/isolated totals)
   */
  async getAccount(userId) {
    // logic later
    return { userId, account: {} };
  }

  /**
   * Set margin mode cross/isolated
   */
  async setMarginMode(userId, payload) {
    // logic later
    return { userId, ...payload };
  }

  /**
   * Set leverage for a symbol (and optionally mode)
   */
  async setLeverage(userId, payload) {
    // logic later
    return { userId, ...payload };
  }

  /**
   * Positions
   */
  async getPositions(userId, filters = {}) {
    const { symbol, status = "open", page = 1, limit = 50 } = filters;

    const where = { userId };
    if (symbol) where.symbol = symbol.toUpperCase();
    if (status) where.status = status;

    const { count, rows } = await PerpPosition.findAndCountAll({
      where,
      order: [["createdAt", "DESC"]],
      limit: Number(limit),
      offset: (Number(page) - 1) * Number(limit),
    });

    return {
      positions: rows,
      pagination: {
        total: count,
        page: Number(page),
        limit: Number(limit),
        totalPages: Math.ceil(count / Number(limit)),
      },
    };
  }

  async closePosition(userId, id) {
    // logic later
    return { userId, id: Number(id), closed: true };
  }

  async updatePositionTpSl(userId, id, payload) {
    // logic later
    return { userId, id: Number(id), ...payload };
  }

  /**
   * Orders
   */
  async getOpenOrders(userId, filters = {}) {
    const { symbol, page = 1, limit = 50 } = filters;

    const where = { userId, status: "open" };
    if (symbol) where.symbol = symbol.toUpperCase();

    const { count, rows } = await PerpOrder.findAndCountAll({
      where,
      order: [["createdAt", "DESC"]],
      limit: Number(limit),
      offset: (Number(page) - 1) * Number(limit),
    });

    return {
      orders: rows,
      pagination: {
        total: count,
        page: Number(page),
        limit: Number(limit),
        totalPages: Math.ceil(count / Number(limit)),
      },
    };
  }

  async getOrderHistory(userId, filters = {}) {
    const { symbol, page = 1, limit = 50 } = filters;

    const where = { userId };
    if (symbol) where.symbol = symbol.toUpperCase();

    const { count, rows } = await PerpOrder.findAndCountAll({
      where,
      order: [["createdAt", "DESC"]],
      limit: Number(limit),
      offset: (Number(page) - 1) * Number(limit),
    });

    return {
      orders: rows,
      pagination: {
        total: count,
        page: Number(page),
        limit: Number(limit),
        totalPages: Math.ceil(count / Number(limit)),
      },
    };
  }

  async placeOrder(userId, payload) {
    // logic later (reduce-only, liquidation, etc.)
    return { userId, order: payload };
  }

  async cancelOrder(userId, id) {
    // logic later
    return { userId, id: Number(id), canceled: true };
  }

  /**
   * Trades
   */
  async getMyTrades(userId, filters = {}) {
    const { symbol, page = 1, limit = 50 } = filters;

    const where = { userId };
    if (symbol) where.symbol = symbol.toUpperCase();

    const { count, rows } = await PerpTrade.findAndCountAll({
      where,
      order: [["createdAt", "DESC"]],
      limit: Number(limit),
      offset: (Number(page) - 1) * Number(limit),
    });

    return {
      trades: rows,
      pagination: {
        total: count,
        page: Number(page),
        limit: Number(limit),
        totalPages: Math.ceil(count / Number(limit)),
      },
    };
  }

  /**
   * Liquidation events
   */
  async getLiquidations(userId, filters = {}) {
    const { symbol, page = 1, limit = 50 } = filters;

    const where = { userId };
    if (symbol) where.symbol = symbol.toUpperCase();

    const { count, rows } = await PerpLiquidation.findAndCountAll({
      where,
      order: [["createdAt", "DESC"]],
      limit: Number(limit),
      offset: (Number(page) - 1) * Number(limit),
    });

    return {
      liquidations: rows,
      pagination: {
        total: count,
        page: Number(page),
        limit: Number(limit),
        totalPages: Math.ceil(count / Number(limit)),
      },
    };
  }
}

module.exports = new PerpsService();