const db = require('../db/models');
const Service_listingsDBApi = require('../db/api/service_listings');
const processFile = require("../middlewares/upload");
const ValidationError = require('./notifications/errors/validation');
const csv = require('csv-parser');
const axios = require('axios');
const config = require('../config');
const stream = require('stream');





module.exports = class Service_listingsService {
  static async purchase(id, currentUser) {
    const transaction = await db.sequelize.transaction();
    try {
      const service = await Service_listingsDBApi.findBy({ id }, { transaction });
      if (!service) throw new Error('Service not found');

      const job = await db.jobs.create({
        clientId: currentUser.id,
        title: `Order: ${service.title}`,
        description: service.description,
        budget: service.starting_price,
        status: 'In-Progress'
      }, { transaction });

      const client_fee = Number(service.starting_price) * 0.01;
      const freelancer_fee = Number(service.starting_price) * 0.005;
      const total_amount = Number(service.starting_price) + client_fee;

      const escrow = await db.escrow_transactions.create({
        jobId: job.id,
        clientId: currentUser.id,
        freelancerId: service.freelancerId,
        total_amount: total_amount,
        client_fee: client_fee,
        freelancer_fee: freelancer_fee,
        status: 'Held_in_Escrow'
      }, { transaction });

      await transaction.commit();
      return { job, escrow };
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  static async create(data, currentUser) {
    const transaction = await db.sequelize.transaction();
    try {
      await Service_listingsDBApi.create(
        data,
        {
          currentUser,
          transaction,
        },
      );

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  };

  static async bulkImport(req, res, sendInvitationEmails = true, host) {
    const transaction = await db.sequelize.transaction();

    try {
      await processFile(req, res);
      const bufferStream = new stream.PassThrough();
      const results = [];

      await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream

      await new Promise((resolve, reject) => {
        bufferStream
          .pipe(csv())
          .on('data', (data) => results.push(data))
          .on('end', async () => {
            console.log('CSV results', results);
            resolve();
          })
          .on('error', (error) => reject(error));
      })

      await Service_listingsDBApi.bulkImport(results, {
          transaction,
          ignoreDuplicates: true,
          validate: true,
          currentUser: req.currentUser
      });

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  static async update(data, id, currentUser) {
    const transaction = await db.sequelize.transaction();
    try {
      let service_listings = await Service_listingsDBApi.findBy(
        {id},
        {transaction},
      );

      if (!service_listings) {
        throw new ValidationError(
          'service_listingsNotFound',
        );
      }

      const updatedService_listings = await Service_listingsDBApi.update(
        id,
        data,
        {
          currentUser,
          transaction,
        },
      );

      await transaction.commit();
      return updatedService_listings;

    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  };

  static async deleteByIds(ids, currentUser) {
    const transaction = await db.sequelize.transaction();

    try {
      await Service_listingsDBApi.deleteByIds(ids, {
        currentUser,
        transaction,
      });

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  static async remove(id, currentUser) {
    const transaction = await db.sequelize.transaction();

    try {
      await Service_listingsDBApi.remove(
        id,
        {
          currentUser,
          transaction,
        },
      );

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  
};