const { faker } = require('@faker-js/faker');
const bcrypt = require('bcryptjs');
const { v4: uuidv4 } = require('uuid');

module.exports = {
  up: async (queryInterface, Sequelize) => {
    console.log('Starting database seeding...');

    // Clear existing data
    // await clearExistingData(queryInterface);

    // Seed in phases respecting foreign key constraints
    await seedStores(queryInterface);
    await seedCategories(queryInterface);
    const accounts = await seedAccounts(queryInterface);
    await seedWallets(queryInterface, accounts);
    await seedProducts(queryInterface, accounts);
    await seedReviews(queryInterface, accounts);
    await seedAccountReviews(queryInterface, accounts);
    await seedProductReviews(queryInterface);
    await seedTransactions(queryInterface, accounts);
    await seedBids(queryInterface, accounts);
    const orders = await seedOrders(queryInterface, accounts);
    await seedOrderProducts(queryInterface, orders);
    await seedOrderTransactions(queryInterface);
    const conversations = await seedConversations(queryInterface, accounts);
    await seedMessages(queryInterface, accounts, conversations);
    await seedAttachments(queryInterface);

    // Seed new tables
    await seedActivityLogs(queryInterface, accounts);
    await seedNotifications(queryInterface, accounts);
    await seedReferrals(queryInterface, accounts);

    console.log('Database seeding completed successfully!');
  },

  down: async (queryInterface, Sequelize) => {
    // No need for down in seeders
  },
};

async function clearExistingData(queryInterface) {
  console.log('Clearing existing data...');
  const tables = [
    'attachments',
    'messages',
    'conversations',
    'order_transactions',
    'order_products',
    'orders',
    'transactions',
    'bids',
    'product_reviews',
    'account_reviews',
    'reviews',
    'products',
    'wallets',
    'accounts',
    'categories',
  ];

  // Disable foreign key checks temporarily
  await queryInterface.sequelize.query(
    'SET session_replication_role = replica;'
  );

  for (const table of tables) {
    try {
      await queryInterface.sequelize.query(
        `TRUNCATE TABLE "${table}" CASCADE;`
      );
      console.log(`Cleared table: ${table}`);
    } catch (error) {
      console.error(`Error clearing table ${table}:`, error.message);
    }
  }

  // Re-enable foreign key checks
  await queryInterface.sequelize.query(
    'SET session_replication_role = DEFAULT;'
  );
}

