/**
 * Sequelize Models Index
 * NOTE: Ensure consistent file naming on disk:
 * WatchlistAlert.js vs WatchListAlert.js must match EXACT casing
 * (Windows is case-insensitive but Node/TypeScript enforces consistency)
 */

const { sequelize } = require('../config/database');

// =========================
// Core / System Models
// =========================
const TestModel = require('./Test');
const SettingModel = require('./Setting');
const SessionModel = require('./Session');
const AdminModel = require('./Admin');
const AdminSessionModel = require('./AdminSession');
const AdminOTPModel = require('./AdminOTP');
const ApiKeyModel = require('./ApiKey');

// OTP / Auth
const OTPModel = require('./OTP');
const EmailOTPModel = require('./EmailOTP');

// =========================
// User Models
// =========================
const UserModel = require('./User');
const UserBalanceModel = require('./UserBalance');

// =========================
// Wallet / Finance
// =========================
const WalletModel = require('./Wallet');
const WalletAddressModel = require('./WalletAddress');
const WalletLedgerModel = require('./WalletLedger');
const TransactionModel = require('./Transaction');
const PaymentMethodModel = require('./PaymentMethod')
const WithdrawalMethodModel = require('./WithdrawalMethod')

// =========================
// Assets / Markets
// =========================
const AssetModel = require('./Asset');
const AssetHoldingModel = require('./AssetHolding');
const AssetLotModel = require('./AssetLot');
const CoinModel = require('./Coin');
const NetworkModel = require('./Network');
const CoinNetworkModel = require('./CoinNetwork');
const NetworkAddressModel = require('./NetworkAddress');

const MarketModel = require('./Market');
const MarketPairModel = require('./MarketPair');
const CoinMarketModel = require('./CoinMarket');

const SymbolStatsModel = require('./SymbolStats');
const MarketStatsModel = require('./MarketStats');
const Price1mModel = require('./Price1m');

// =========================
// Trading
// =========================
const TradingPairModel = require('./TradingPair');
const TradeHistoryModel = require('./TradeHistory');
const TradeSymbolModel = require('./TradeSymbol');

const SpotOrderModel = require('./SpotOrder');
const SpotTradeModel = require('./SpotTrade');

const DerivativeAccountModel = require('./DerivativeAccount');
const DerivativeOrderModel = require('./DerivativeOrder');
const DerivativePositionModel = require('./DerivativePosition');
const DerivativeTradeModel = require('./DerivativeTrade');

const OptionOrderModel = require('./OptionOrder');
const OptionPositionModel = require('./OptionPosition');
const OptionChainModel = require('./OptionChain');

const BinaryTradeModel = require('./BinaryTrade');

// =========================
// Plans / Coupons
// =========================
const PlanModel = require('./Plan');
const UserPlanModel = require('./UserPlan');
const CouponModel = require('./Coupon');

// =========================
// Notifications / Alerts
// =========================
const NotificationModel = require('./Notification');
const PriceAlertModel = require('./PriceAlert');

const WatchlistModel = require('./Watchlist');
const WatchlistAlertModel = require('./WatchListAlert');

// =========================
// Copy Trading
// =========================
const TraderProfileModel = require('./TraderProfile');
const CopyRelationModel = require('./CopyRelation');
const CopyTradeModel = require('./CopyTrade');

// =========================
// Referral
// =========================
const ReferralModel = require('./Referral');
const ReferralEarningModel = require('./ReferralEarning');

// =========================
// Signals
// =========================
const SignalModel = require('./Signal');
const SignalProviderModel = require('./SignalProvider');
const SignalSubscriptionModel = require('./SignalSubscription');

// =========================
// Bots
// =========================
const BotMarketplaceModel = require('./BotMarketplace');
const BotInstanceModel = require('./BotInstance');
const BotOrderModel = require('./BotOrder');
const BotPositionModel = require('./BotPosition');
const BotEventModel = require('./BotEvent');

// =========================
// KYC
// =========================
const KycSubmissionModel = require('./KycSubmission');
const KycDocumentModel = require('./KycDocument');

// =========================
// Tickets / Support
// =========================
const TicketModel = require('./Ticket');
const TicketMessageModel = require('./TicketMessage');

