import { faker } from '@faker-js/faker/locale/sk'
import SwedishSSN from 'swedish-ssn-generator'
import { inPlaceUnsorted } from 'weighted-random-distribution'
import moment from 'moment'
import { between } from './utils.js'

async function populate (client, personCount) {
  function createRandomPerson () {
    const gender = between(0, 1) ? 'male' : 'female'
    const p = {
      // userId: faker.datatype.uuid(),
      // username: faker.internet.userName(),
      // email: faker.internet.email(),
      // avatar: faker.image.avatar(),
      // password: faker.internet.password(),
      birthdate: faker.date.birthdate(),
      name: faker.name.findName(undefined, undefined, gender)
      // registeredAt: faker.date.past()
    }
    p.rc = SwedishSSN.generateSSNWithParameters(p.birthdate, gender).replace('-', '')
    return p
  }

  async function insertLabel (title) {
    try {
      const d = (await client.put(
        `/labels`,
        {
          title
        }
      )).data

      return d.id
    } catch (ex) {
      console.log(ex)
      process.exit()
      return false
    }
  }

  function createTask (date, past = false) {
    const t = {
      start_date: date,
      title: faker.hacker.phrase() // faker.lorem.sentence()
    }

    if (inPlaceUnsorted({
      0: 95,
      1: 5
    }) * 1) {
      // priority
      t.priority = 4
    }

    if (inPlaceUnsorted({
      0: 95,
      1: 5
    }) * 1) {
      // reminder
      t.reminder_dates = [moment(date).add(-3, 'day')]
    }

    // label
    const label = inPlaceUnsorted(MY_LABELS)
    if (label) {
      console.log(label)
      t.labels = [{ id: label * 1 }]
      if (label * 1 === 1) { // recept
        if (1 * inPlaceUnsorted({
          0: 30,
          1: 70
        })) {
          // repeat
          t.title = 'REPEAT: ' + t.title
          t.repeat_after = 60 * 60 * 24 * 30 * 3
          t.repeat_mode = 0
        }
      }
    }

    if ((past && 1 * inPlaceUnsorted({
      0: 30,
      1: 70
    })) || 1 * inPlaceUnsorted({
      0: 95,
      1: 5
    })) {
      // done
      t.done = true
    }

    if (1 * inPlaceUnsorted({
      0: 5,
      1: 95
    })) {
      // due
      t.due_date = date
    }

    return t
  }

  async function insertTask (listId, task) {
    try {
      let labels
      if (task.labels) {
        // BUG this is workarround because create task with labels will not insert the labels
        labels = task.labels
        delete task.labels
      }

      const d = (await client.put(
        `/lists/${listId}`,
        task
      )).data

      if (labels) {
        await client.post(
          `/tasks/${d.id}/labels/bulk`,
          { labels }
        )
      }

      return d.id
    } catch (ex) {
      console.log(ex)
      process.exit()
      return false
    }
  }

  async function insertPerson (person) {
    // const d = (await client.get(`/namespaces/${namespace}/lists`)).data
    // console.log(d)
    try {
      const d = (await client.put(
        `/namespaces/${namespace}/lists`,
        {
          title: person.name,
          identifier: person.rc
        }
      )).data

      return d.id
    } catch (ex) {
      console.log(ex)
      return false
    }
  }

  const namespace = 1

  // prepare labels
  const MY_LABELS = { '': 20 }
  MY_LABELS[await insertLabel('recept')] = 45
  MY_LABELS[await insertLabel('kontrola')] = 20
  MY_LABELS[await insertLabel('krv')] = 10
  MY_LABELS[await insertLabel('FOB')] = 5

  for (let i = 0; i < personCount; i++) {
    const person = createRandomPerson()
    const pId = await insertPerson(person)
    if (pId === false) continue

    // lists, sqlite_sequence, tasks

    // past dates
    for (let c = 0; c < between(0, 20); c++) {
      await insertTask(pId, createTask(faker.date.past(), true))
    }

    // future dates
    for (let c = 0; c < between(0, 5); c++) {
      const soon = 1 * inPlaceUnsorted({
        0: 70,
        1: 30
      })
      await insertTask(pId, createTask(soon ? faker.date.soon(5) : faker.date.future()))
    }
  }
}

export default populate