async function seedStores(queryInterface) {
  console.log('Seeding stores...');
  const stores = [];
  for (let i = 0; i < 10; i++) {
    const name = faker.company.name();
    const address = faker.location.streetAddress();
    const contact = faker.phone.number();
    stores.push({
      name,
      address,
      contact,
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }
  await queryInterface.bulkInsert('stores', stores);
}

async function seedActivityLogs(queryInterface, accounts) {
  console.log('Seeding activity logs...');
  const adminAccounts = accounts.filter(
    (a) => a.role === 'ADMIN' || a.role === 'SUPER_ADMIN'
  );
  const products = await queryInterface.sequelize.query(
    'SELECT id FROM products',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );
  const orders = await queryInterface.sequelize.query('SELECT id FROM orders', {
    type: queryInterface.sequelize.QueryTypes.SELECT,
  });
  const transactions = await queryInterface.sequelize.query(
    'SELECT id FROM transactions',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );

  const activityLogs = [];
  const actions = [
    'create',
    'update',
    'delete',
    'approve',
    'reject',
    'verify',
    'suspend',
    'ban',
    'activate',
    'deactivate',
  ];
  const targetTypes = [
    'user',
    'product',
    'order',
    'transaction',
    'store',
    'admin',
  ];

  for (let i = 0; i < 50; i++) {
    const targetType = faker.helpers.arrayElement(targetTypes);
    let targetId = null;

    // Assign appropriate target ID based on target type
    switch (targetType) {
      case 'user':
        targetId = faker.helpers.arrayElement(accounts).id;
        break;
      case 'product':
        targetId = faker.helpers.arrayElement(products).id;
        break;
      case 'order':
        targetId = faker.helpers.arrayElement(orders).id;
        break;
      case 'transaction':
        targetId = faker.helpers.arrayElement(transactions).id;
        break;
      case 'store':
        // Assuming stores are already seeded
        targetId = faker.number.int({ min: 1, max: 10 });
        break;
      case 'admin':
        targetId = faker.helpers.arrayElement(adminAccounts).id;
        break;
    }

    activityLogs.push({
      adminId: faker.helpers.arrayElement(adminAccounts).id,
      action: faker.helpers.arrayElement(actions),
      description: `${faker.helpers.arrayElement(actions)}d ${targetType}`,
      targetType,
      targetId,
      metadata: JSON.stringify({
        ip: faker.internet.ip(),
        changes: faker.datatype.boolean()
          ? {
              field: faker.helpers.arrayElement([
                'status',
                'price',
                'name',
                'email',
              ]),
              from: faker.word.adjective(),
              to: faker.word.adjective(),
            }
          : null,
      }),
      ipAddress: faker.internet.ip(),
      userAgent: faker.internet.userAgent(),
      createdAt: faker.date.recent({ days: 30 }),
      updatedAt: faker.date.recent({ days: 30 }),
    });
  }

  await queryInterface.bulkInsert('activity_logs', activityLogs);
}

async function seedNotifications(queryInterface, accounts) {
  console.log('Seeding notifications...');
  const notifications = [];
  const types = [
    'order_created',
    'order_accepted',
    'order_rejected',
    'order_shipped',
    'order_completed',
    'product_approved',
    'product_rejected',
    'payment_received',
    'referral_bonus',
    'general',
  ];

  for (let i = 0; i < 100; i++) {
    const userId = faker.helpers.arrayElement(accounts).id;
    const type = faker.helpers.arrayElement(types);

    notifications.push({
      userId,
      title: `${type.replace(/_/g, ' ').toUpperCase()}`,
      message: faker.lorem.sentence(),
      type,
      isRead: faker.datatype.boolean(),
      data: JSON.stringify({
        orderId: faker.number.int({ min: 1, max: 20 }),
        amount: faker.finance.amount(10, 1000, 2),
        product: faker.commerce.productName(),
      }),
      fcmToken: faker.string.alphanumeric(150),
      sentAt: faker.date.recent(),
      createdAt: faker.date.recent(),
      updatedAt: faker.date.recent(),
    });
  }

  await queryInterface.bulkInsert('notifications', notifications);
}

async function seedReferrals(queryInterface, accounts) {
  console.log('Seeding referrals...');
  const referrals = [];
  const userAccounts = accounts.filter((a) => a.role === 'USER');

  // Ensure we have enough accounts to create referrals
  if (userAccounts.length < 10) {
    console.log('Not enough user accounts to create referrals');
    return;
  }

  // Create referrals for first 10 users referring next 10 users
  for (let i = 0; i < 10; i++) {
    const referrerId = userAccounts[i].id;
    const referredId = userAccounts[i + 10].id;

    referrals.push({
      referrerId,
      referredId,
      bonusAmount: faker.finance.amount(100, 1000, 2),
      status: faker.helpers.arrayElement(['pending', 'completed', 'cancelled']),
      completedAt: faker.datatype.boolean() ? faker.date.recent() : null,
      createdAt: faker.date.recent(),
      updatedAt: faker.date.recent(),
    });
  }

  await queryInterface.bulkInsert('referrals', referrals);
}

async function seedCategories(queryInterface) {
  console.log('Seeding categories...');
  const categories = [
    { name: 'Apple', description: 'Devices by Apple' },
    { name: 'Speakers', description: 'Audio devices and accessories' },
    { name: 'Handband', description: 'Wearables' },
    { name: 'Mouse', description: 'Computer accesories' },
    { name: 'Mobile', description: 'Mobile devices and accessories' },
    { name: 'MacBook', description: "Apple's line of laptops" },
  ];

  await queryInterface.bulkInsert(
    'categories',
    categories.map((category) => ({
      ...category,
      createdAt: new Date(),
      updatedAt: new Date(),
    }))
  );
}

async function seedAccounts(queryInterface) {
  console.log('Seeding accounts...');
  const accounts = [];
  // const roles = ['USER'];

  for (let i = 0; i < 30; i++) {
    const firstName = faker.person.firstName();
    const lastName = faker.person.lastName();
    const authType = faker.helpers.arrayElement(['google', 'password']);

    accounts.push({
      firstName,
      lastName,
      authType,
      phone: faker.phone.number(),
      accountNumber: faker.finance.accountNumber(),
      bankName: faker.company.name(),
      bankCode: faker.finance.bic(),
      email: faker.internet.email({ firstName, lastName }),
      banned: faker.datatype.boolean(),
      suspensionReason: faker.datatype.boolean()
        ? faker.lorem.sentence()
        : null,
      suspendedAt: faker.datatype.boolean() ? faker.date.recent() : null,
      bannedAt: faker.datatype.boolean() ? faker.date.recent() : null,
      verificationCode: faker.string.alphanumeric(6),
      verificationCodeExpiry: faker.date.future(),
      passwordResetCode: faker.string.alphanumeric(6),
      passwordResetCodeExpiry: faker.date.future(),
      avatar: faker.image.avatar(),
      suspended: faker.datatype.boolean(),
      addresses: [
        faker.location.streetAddress(),
        faker.location.streetAddress(),
      ],
      referredBy: faker.datatype.boolean()
        ? faker.string.alphanumeric(8)
        : null,
      referralCode: faker.string.alphanumeric(8),
      uid: faker.string.uuid(),
      phoneVerified: faker.datatype.boolean(),
      emailVerified: faker.datatype.boolean(),
      verified: faker.datatype.boolean(),
      password: bcrypt.hashSync('password123', 10),
      twoFactorEnabled: faker.datatype.boolean(),
      twoFactorCode: faker.string.alphanumeric(6),
      twoFactorCodeExpiry: faker.date.future(),
      role: 'USER', // Distribute roles evenly
      badge: faker.datatype.boolean(),
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  // Insert admin accounts
  accounts.push({
    firstName: 'Admin',
    lastName: 'User',
    authType: 'password',
    email: 'oluwayimikaoladipupo@gmail.com',
    password: bcrypt.hashSync('admin123', 10),
    role: 'ADMIN',
    badge: faker.datatype.boolean(),
    emailVerified: true,
    verified: true,
    createdAt: new Date(),
    updatedAt: new Date(),
  });

  accounts.push({
    firstName: 'Super',
    lastName: 'Admin',
    authType: 'password',
    email: 'oladipupomichael9@gmail.com',
    password: bcrypt.hashSync('superadmin123', 10),
    role: 'SUPER_ADMIN',
    badge: faker.datatype.boolean(),
    verified: true,
    emailVerified: true,
    createdAt: new Date(),
    updatedAt: new Date(),
  });

  accounts.push({
    firstName: 'Adebanjo',
    lastName: 'Adebayo',
    authType: 'password',
    email: 'adebanjoadeniji5@gmail.com',
    password: bcrypt.hashSync('admin123', 10),
    role: 'ADMIN',
    badge: faker.datatype.boolean(),
    verified: true,
    emailVerified: true,
    createdAt: new Date(),
    updatedAt: new Date(),
  });

  accounts.push({
    firstName: 'Queensley',
    lastName: 'Ojenike',
    authType: 'password',
    email: 'ojenikequeensley@gmail.com',
    password: bcrypt.hashSync('Queensley001', 10),
    role: 'ADMIN',
    badge: faker.datatype.boolean(),
    verified: true,
    emailVerified: true,
    createdAt: new Date(),
    updatedAt: new Date(),
  });

  await queryInterface.bulkInsert('accounts', accounts);

  // Return the inserted accounts for reference
  return await queryInterface.sequelize.query('SELECT id, role FROM accounts', {
    type: queryInterface.sequelize.QueryTypes.SELECT,
  });
}

async function seedWallets(queryInterface, accounts) {
  console.log('Seeding wallets...');
  const wallets = [];
  const currencies = ['NGN', 'USD', 'EUR', 'GBP'];

  for (const account of accounts) {
    wallets.push({
      id: uuidv4(),
      balance: faker.finance.amount(0, 10000, 2),
      user: account.id,
      currency: faker.helpers.arrayElement(currencies),
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('wallets', wallets);

  // Update accounts with walletId
  for (const wallet of wallets) {
    await queryInterface.sequelize.query(
      `UPDATE accounts SET "walletId" = '${wallet.id}' WHERE id = ${wallet.user}`
    );
  }
}

const picsum = [
  'https://fdn2.gsmarena.com/vv/pics/samsung/samsung-galaxy-z-fold7-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/samsung/samsung-galaxy-z-fold7-2.jpg',
  'https://fdn2.gsmarena.com/vv/pics/apple/apple-iphone-16-pro-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/xiaomi/xiaomi-redmi-k80-ultra-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/google/google-pixel-9a-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/realme/realme-narzo-80-lite-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/asus/asus-zenfone-12-ultra-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/infinix/infinix-hot60-5g-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/tecno/tecno-pova7-pro-3.jpg',
];

const phoneBrands = [
  'Samsung',
  'Apple',
  'Google',
  'OnePlus',
  'Xiaomi',
  'Oppo',
  'Vivo',
  'Realme',
  'Tecno',
  'Infinix',
  'Huawei',
  'Nokia',
];
const laptopBrands = [
  'Apple',
  'Dell',
  'HP',
  'Lenovo',
  'Asus',
  'Acer',
  'MSI',
  'Razer',
  'Microsoft',
  'Samsung',
  'LG',
];
const phoneModels = [
  'Galaxy S23',
  'iPhone 15',
  'Pixel 8',
  '11T Pro',
  'Find X6',
  'X90 Pro',
  'GT Neo 5',
  'Camon 20',
  'Note 30',
  'Mate 60',
  'G42',
];
const laptopModels = [
  'MacBook Pro',
  'XPS 13',
  'Spectre x360',
  'ThinkPad X1',
  'ZenBook Pro',
  'Swift 3',
  'Stealth 16',
  'Blade 15',
  'Surface Laptop',
  'Galaxy Book',
  'Gram 17',
];

const phoneImages = [
  'https://fdn2.gsmarena.com/vv/pics/samsung/samsung-galaxy-z-fold7-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/samsung/samsung-galaxy-z-fold7-2.jpg',
  'https://fdn2.gsmarena.com/vv/pics/apple/apple-iphone-16-pro-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/xiaomi/xiaomi-redmi-k80-ultra-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/google/google-pixel-9a-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/realme/realme-narzo-80-lite-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/asus/asus-zenfone-12-ultra-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/infinix/infinix-hot60-5g-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/tecno/tecno-pova7-pro-3.jpg',
  'https://fdn2.gsmarena.com/vv/pics/huawei/huawei-p70-pro-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/oneplus/oneplus-12-1.jpg',
  'https://fdn2.gsmarena.com/vv/pics/oppo/oppo-find-x7-ultra-1.jpg',
];

const laptopImages = [
  'https://images.unsplash.com/photo-1517336714731-489689fd1ca8',
  'https://images.unsplash.com/photo-1537498425277-c283d32ef9db',
  'https://plus.unsplash.com/premium_photo-1681702156223-ea59bfbf1065?q=80&w=735&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
  'https://images.unsplash.com/photo-1484788984921-03950022c9ef?q=80&w=1232&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
  'https://images.unsplash.com/photo-1611186871348-b1ce696e52c9?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
  'https://images.unsplash.com/photo-1593642634315-48f5414c3ad9?q=80&w=1169&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
  'https://images.unsplash.com/photo-1460925895917-afdab827c52f?q=80&w=1115&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
];

async function seedProducts(queryInterface, accounts) {
  console.log('Seeding products...');
  const categories = await queryInterface.sequelize.query(
    'SELECT id FROM categories',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );

  const products = [];
  const vendorAccounts = accounts.filter((a) => a.role === 'USER');

  for (let i = 0; i < 50; i++) {
    const isPhone = faker.datatype.boolean();
    const brand = isPhone
      ? faker.helpers.arrayElement(phoneBrands)
      : faker.helpers.arrayElement(laptopBrands);
    const model = isPhone
      ? faker.helpers.arrayElement(phoneModels)
      : faker.helpers.arrayElement(laptopModels);

    const imageUrls = isPhone ? phoneImages : laptopImages;
    const mainImage = faker.helpers.arrayElement(imageUrls);

    const installmentPlans = faker.datatype.boolean()
      ? {
          plans: [
            { months: 3, percentage: 10 },
            { months: 6, percentage: 15 },
            { months: 12, percentage: 25 },
          ],
        }
      : null;

    const imageCount = faker.number.int({ min: 0, max: 5 });
    const otherImages =
      imageCount > 0
        ? Array.from({ length: imageCount }, () =>
            faker.helpers.arrayElement(imageUrls)
          )
        : null;

    const specs = {
      storage: isPhone
        ? faker.helpers.arrayElement(['128GB', '256GB', '512GB', '1TB'])
        : faker.helpers.arrayElement([
            '256GB SSD',
            '512GB SSD',
            '1TB SSD',
            '2TB SSD',
          ]),
      ram: isPhone
        ? faker.helpers.arrayElement(['6GB', '8GB', '12GB', '16GB'])
        : faker.helpers.arrayElement(['8GB', '16GB', '32GB', '64GB']),
      processor: isPhone
        ? faker.helpers.arrayElement([
            'Snapdragon 8 Gen 2',
            'Apple A16 Bionic',
            'Dimensity 9200',
            'Exynos 2200',
          ])
        : faker.helpers.arrayElement([
            'Intel Core i7',
            'Intel Core i9',
            'AMD Ryzen 7',
            'AMD Ryzen 9',
            'Apple M2',
          ]),
      display: isPhone
        ? `${faker.number.int({ min: 6, max: 7 })}.${faker.number.int({
            min: 1,
            max: 9,
          })} inch AMOLED`
        : `${faker.number.int({ min: 13, max: 17 })}.${faker.number.int({
            min: 0,
            max: 9,
          })} inch ${faker.helpers.arrayElement(['IPS', 'OLED', 'Retina'])}`,
      battery: isPhone
        ? `${faker.number.int({ min: 4000, max: 6000 })} mAh`
        : `${faker.number.int({ min: 50, max: 100 })} Wh`,
      os: isPhone
        ? faker.helpers.arrayElement(['Android 13', 'iOS 16'])
        : faker.helpers.arrayElement([
            'Windows 11',
            'macOS Ventura',
            'Chrome OS',
          ]),
      color: faker.color.human(),
    };

    products.push({
      user: faker.helpers.arrayElement(vendorAccounts).id,
      brand,
      name: `${brand} ${model}`,
      description: `The ${brand} ${model} features ${specs.display} display, ${specs.processor} processor, ${specs.ram} RAM and ${specs.storage} storage.`,
      price: isPhone
        ? faker.finance.amount(200, 1500, 2)
        : faker.finance.amount(500, 3500, 2),
      metaData: JSON.stringify(specs),
      imageUrl: mainImage,
      otherImages,
      stock: faker.number.int({ min: 0, max: 100 }),
      isActive: faker.datatype.boolean(),
      swappable: faker.datatype.boolean(),
      installment_available: installmentPlans !== null,
      installmentTotalAmount: installmentPlans
        ? isPhone
          ? faker.finance.amount(300, 2000, 2)
          : faker.finance.amount(600, 4000, 2)
        : null,
      installment_plans: installmentPlans
        ? JSON.stringify(installmentPlans)
        : null,
      views: faker.number.int({ min: 0, max: 1000 }),
      approved: faker.datatype.boolean(),
      categoryId: faker.helpers.arrayElement(categories).id,
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('products', products);
}

async function seedReviews(queryInterface, accounts) {
  console.log('Seeding reviews...');
  const reviews = [];

  for (let i = 0; i < 100; i++) {
    reviews.push({
      rating: faker.number.int({ min: 1, max: 5 }),
      comment: faker.datatype.boolean() ? faker.lorem.paragraph() : null,
      user: faker.helpers.arrayElement(accounts).id,
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('reviews', reviews);
}

async function seedAccountReviews(queryInterface, accounts) {
  console.log('Seeding account reviews...');
  const reviews = await queryInterface.sequelize.query(
    'SELECT id FROM reviews ORDER BY RANDOM() LIMIT 30',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );

  const accountReviews = [];

  for (let i = 0; i < reviews.length; i++) {
    accountReviews.push({
      accountId: faker.helpers.arrayElement(accounts).id,
      reviewId: reviews[i].id,
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('account_reviews', accountReviews);
}

async function seedProductReviews(queryInterface) {
  console.log('Seeding product reviews...');
  const products = await queryInterface.sequelize.query(
    'SELECT id FROM products',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );
  const reviews = await queryInterface.sequelize.query(
    'SELECT id FROM reviews ORDER BY RANDOM() LIMIT 70',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );

  const productReviews = [];

  for (let i = 0; i < reviews.length; i++) {
    productReviews.push({
      productId: faker.helpers.arrayElement(products).id,
      reviewId: reviews[i].id,
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('product_reviews', productReviews);
}

async function seedBids(queryInterface, accounts) {
  console.log('Seeding bids...');
  const products = await queryInterface.sequelize.query(
    'SELECT id FROM products WHERE swappable = true',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );

  // Get purchase transactions that could be associated with bids
  const transactions = await queryInterface.sequelize.query(
    "SELECT id FROM transactions WHERE purpose = 'purchase' ORDER BY RANDOM() LIMIT 20",
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );

  const bids = [];

  for (let i = 0; i < 20; i++) {
    const product = faker.helpers.arrayElement(products);
    const swapProduct = faker.helpers.arrayElement(
      products.filter((p) => p.id !== product.id)
    );

    bids.push({
      amount: faker.finance.amount(10, 1000, 2),
      status: faker.helpers.arrayElement(['pending', 'accepted', 'rejected']),
      swapWith: faker.datatype.boolean() ? swapProduct.id : null,
      product: product.id,
      metaData: JSON.stringify({
        message: faker.lorem.sentence(),
        condition: faker.helpers.arrayElement(['new', 'used', 'refurbished']),
      }),
      user: faker.helpers.arrayElement(accounts).id,
      transactionId: transactions[i]?.id || null, // Assign transaction if available
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('bids', bids);
}
async function seedTransactions(queryInterface, accounts) {
  console.log('Seeding transactions...');
  const transactions = [];

  for (let i = 0; i < 50; i++) {
    const sender = faker.helpers.arrayElement(accounts);
    const receiver = faker.helpers.arrayElement(
      accounts.filter((a) => a.id !== sender.id)
    );

    transactions.push({
      amount: faker.finance.amount(10, 5000, 2),
      reference: `TXN-${faker.string.alphanumeric(10).toUpperCase()}`,
      type: faker.helpers.arrayElement(['credit', 'debit']),
      method: faker.helpers.arrayElement(['wallet', 'paystack']),
      mode: faker.helpers.arrayElement(['installment', 'full']),
      purpose: faker.helpers.arrayElement([
        'deposit',
        'withdrawal',
        'purchase',
        'refund',
        'referral',
      ]),
      status: faker.helpers.arrayElement([
        'success',
        'failed',
        'pending',
        'abandoned',
      ]),
      senderId: sender.id,
      receiverId: receiver.id,
      paystackData: JSON.stringify({
        authorization_url: faker.internet.url(),
        access_code: faker.string.alphanumeric(10),
        reference: `PS-${faker.string.alphanumeric(10)}`,
      }),
      description: faker.finance.transactionDescription(),
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('transactions', transactions);
}

async function seedOrders(queryInterface, accounts) {
  console.log('Seeding orders...');
  const products = await queryInterface.sequelize.query(
    'SELECT id, price FROM products',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );
  // console.log(products);

  const orders = [];
  const userAccounts = accounts.filter((a) => a.role === 'USER');

  for (let i = 0; i < 20; i++) {
    const orderProducts = faker.helpers.arrayElements(products, {
      min: 1,
      max: 5,
    });
    const totalAmount = orderProducts.reduce(
      (sum, p) => sum + parseFloat(p.price),
      0
    );
    const swapped = faker.datatype.boolean();

    orders.push({
      user: faker.helpers.arrayElement(userAccounts).id,
      totalAmount,
      amountPaid: swapped ? 0 : faker.finance.amount(0, totalAmount, 2),
      swapped,
      swap: swapped ? orderProducts.map((p) => p.id) : null,
      address: faker.location.streetAddress(),
      status: faker.helpers.arrayElement([
        'pending',
        'completed',
        'cancelled',
        'rejected',
        'accepted',
        'partially paid',
        'paid',
        'in progress',
      ]),
      paymentCompleted: faker.datatype.boolean(),
      paymentMode: faker.helpers.arrayElement(['installment', 'full']),
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('orders', orders);

  // Return the inserted orders for reference
  return await queryInterface.sequelize.query('SELECT id, user FROM orders', {
    type: queryInterface.sequelize.QueryTypes.SELECT,
  });
}

async function seedOrderProducts(queryInterface, orders) {
  console.log('Seeding order products...');
  const products = await queryInterface.sequelize.query(
    'SELECT id FROM products',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );

  const orderProducts = [];

  for (const order of orders) {
    const orderProds = faker.helpers.arrayElements(products, {
      min: 1,
      max: 5,
    });

    for (let i = 0; i < orderProds.length; i++) {
      orderProducts.push({
        orderId: order.id,
        productId: orderProds[i].id,
        quantity: faker.number.int({ min: 1, max: 3 }),
        createdAt: new Date(),
        updatedAt: new Date(),
      });
    }
  }

  await queryInterface.bulkInsert('order_products', orderProducts);
}

async function seedOrderTransactions(queryInterface) {
  console.log('Seeding order transactions...');
  const orders = await queryInterface.sequelize.query('SELECT id FROM orders', {
    type: queryInterface.sequelize.QueryTypes.SELECT,
  });
  const transactions = await queryInterface.sequelize.query(
    "SELECT id FROM transactions WHERE purpose = 'purchase' OR purpose = 'refund'",
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );

  const orderTransactions = [];

  for (let i = 0; i < Math.min(orders.length, transactions.length); i++) {
    orderTransactions.push({
      orderId: orders[i].id,
      transactionId: transactions[i].id,
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('order_transactions', orderTransactions);
}

async function seedConversations(queryInterface, accounts) {
  console.log('Seeding conversations...');
  const adminAccounts = accounts.filter(
    (a) => a.role === 'ADMIN' || a.role === 'SUPER_ADMIN'
  );
  const userAccounts = accounts.filter((a) => a.role === 'USER');
  // console.log(adminAccounts);
  // console.log(userAccounts);

  const conversations = [];

  for (let i = 0; i < 15; i++) {
    conversations.push({
      user: faker.helpers.arrayElement(userAccounts).id,
      admin: faker.helpers.arrayElement(adminAccounts).id,
      subject: faker.lorem.sentence(),
      roomId: faker.string.uuid(),
      status: faker.helpers.arrayElement(['open', 'closed', 'pending']),
      lastMessageAt: faker.date.recent(),
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('conversations', conversations);

  // Return the inserted conversations for reference
  return await queryInterface.sequelize.query(
    'SELECT id, user, admin FROM conversations',
    {
      type: queryInterface.sequelize.QueryTypes.SELECT,
    }
  );
}

async function seedMessages(queryInterface, accounts) {
  console.log('Seeding messages...');
  const messages = [];
  const conversations = await queryInterface.sequelize.query(
    'SELECT * FROM conversations',
    {
      type: queryInterface.sequelize.QueryTypes.SELECT,
    }
  );

  // console.log(conversations);

  for (const conversation of conversations) {
    const numMessages = faker.number.int({ min: 3, max: 10 });
    let senderId = conversation.user;
    // console.log(senderId);
    // console.log(conversation);

    for (let i = 0; i < numMessages; i++) {
      // Alternate between user and admin
      senderId =
        senderId === conversation.user ? conversation.admin : conversation.user;

      messages.push({
        conversationId: conversation.id,
        senderId,
        content: faker.lorem.paragraph(),
        isRead: faker.datatype.boolean(),
        createdAt: new Date(),
        updatedAt: new Date(),
      });
    }
  }

  await queryInterface.bulkInsert('messages', messages);
}

async function seedAttachments(queryInterface) {
  console.log('Seeding attachments...');
  const messages = await queryInterface.sequelize.query(
    'SELECT id FROM messages ORDER BY RANDOM() LIMIT 20',
    { type: queryInterface.sequelize.QueryTypes.SELECT }
  );

  const attachments = [];
  const fileTypes = ['image', 'document', 'video', 'audio'];

  for (const message of messages) {
    attachments.push({
      message: message.id,
      fileUrl: faker.internet.url(),
      fileType: faker.helpers.arrayElement(fileTypes),
      fileName: faker.system.fileName(),
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  }

  await queryInterface.bulkInsert('attachments', attachments);
}