// =========================
// Init Models
// =========================
const Test = TestModel(sequelize);
const Admin = AdminModel(sequelize);
const AdminSession = AdminSessionModel(sequelize);
const Session = SessionModel(sequelize);
const ApiKey = ApiKeyModel(sequelize);
const EmailOTP = EmailOTPModel(sequelize);
const OTP = OTPModel(sequelize);
const AdminOTP = AdminOTPModel(sequelize);
const Setting = SettingModel(sequelize);

const User = UserModel(sequelize);
const UserBalance = UserBalanceModel(sequelize);

const Wallet = WalletModel(sequelize);
const WalletAddress = WalletAddressModel(sequelize);
const WalletLedger = WalletLedgerModel(sequelize);
const Transaction = TransactionModel(sequelize);
const WithdrawalMethod = WithdrawalMethodModel(sequelize)
const PaymentMethod = PaymentMethodModel(sequelize)

const Asset = AssetModel(sequelize);
const AssetHolding = AssetHoldingModel(sequelize);
const AssetLot = AssetLotModel(sequelize);
const Coin = CoinModel(sequelize);
const Network = NetworkModel(sequelize);
const CoinNetwork = CoinNetworkModel(sequelize);
const NetworkAddress = NetworkAddressModel(sequelize);

const Market = MarketModel(sequelize);
const MarketPair = MarketPairModel(sequelize);
const CoinMarket = CoinMarketModel(sequelize);

const SymbolStats = SymbolStatsModel(sequelize);
const MarketStats = MarketStatsModel(sequelize);
const Price1m = Price1mModel(sequelize);

const TradingPair = TradingPairModel(sequelize);
const TradeHistory = TradeHistoryModel(sequelize);
const TradeSymbol = TradeSymbolModel(sequelize);

const SpotOrder = SpotOrderModel(sequelize);
const SpotTrade = SpotTradeModel(sequelize);

const DerivativeAccount = DerivativeAccountModel(sequelize);
const DerivativeOrder = DerivativeOrderModel(sequelize);
const DerivativePosition = DerivativePositionModel(sequelize);
const DerivativeTrade = DerivativeTradeModel(sequelize);

const OptionOrder = OptionOrderModel(sequelize);
const OptionPosition = OptionPositionModel(sequelize);
const OptionChain = OptionChainModel(sequelize);

const BinaryTrade = BinaryTradeModel(sequelize);

const Plan = PlanModel(sequelize);
const UserPlan = UserPlanModel(sequelize);
const Coupon = CouponModel(sequelize);

const Notification = NotificationModel(sequelize);
const PriceAlert = PriceAlertModel(sequelize);
const Watchlist = WatchlistModel(sequelize);
const WatchlistAlert = WatchlistAlertModel(sequelize);

const TraderProfile = TraderProfileModel(sequelize);
const CopyRelation = CopyRelationModel(sequelize);
const CopyTrade = CopyTradeModel(sequelize);

const Referral = ReferralModel(sequelize);
const ReferralEarning = ReferralEarningModel(sequelize);

const Signal = SignalModel(sequelize);
const SignalProvider = SignalProviderModel(sequelize);
const SignalSubscription = SignalSubscriptionModel(sequelize);

const BotMarketplace = BotMarketplaceModel(sequelize);
const BotInstance = BotInstanceModel(sequelize);
const BotOrder = BotOrderModel(sequelize);
const BotPosition = BotPositionModel(sequelize);
const BotEvent = BotEventModel(sequelize);

const KycSubmission = KycSubmissionModel(sequelize);
const KycDocument = KycDocumentModel(sequelize);

const Ticket = TicketModel(sequelize);
const TicketMessage = TicketMessageModel(sequelize);

// =========================
// Associations
// =========================

