import 'dotenv/config';
import { drizzle } from 'drizzle-orm/node-postgres';
import { existsSync, readdirSync, readFileSync, statSync, unlinkSync } from 'fs';
import fs from 'fs-extra';
import { join } from 'path';
import { Pool } from 'pg';
import { rimraf } from 'rimraf';
import sharp from 'sharp';
import { BusinessListingService } from 'src/listings/business-listing.service';
import { CommercialPropertyService } from 'src/listings/commercial-property.service';
import { Geo } from 'src/models/server.model';
import { UserService } from 'src/user/user.service';
import winston from 'winston';
import { User, UserData } from '../models/db.model';
import { createDefaultBusinessListing, createDefaultCommercialPropertyListing, createDefaultUser, emailToDirName } from '../models/main.model';
import { SelectOptionsService } from '../select-options/select-options.service';
import * as schema from './schema';
interface PropertyImportListing {
  id: string;
  userId: string;
  listingsCategory: 'commercialProperty';
  title: string;
  state: string;
  hasImages: boolean;
  price: number;
  city: string;
  description: string;
  type: number;
  imageOrder: any[];
}
interface BusinessImportListing {
  userId: string;
  listingsCategory: 'business';
  title: string;
  description: string;
  type: number;
  state: string;
  city: string;
  id: string;
  price: number;
  salesRevenue: number;
  leasedLocation: boolean;
  established: number;
  employees: number;
  reasonForSale: string;
  supportAndTraining: string;
  cashFlow: number;
  brokerLicencing: string;
  internalListingNumber: number;
  realEstateIncluded: boolean;
  franchiseResale: boolean;
  draft: boolean;
  internals: string;
  created: string;
}
// const typesOfBusiness: Array<KeyValueStyle> = [
//   { name: 'Automotive', value: '1', icon: 'fa-solid fa-car', textColorClass: 'text-green-400' },
//   { name: 'Industrial Services', value: '2', icon: 'fa-solid fa-industry', textColorClass: 'text-yellow-400' },
//   { name: 'Real Estate', value: '3', icon: 'fa-solid fa-building', textColorClass: 'text-blue-400' },
//   { name: 'Uncategorized', value: '4', icon: 'fa-solid fa-question', textColorClass: 'text-cyan-400' },
//   { name: 'Retail', value: '5', icon: 'fa-solid fa-money-bill-wave', textColorClass: 'text-pink-400' },
//   { name: 'Oilfield SVE and MFG.', value: '6', icon: 'fa-solid fa-oil-well', textColorClass: 'text-indigo-400' },
//   { name: 'Service', value: '7', icon: 'fa-solid fa-umbrella', textColorClass: 'text-teal-400' },
//   { name: 'Advertising', value: '8', icon: 'fa-solid fa-rectangle-ad', textColorClass: 'text-orange-400' },
//   { name: 'Agriculture', value: '9', icon: 'fa-solid fa-wheat-awn', textColorClass: 'text-sky-400' },
//   { name: 'Franchise', value: '10', icon: 'fa-solid fa-star', textColorClass: 'text-purple-400' },
//   { name: 'Professional', value: '11', icon: 'fa-solid fa-user-gear', textColorClass: 'text-gray-400' },
//   { name: 'Manufacturing', value: '12', icon: 'fa-solid fa-industry', textColorClass: 'text-red-400' },
//   { name: 'Food and Restaurant', value: '13', icon: 'fa-solid fa-utensils', textColorClass: 'text-amber-700' },
// ];
// const { Pool } = pkg;

