// services/watchlistService.js
const { Op } = require("sequelize");
const {
  Watchlist,
  WatchlistAlert,
  SymbolStats,
  Asset,
  MarketPair,
} = require("../models");
const { ConflictError, NotFoundError } = require("../utils/errors");
const { mapWatchlist, getUploadedFile, safeNumber } = require("../utils/helpers");

class WatchlistService {
  // ─────────────────────────────────────────────
  //  READ
  // ─────────────────────────────────────────────
  async getWatchlist(userId) {
    // All tradeable pairs (for the "Add Asset" search modal)
    const allPairs = await MarketPair.findAll({
      where: { status: "active" },
      include: [
        { model: Asset, as: "base" },
        { model: Asset, as: "quote" },
        { model: SymbolStats, as: "rate" },
      ],
    });

    // User's watchlist rows with alerts eager-loaded
    const { rows, count } = await Watchlist.findAndCountAll({
      where: { userId },
      order: [["createdAt", "ASC"]],
      include: [
        {
          model: MarketPair,
          as: "pair",
          include: [
            { model: Asset, as: "base" },
            { model: Asset, as: "quote" },
            { model: SymbolStats, as: "rate" },
          ],
        },
        {
          model: WatchlistAlert,
          as: "alerts",
          where: {},   // load all alerts (active + inactive)
          required: false,
          order: [["createdAt", "DESC"]],
        },
      ],
    });
    const alerts = await WatchlistAlert.findAll({
        where: {userId},
        include: [{model: Watchlist , as: 'watchlist' , include: [{model: MarketPair , as: 'pair'}]}]
    })

    // Category counts
    const byType = (type) => rows.filter((r) => r.pair?.type === type).length;
    const assetcategory = [
      { id: "all",       name: "All Favorites",  icon: "", count, isDefault: true },
      { id: "stock",     name: "Stock",           icon: "", count: byType("stock"),     isDefault: false },
      { id: "spot",      name: "Cryptocurrency",  icon: "", count: byType("spot"),      isDefault: false },
      { id: "fx",        name: "Forex",           icon: "", count: byType("fx"),        isDefault: false },
      { id: "commodity", name: "Commodity",       icon: "", count: byType("commodity"), isDefault: false },
      { id: "index",     name: "Indice",          icon: "", count: byType("index"),     isDefault: false },
    ];

    return {
      assetLists: rows.map((l) => mapWatchlist(l)),
      category:   assetcategory,
      alerts: alerts.map(a => ({
        id: a.id,
        symbol: a.symbol,
        type: a.type,
        price: a.targetPrice
      })),
      assets:     allPairs.map((a) => ({
        symbol:      a.symbol,
        name:        a.name ?? a.base?.name ?? "",
        price:       safeNumber(a.rate?.price ?? 0),
        change:      safeNumber(a.rate?.change24h ?? 0),
        logo:        getUploadedFile(a.base?.logo ?? null, "assets"),
        quoteSymbol: a.quote?.symbol ?? "",
        quoteLogo:   getUploadedFile(a.quote?.logo ?? null, "assets"),
      })),
    };
  }

  // ─────────────────────────────────────────────
  //  WATCHLIST CRUD
  // ─────────────────────────────────────────────
  async addToWatchlist({ userId, symbol }) {
    const pair = await MarketPair.findOne({ where: { symbol } });
    if (!pair) throw new ConflictError("Asset not found");

    const exists = await Watchlist.findOne({ where: { userId, assetId: pair.id } });
    if (exists) return exists;

    return Watchlist.create({ userId, assetId: pair.id });
  }

  async removeFromWatchlist({ userId, itemId }) {
    const deleted = await Watchlist.destroy({ where: { id: itemId, userId } });
    return deleted > 0;
  }

  // ─────────────────────────────────────────────
  //  ALERT CRUD
  // ─────────────────────────────────────────────

  /**
   * Create a price alert tied to a specific watchlist row.
   * @param {object} p
   * @param {number} p.userId
   * @param {number} p.watchlistId  - the watchlists.id row
   * @param {string} p.symbol       - e.g. "BTCUSDT"
   * @param {string} p.type         - "above" | "below"
   * @param {number} p.targetPrice
   */
  async createAlert({ userId, watchlistId, symbol, type, targetPrice }) {
    // Verify the watchlist row belongs to this user
    const row = await Watchlist.findOne({ where: { id: watchlistId, userId } });
    if (!row) throw new NotFoundError("Watchlist item not found");

    const dir = type === "below" ? "below" : "above";

    return WatchlistAlert.create({
      userId,
      watchlistId,
      symbol: String(symbol).toUpperCase(),
      type: dir,
      targetPrice: safeNumber(targetPrice),
      active: true,
    });
  }

  async toggleAlert({ userId, alertId }) {
    const alert = await WatchlistAlert.findOne({ where: { id: alertId, userId } });
    if (!alert) throw new NotFoundError("Alert not found");
    alert.active = !alert.active;
    await alert.save();
    return alert;
  }

  async deleteAlert({ userId, alertId }) {
    const deleted = await WatchlistAlert.destroy({ where: { id: alertId, userId } });
    return deleted > 0;
  }

  // ─────────────────────────────────────────────
  //  LISTS (future – placeholder kept)
  // ─────────────────────────────────────────────
  async createList({ userId, name, iconKey }) {
    // extend if you add a WatchlistList model
    throw new Error("createList: not yet implemented");
  }
}

module.exports = new WatchlistService();