// USER
User.hasMany(Wallet, { foreignKey: 'userId', as: 'wallets' });
User.hasOne(Wallet, { foreignKey: 'coinId', as: 'wallet' }); // FIX: restored missing association
User.hasMany(Transaction, { foreignKey: 'userId', as: 'transactions' });
User.hasMany(Notification, { foreignKey: 'userId', as: 'notifications' });
User.hasMany(PriceAlert, { foreignKey: 'userId', as: 'priceAlerts' });
User.hasMany(Session, { foreignKey: 'userId', as: 'sessions' });
User.hasMany(ApiKey, { foreignKey: 'userId', as: 'apiKeys' });
User.hasMany(AssetHolding, { foreignKey: 'userId', as: 'assetHolding' });
User.hasMany(AssetLot, { foreignKey: 'userId', as: 'assetLot' });
User.hasOne(UserBalance, { foreignKey: 'userId', as: 'balance' });
User.hasMany(UserPlan, { foreignKey: 'userId', as: 'userPlan' });
User.hasMany(BotInstance, { foreignKey: 'userId', as: 'botInstances' });

User.belongsTo(User, { foreignKey: 'referredById', as: 'referrer' });
User.hasMany(User, { foreignKey: 'referredById', as: 'referrals' });

// ADMIN
AdminOTP.belongsTo(Admin, { foreignKey: 'adminId', as: 'admin' });
AdminSession.belongsTo(Admin, { foreignKey: 'adminId', as: 'admin' });

// WALLET
UserBalance.belongsTo(User, { foreignKey: 'userId', as: 'user' });
Wallet.belongsTo(User, { foreignKey: 'userId', as: 'user' });
Wallet.belongsTo(Asset, { foreignKey: 'coinId', as: 'coin' });
Wallet.hasMany(Transaction, { foreignKey: 'walletId', as: 'transactions' });

WalletAddress.belongsTo(User, { foreignKey: 'userId', as: 'user' });
WalletAddress.belongsTo(Asset, { foreignKey: 'coinId', as: 'coin' });
WalletAddress.belongsTo(Network, { foreignKey: 'networkId', as: 'network' });
WalletAddress.belongsTo(NetworkAddress, { foreignKey: 'networkAddressId', as: 'networkAddress' });

// TRANSACTION
Transaction.belongsTo(User, { foreignKey: 'userId', as: 'user' });
Transaction.belongsTo(Wallet, { foreignKey: 'walletId', as: 'wallet' });

// ASSETS
AssetHolding.belongsTo(User, { foreignKey: 'userId', as: 'user' });
AssetHolding.belongsTo(MarketPair, { foreignKey: 'assetId', as: 'asset' });
AssetLot.belongsTo(MarketPair, { foreignKey: 'assetId', as: 'pair' });
AssetLot.belongsTo(User, { foreignKey: 'userId', as: 'user' });

MarketPair.belongsTo(Asset, { foreignKey: 'baseAssetId', as: 'base' });
MarketPair.belongsTo(Asset, { foreignKey: 'quoteAssetId', as: 'quote' });
MarketPair.hasOne(AssetHolding, { foreignKey: 'assetId', as: 'holdings' }); // FIX: restored missing association
MarketPair.hasOne(SymbolStats, { foreignKey: 'asset_id', as: 'rate' });
MarketPair.hasMany(AssetLot, { foreignKey: 'assetId', as: 'lots' });

// COIN NETWORK
CoinNetwork.belongsTo(Asset, { foreignKey: 'coin_id', as: 'coin' });
CoinNetwork.belongsTo(Network, { foreignKey: 'network_id', as: 'network' });
Asset.hasMany(CoinNetwork, { foreignKey: 'coin_id', as: 'coinNetwork' }); // FIX: restored with correct coin_id FK
Network.hasMany(CoinNetwork, { foreignKey: 'network_id', as: 'coinNetwork' }); // FIX: restored missing association
Asset.hasMany(CoinNetwork, { foreignKey: 'coinId', as: 'networks' });

NetworkAddress.belongsTo(Network, { foreignKey: 'networkId', as: 'network' });

// MARKET
CoinMarket.belongsTo(Asset, { foreignKey: 'symbol', as: 'asset' });
Asset.hasOne(MarketStats, { foreignKey: 'pairId', as: 'stats' });

SymbolStats.belongsTo(Asset, { foreignKey: 'asset_id', as: 'asset' });
MarketStats.belongsTo(Asset, { foreignKey: 'pairId', as: 'asset' });
Price1m.belongsTo(Coin, { foreignKey: 'coin_id', as: 'coin' });
Price1m.belongsTo(Asset, { foreignKey: 'asset_id', as: 'asset' });