// const openai = new OpenAI({
//   apiKey: process.env.OPENAI_API_KEY, // Stellen Sie sicher, dass Sie Ihren API-Key als Umgebungsvariable setzen
// });
(async () => {
  const connectionString = process.env.DATABASE_URL;
  // const pool = new Pool({connectionString})
  const client = new Pool({ connectionString });
  const db = drizzle(client, { schema, logger: true });
  const logger = winston.createLogger({
    transports: [new winston.transports.Console()],
  });
  const commService = new CommercialPropertyService(null, db);
  const businessService = new BusinessListingService(null, db);
  const userService = new UserService(null, db, null, null);
  //Delete Content
  await db.delete(schema.commercials);
  await db.delete(schema.businesses);
  await db.delete(schema.users);
  let filePath = `./src/assets/geo.json`;
  const rawData = readFileSync(filePath, 'utf8');
  const geos = JSON.parse(rawData) as Geo;

  const sso = new SelectOptionsService();
  //Broker
  filePath = `./data/broker.json`;
  let data: string = readFileSync(filePath, 'utf8');
  const usersData: UserData[] = JSON.parse(data); // Erwartet ein Array von Objekten
  const generatedUserData = [];
  console.log(usersData.length);
  let i = 0,
    male = 0,
    female = 0;
  const targetPathProfile = `./pictures/profile`;
  deleteFilesOfDir(targetPathProfile);
  const targetPathLogo = `./pictures/logo`;
  deleteFilesOfDir(targetPathLogo);
  const targetPathProperty = `./pictures/property`;
  deleteFilesOfDir(targetPathProperty);
  fs.ensureDirSync(`./pictures/logo`);
  fs.ensureDirSync(`./pictures/profile`);
  fs.ensureDirSync(`./pictures/property`);

  //User
  for (let index = 0; index < usersData.length; index++) {
    const userData = usersData[index];
    const user: User = createDefaultUser('', '', '', null);
    user.licensedIn = [];
    userData.licensedIn.forEach(l => {
      console.log(l['value'], l['name']);
      user.licensedIn.push({ registerNo: l['value'], state: l['name'] });
    });
    user.areasServed = [];
    user.areasServed = userData.areasServed.map(l => {
      return { county: l.split(',')[0].trim(), state: l.split(',')[1].trim() };
    });
    user.hasCompanyLogo = true;
    user.hasProfile = true;
    user.firstname = userData.firstname;
    user.lastname = userData.lastname;
    user.email = userData.email;
    user.phoneNumber = userData.phoneNumber;
    user.description = userData.description;
    user.companyName = userData.companyName;
    user.companyOverview = userData.companyOverview;
    user.companyWebsite = userData.companyWebsite;
    const [city, state] = userData.companyLocation.split('-').map(e => e.trim());
    user.location = {};
    user.location.name = city;
    user.location.state = state;
    const cityGeo = geos.states.find(s => s.state_code === state).cities.find(c => c.name === city);
    user.location.latitude = cityGeo.latitude;
    user.location.longitude = cityGeo.longitude;
    user.offeredServices = userData.offeredServices;
    user.gender = userData.gender;
    user.customerType = 'professional';
    user.customerSubType = 'broker';
    user.created = new Date();
    user.updated = new Date();

    // const u = await db
    //   .insert(schema.users)
    //   .values(convertUserToDrizzleUser(user))
    //   .returning({ insertedId: schema.users.id, gender: schema.users.gender, email: schema.users.email, firstname: schema.users.firstname, lastname: schema.users.lastname });
    const u = await userService.saveUser(user);
    generatedUserData.push(u);
    i++;
    logger.info(`user_${index} inserted`);
    if (u.gender === 'male') {
      male++;
      const data = readFileSync(`./pictures_base/profile/Mann_${male}.jpg`);
      await storeProfilePicture(data, emailToDirName(u.email));
    } else {
      female++;
      const data = readFileSync(`./pictures_base/profile/Frau_${female}.jpg`);
      await storeProfilePicture(data, emailToDirName(u.email));
    }
    const data = readFileSync(`./pictures_base/logo/${i}.jpg`);
    await storeCompanyLogo(data, emailToDirName(u.email));
  }

  //Corporate Listings
  filePath = `./data/commercials.json`;
  data = readFileSync(filePath, 'utf8');
  const commercialJsonData = JSON.parse(data) as PropertyImportListing[]; // Erwartet ein Array von Objekten
  for (let index = 0; index < commercialJsonData.length; index++) {
    const user = getRandomItem(generatedUserData);
    const commercial = createDefaultCommercialPropertyListing();
    const id = commercialJsonData[index].id;
    delete commercial.id;

    commercial.email = user.email;
    commercial.type = sso.typesOfCommercialProperty.find(e => e.oldValue === String(commercialJsonData[index].type)).value;
    commercial.title = commercialJsonData[index].title;
    commercial.description = commercialJsonData[index].description;
    try {
      const cityGeo = geos.states.find(s => s.state_code === commercialJsonData[index].state).cities.find(c => c.name === commercialJsonData[index].city);
      commercial.location = {};
      commercial.location.latitude = cityGeo.latitude;
      commercial.location.longitude = cityGeo.longitude;
      commercial.location.name = commercialJsonData[index].city;
      commercial.location.state = commercialJsonData[index].state;
      // console.log(JSON.stringify(commercial.location));
    } catch (e) {
      console.log(`----------------> ERROR ${commercialJsonData[index].state} - ${commercialJsonData[index].city}`);
      continue;
    }
    commercial.price = commercialJsonData[index].price;
    commercial.listingsCategory = 'commercialProperty';
    commercial.draft = false;
    commercial.imageOrder = getFilenames(id);
    commercial.imagePath = emailToDirName(user.email);
    const insertionDate = getRandomDateWithinLastYear();
    commercial.created = insertionDate;
    commercial.updated = insertionDate;

    const result = await commService.createListing(commercial); //await db.insert(schema.commercials).values(commercial).returning();
    try {
      fs.copySync(`./pictures_base/property/${id}`, `./pictures/property/${result.imagePath}/${result.serialId}`);
    } catch (err) {
      console.log(`----- No pictures available for ${id} ------ ${err}`);
    }
  }

  //Business Listings
  filePath = `./data/businesses.json`;
  data = readFileSync(filePath, 'utf8');
  const businessJsonData = JSON.parse(data) as BusinessImportListing[]; // Erwartet ein Array von Objekten
  for (let index = 0; index < businessJsonData.length; index++) {
    const business = createDefaultBusinessListing(); //businessJsonData[index];
    delete business.id;
    const user = getRandomItem(generatedUserData);
    business.email = user.email;
    business.type = sso.typesOfBusiness.find(e => e.oldValue === String(businessJsonData[index].type)).value;
    business.title = businessJsonData[index].title;
    business.description = businessJsonData[index].description;
    try {
      const cityGeo = geos.states.find(s => s.state_code === businessJsonData[index].state).cities.find(c => c.name === businessJsonData[index].city);
      business.location = {};
      business.location.latitude = cityGeo.latitude;
      business.location.longitude = cityGeo.longitude;
      business.location.name = businessJsonData[index].city;
      business.location.state = businessJsonData[index].state;
    } catch (e) {
      console.log(`----------------> ERROR ${businessJsonData[index].state} - ${businessJsonData[index].city}`);
      continue;
    }
    business.price = businessJsonData[index].price;
    business.title = businessJsonData[index].title;
    business.draft = businessJsonData[index].draft;
    business.listingsCategory = 'business';
    business.realEstateIncluded = businessJsonData[index].realEstateIncluded;
    business.leasedLocation = businessJsonData[index].leasedLocation;
    business.franchiseResale = businessJsonData[index].franchiseResale;

    business.salesRevenue = businessJsonData[index].salesRevenue;
    business.cashFlow = businessJsonData[index].cashFlow;
    business.supportAndTraining = businessJsonData[index].supportAndTraining;
    business.employees = businessJsonData[index].employees;
    business.established = businessJsonData[index].established;
    business.internalListingNumber = businessJsonData[index].internalListingNumber;
    business.reasonForSale = businessJsonData[index].reasonForSale;
    business.brokerLicencing = businessJsonData[index].brokerLicencing;
    business.internals = businessJsonData[index].internals;
    business.imageName = emailToDirName(user.email);
    business.created = new Date(businessJsonData[index].created);
    business.updated = new Date(businessJsonData[index].created);

    await businessService.createListing(business); //db.insert(schema.businesses).values(business);
  }

  //End
  await client.end();
})();
// function sleep(ms) {
//   return new Promise(resolve => setTimeout(resolve, ms));
// }
// async function createEmbedding(text: string): Promise<number[]> {
//   const response = await openai.embeddings.create({
//     model: 'text-embedding-3-small',
//     input: text,
//   });
//   return response.data[0].embedding;
// }

