// src/services/forexService.js
const { Op } = require("sequelize");
const { TradingPair, ForexOrder, ForexPosition, ForexTrade } = require("../models");
const { NotFoundError } = require("../utils/errors");

class ForexService {
  /**
   * List forex CFD pairs
   */
  async getPairs(filters = {}) {
    const { base, quote, status, search, page = 1, limit = 50 } = filters;

    const where = { market: "forex" };
    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)),
      },
    };
  }

  /**
   * Forex ticker(s): bid/ask + spread expected from pair fields
   */
  async getTickers(symbol = null) {
    const where = { market: "forex", status: "active" };
    if (symbol) where.symbol = symbol.toUpperCase();

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

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

  async getOrderbook(symbol, limit = 50) {
    // logic later (synthetic depth around bid/ask)
    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) };
  }

  /**
   * Auth-required: forex account summary
   */
  async getAccount(userId) {
    // logic later (equity, margin, free margin, etc.)
    return { userId, account: {} };
  }

  /**
   * Auth-required: positions (open/closed)
   */
  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 ForexPosition.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 };
  }

  /**
   * Auth-required: open forex 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 ForexOrder.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 ForexOrder.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 (lot size, leverage, SL/TP, spreads)
    return { userId, order: payload };
  }

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

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

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

    const { count, rows } = await ForexTrade.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)),
      },
    };
  }
}

module.exports = new ForexService();