// NOTIFICATIONS
Notification.belongsTo(User, { foreignKey: 'userId', as: 'user' });

// PRICE ALERT
PriceAlert.belongsTo(User, { foreignKey: 'userId', as: 'user' });

// REFERRAL
Referral.belongsTo(User, { foreignKey: 'referrerId', as: 'referrer' });
Referral.belongsTo(User, { foreignKey: 'referredId', as: 'referred' });
Referral.hasMany(ReferralEarning, { foreignKey: 'referralId', as: 'earnings' });
ReferralEarning.belongsTo(Referral, { foreignKey: 'referralId', as: 'referral' });

// COPY TRADE
TraderProfile.hasMany(CopyRelation, { foreignKey: 'traderProfileId', as: 'copiers' });
CopyRelation.belongsTo(User, { foreignKey: 'copierId', as: 'copier' });
CopyRelation.belongsTo(TraderProfile, { foreignKey: 'traderId', as: 'trader' });
CopyRelation.belongsTo(TraderProfile, { foreignKey: 'traderProfileId', as: 'traderProfile' });
CopyTrade.belongsTo(TraderProfile, { foreignKey: 'traderId', as: 'trader' });
CopyTrade.belongsTo(MarketPair, { foreignKey: 'pairId', as: 'pair' });

// TRADING HISTORY
TradeSymbol.hasMany(TradeHistory, { foreignKey: 'pairId', as: 'history' });
TradeHistory.belongsTo(TradeSymbol, { foreignKey: 'pairId', as: 'symbol' });
TradeHistory.belongsTo(User, { foreignKey: 'userId', as: 'user' });
TradeHistory.belongsTo(MarketPair, { foreignKey: 'pairId', as: 'pair' });

// TRADING PAIR
TradingPair.belongsTo(Asset, { foreignKey: 'baseAsset', as: 'baseAssetData' });   // FIX: restored missing association
TradingPair.belongsTo(Asset, { foreignKey: 'quoteAsset', as: 'quoteAssetData' }); // FIX: restored missing association

// BOT
BotMarketplace.hasMany(BotInstance, { foreignKey: 'marketplaceBotId', as: 'botInstances' }); // FIX: restored missing association
BotInstance.belongsTo(User, { foreignKey: 'userId', as: 'user' });
BotInstance.belongsTo(BotMarketplace, { foreignKey: 'marketplaceBotId', as: 'bot' });
BotInstance.hasMany(BotPosition, { foreignKey: 'botInstanceId', as: 'botPositions' });
BotInstance.hasMany(BotEvent, { foreignKey: 'botInstanceId', as: 'botEvents' });
BotInstance.hasMany(BotOrder, { foreignKey: 'botInstanceId', as: 'botOrders' });

BotPosition.belongsTo(BotInstance, { foreignKey: 'botInstanceId', as: 'botInstance' });
BotEvent.belongsTo(BotInstance, { foreignKey: 'botInstanceId', as: 'botInstance' });
BotOrder.belongsTo(BotInstance, { foreignKey: 'botInstanceId', as: 'botInstance' });

// SIGNALS
SignalProvider.hasMany(Signal, { foreignKey: 'providerId', as: 'signals' });
SignalProvider.hasMany(SignalSubscription, { foreignKey: 'providerId', as: 'subscriptions' });
SignalSubscription.belongsTo(User, { foreignKey: 'userId', as: 'user' });
SignalSubscription.belongsTo(SignalProvider, { foreignKey: 'providerId', as: 'provider' });
Signal.belongsTo(SignalProvider, { foreignKey: 'providerId', as: 'provider' });
Signal.belongsTo(MarketPair, { foreignKey: 'pair', as: 'pairs' });

// WATCHLIST
Watchlist.belongsTo(User, { foreignKey: 'userId', as: 'user' });
Watchlist.belongsTo(MarketPair, { foreignKey: 'assetId', as: 'pair' });
Watchlist.hasMany(WatchlistAlert, { foreignKey: 'watchlistId', as: 'alerts' });
WatchlistAlert.belongsTo(Watchlist, { foreignKey: 'watchlistId', as: 'watchlist' });
WatchlistAlert.belongsTo(User, { foreignKey: 'userId', as: 'user' });