function getRandomItem<T>(arr: T[]): T {
  if (arr.length === 0) {
    throw new Error('The array is empty.');
  }

  const randomIndex = Math.floor(Math.random() * arr.length);
  return arr[randomIndex];
}
function getFilenames(id: string): string[] {
  try {
    const filePath = `./pictures_base/property/${id}`;
    return readdirSync(filePath);
  } catch (e) {
    return [];
  }
}
function getRandomDateWithinLastYear(): Date {
  const currentDate = new Date();
  const lastYear = new Date(currentDate.getFullYear() - 1, currentDate.getMonth(), currentDate.getDate());

  const timeDiff = currentDate.getTime() - lastYear.getTime();
  const randomTimeDiff = Math.random() * timeDiff;
  const randomDate = new Date(lastYear.getTime() + randomTimeDiff);

  return randomDate;
}
async function storeProfilePicture(buffer: Buffer, userId: string) {
  const quality = 50;
  const output = await sharp(buffer)
    .resize({ width: 300 })
    .avif({ quality }) // Verwende AVIF
    //.webp({ quality }) // Verwende Webp
    .toBuffer();
  await sharp(output).toFile(`./pictures/profile/${userId}.avif`);
}

async function storeCompanyLogo(buffer: Buffer, adjustedEmail: string) {
  const quality = 50;
  const output = await sharp(buffer)
    .resize({ width: 300 })
    .avif({ quality }) // Verwende AVIF
    //.webp({ quality }) // Verwende Webp
    .toBuffer();
  await sharp(output).toFile(`./pictures/logo/${adjustedEmail}.avif`); // Ersetze Dateierweiterung
  // await fs.outputFile(`./pictures/logo/${userId}`, file.buffer);
}

function deleteFilesOfDir(directoryPath) {
  // Überprüfen, ob das Verzeichnis existiert
  if (existsSync(directoryPath)) {
    // Den Inhalt des Verzeichnisses synchron löschen
    try {
      readdirSync(directoryPath).forEach(file => {
        const filePath = join(directoryPath, file);
        // Wenn es sich um ein Verzeichnis handelt, rekursiv löschen
        if (statSync(filePath).isDirectory()) {
          rimraf.sync(filePath);
        } else {
          // Wenn es sich um eine Datei handelt, direkt löschen
          unlinkSync(filePath);
        }
      });
      console.log('Der Inhalt des Verzeichnisses wurde erfolgreich gelöscht.');
    } catch (err) {
      console.error('Fehler beim Löschen des Verzeichnisses:', err);
    }
  } else {
    console.log('Das Verzeichnis existiert nicht.');
  }
}
