import { PrismaClient, Role, User } from '@prisma/client';
import * as bcrypt from 'bcrypt';
import * as fs from 'fs';
import { parse } from 'csv-parse';

const prisma = new PrismaClient();

async function importEvents(userID: string) {
  const records: any[] = [];

  fs.createReadStream('./prisma/events.csv')
    .pipe(parse({ columns: true, skip_empty_lines: true }))
    .on('data', (row: any) => {
      records.push(row);
      // console.log('AICI ' + row);
    })
    .on('end', async () => {
      // Insert records into the database
      await prisma.event.createMany({
        data: records.map((record) => ({
          mdID: userID,
          name: record.Name,
          year: record.Year,
          drive: record.Drive,
        })),
      });

      console.log('Events imported successfully.');
    });
}

async function importCompanies() {
  const companies = new Map();
  const networks: any[] = [];

  fs.createReadStream('./prisma/companies.csv')
    .pipe(parse({ columns: true, skip_empty_lines: true }))
    .on('data', (row) => {
      // Extract company and network data
      const companyName = row['Company Name'];
      const category = row['Category'];
      const companyDescription = row['Description'];
      const networkName = row['Contact Name'];
      const networkEmail = row['Contact Email'];
      const networkPhone = row['Contact Phone'];
      const networkLinkedIn = row['Contact LinkedIn'];
      const networkFacebook = row['Contact Facebook'];
      const networkRole = row['Contact Role'];
      const networkIsActive = row['Contact IsActive'] === 'true';
      const networkIsPrimary = row['Contact IsPrimary'] === 'true';
      const networkNotes = row['Contact Notes'];

      if (!companies.has(companyName)) {
        companies.set(companyName, {
          name: companyName,
          category: category,
          description: companyDescription,
        });
      }

      networks.push({
        companyName,
        name: networkName,
        email: networkEmail,
        phone: networkPhone,
        linkedIn: networkLinkedIn === '' ? null : networkLinkedIn,
        facebook: networkFacebook === '' ? null : networkFacebook,
        role: networkRole,
        isActive: networkIsActive,
        isPrimary: networkIsPrimary,
        notes: networkNotes,
      });
    })
    .on('end', async () => {
      // Insert companies into the database
      const companyEntries = Array.from(companies.values());
      await prisma.company.createMany({
        data: companyEntries,
        skipDuplicates: true,
      });

      // Map company names to IDs
      const companyNames = companyEntries.map((company) => company.name);
      const companyIdMap = new Map();
      const fetchedCompanies = await prisma.company.findMany({
        where: { name: { in: companyNames } },
        select: { id: true, name: true },
      });
      fetchedCompanies.forEach((company) =>
        companyIdMap.set(company.name, company.id),
      );

      // Insert networks into the database
      await prisma.network.createMany({
        data: networks.map((network) => ({
          companyID: companyIdMap.get(network.companyName),
          name: network.name,
          email: network.email,
          phone: network.phone,
          linkedIn: network.linkedIn,
          facebook: network.facebook,
          role: network.role,
          isActive: network.isActive,
          isPrimary: network.isPrimary,
          notes: network.notes,
        })),
      });

      console.log('Companies and networks imported successfully.');
    });
}

async function importContracts(userID: string) {
  const contracts: any[] = [];
  const companies = new Map();
  const events = new Map();

  fs.createReadStream('./prisma/contracts.csv')
    .pipe(parse({ columns: true, skip_empty_lines: true }))
    .on('data', async (row: any) => {
      const companyName = row['Company Name'];
      const eventName = row['Event Name'];
      const eventYear = row['Event Year'];
      const status = row['Status'];
      const notes = row['Notes'];

      if (!companies.has(companyName)) {
        prisma.company
          .findFirst({
            where: { name: companyName },
            select: { id: true },
          })
          .then((company) => {
            if (company) companies.set(companyName, company.id);
          });
      }

      if (!events.has({ eventName, eventYear })) {
        const event = await prisma.event.findFirst({
          where: { name: eventName, year: eventYear },
          select: { id: true },
        });
        if (event) events.set(`${eventName} ${eventYear}`, event?.id);
      }
      contracts.push({
        companyName,
        eventName,
        eventYear,
        status,
        notes,
      });
    })
    .on('end', async () => {
      await prisma.contract.createMany({
        data: contracts.map((contract) => ({
          companyID: companies.get(contract.companyName),
          eventID: events.get(`${contract.eventName} ${contract.eventYear}`),
          userID: userID,
          status: contract.status,
          notes: contract.notes,
        })),
      });
      console.log('Contracts imported successfully.');
    });
}

async function main() {
  const hashedPass = bcrypt.hashSync('adminFrApp', 10);

  const data = {
    nume: 'Admin',
    prenume: 'Admin',
    email: 'admin@gmail.com',
    password: hashedPass,
    role: Role.COORDONATOR,
  };

  prisma.user.create({ data }).then(async () => {
    const user: User[] = await prisma.user.findMany();
    const id: string = user[0].id;

    await Promise.all([importEvents(id), importCompanies()]);

    await importContracts(id);
  });
}

main()
  .then(async () => {
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });


how can i make so that the importContracts only runs after importCompanies and importEvents is finished