// SPOT
SpotOrder.belongsTo(MarketPair, { foreignKey: 'market_id', as: 'pair' });
SpotTrade.belongsTo(MarketPair, { foreignKey: 'market_id', as: 'pair' });

// DERIVATIVES
DerivativeOrder.belongsTo(MarketPair, { foreignKey: 'market_id', as: 'pair' });
DerivativeOrder.hasOne(DerivativePosition, { foreignKey: 'order_id', as: 'position' });
DerivativePosition.belongsTo(MarketPair, { foreignKey: 'market_id', as: 'pair' });
DerivativePosition.belongsTo(DerivativeOrder, { foreignKey: 'order_id', as: 'order' });
DerivativePosition.belongsTo(User, { foreignKey: 'userId', as: 'user' });

// BINARY
BinaryTrade.belongsTo(MarketPair, { foreignKey: 'assetId', as: 'pair' }); // FIX: restored missing association

// OPTIONS
OptionPosition.belongsTo(Asset, { foreignKey: 'assetId', as: 'asset' });
OptionPosition.belongsTo(User, { foreignKey: 'userId', as: 'user' });
OptionOrder.belongsTo(Asset, { foreignKey: 'assetId', as: 'asset' });
OptionOrder.belongsTo(User, { foreignKey: 'userId', as: 'user' });

// KYC
KycSubmission.belongsTo(User, { foreignKey: 'userId', as: 'user' });
KycSubmission.hasMany(KycDocument, { foreignKey: 'submissionId', as: 'documents' });
KycDocument.belongsTo(User, { foreignKey: 'userId', as: 'user' });
KycDocument.belongsTo(KycSubmission, { foreignKey: 'submissionId', as: 'submission' });

// PLANS
UserPlan.belongsTo(User, { foreignKey: 'userId', as: 'user' });
UserPlan.belongsTo(Plan, { foreignKey: 'planId', as: 'plan' });
Plan.hasMany(UserPlan, { foreignKey: 'planId', as: 'userPlan' });

// SESSION & API KEYS
Session.belongsTo(User, { foreignKey: 'userId', as: 'user' });
ApiKey.belongsTo(User, { foreignKey: 'userId', as: 'user' });

// TICKETS
Ticket.belongsTo(User, { foreignKey: 'userId' });
Ticket.hasMany(TicketMessage, { foreignKey: 'ticketId', as: 'messages' });
TicketMessage.belongsTo(Ticket, { foreignKey: 'ticketId', as: 'ticket' });

// =========================
// Export
// =========================
module.exports = {
  sequelize,
  Test,
  Admin,
  AdminSession,
  Session,
  ApiKey,
  EmailOTP,
  OTP,
  AdminOTP,
  Setting,
  User,
  UserBalance,
  Wallet,
  WalletAddress,
  WalletLedger,
  Transaction,
  WithdrawalMethod,
  PaymentMethod,
  Asset,
  AssetHolding,
  AssetLot,
  Coin,
  Network,
  CoinNetwork,
  NetworkAddress,
  Market,
  MarketPair,
  CoinMarket,
  SymbolStats,
  MarketStats, // FIX: restored missing export
  Price1m,
  TradingPair,
  TradeHistory,
  TradeSymbol,
  SpotOrder,
  SpotTrade,
  DerivativeAccount,
  DerivativeOrder,
  DerivativeTrade,
  DerivativePosition,
  OptionPosition,
  OptionOrder,
  OptionChain,
  BinaryTrade,
  Plan,
  UserPlan,
  Coupon,
  Notification,
  PriceAlert,
  Watchlist,
  WatchlistAlert,
  TraderProfile,
  CopyRelation,
  CopyTrade,
  Referral,
  ReferralEarning,
  Signal,
  SignalProvider,
  SignalSubscription,
  BotMarketplace,
  BotInstance,
  BotOrder,
  BotPosition,
  BotEvent,
  KycSubmission,
  KycDocument,
  Ticket,
  TicketMessage,
};