// Available variables:
  // - Machine
  // - interpret
  // - assign
  // - send
  // - sendParent
  // - spawn
  // - raise
  // - actions
  // - XState (all XState exports)
  
const createLinkMachine = Machine(
  {
    id: 'shortenLink',
    context: {
      linkHistory: [],
      value: '',
      errorMessage: null,
      retries: 0,
    },
    initial: 'idle',
    states: {
      idle: {
        tags: ['showingForm'],
        on: {
          CREATE_LINK: 'validateForm',
          UPDATE_INPUT: {
            actions: ['updateValue', 'clearErrorMessage'],
          },
        },
      },
      validateForm: {
        tags: ['showingForm'],
        invoke: {
          id: 'validatingUrl',
          src: 'validateUrl',
          onDone: {
            target: 'creatingLink',
            actions: ['clearErrorMessage'],
          },
          onError: {
            target: 'idle',
            actions: ['setErrorMessage'],
          },
        },
      },
      creatingLink: {
        tags: ['showingForm'],
        always: [{ cond: 'retriesExceeded', target: 'cannotCreateLink' }],
        invoke: {
          id: 'creatingLink',
          src: 'postLink',
          onDone: {
            target: 'linkCreated',
            actions: ['prependLink'],
          },
          onError: {
            target: 'creatingLink',
            actions: ['incrementRetries', 'setErrorMessage'],
          },
        },
      },
      cannotCreateLink: {
        tags: ['showingForm'],
        exit: ['resetErrorCount'],
        on: {
          CREATE_LINK: 'validateForm',
        },
      },
      linkCreated: {
        tags: ['showingResult'],
        exit: ['resetContext'],
        on: {
          RESTART: 'idle',
        },
      },
    },
  },
  {
    guards: {
      retriesExceeded: (ctx) => {
        return ctx.retries !== 0 && ctx.retries >= 2
      },
    },
    services: {
      validateUrl: async (ctx) => {
        // const result = urlFormSchema.validate({ url: ctx.value })

        // if (result.error) {
        //   return Promise.reject({ message: 'Must be a valid URL' })
        // }

        return {}
      },
      postLink: async (ctx) => {
        // // const res = await fetch('/api/link', {
        // //   method: 'POST',
        // //   body: JSON.stringify({ url: ctx.value }),
        // //   headers: { 'Content-Type': 'application/json' },
        // // })
        // if (res.status === 201) {
        //   const data = res.json()
        //   return data
        // }

        // return Promise.reject({ status: res.status, message: 'Unable to create link. Please try again later.' })
        
        return { id: 1234, url: 'https://example.com', slug: 'abc123'}
      },
    },
    actions: {
      updateValue: assign((_ctx, evt) => {
        if (evt.type !== 'UPDATE_INPUT') return {}

        return {
          value: evt.value,
        }
      }),
      resetContext: assign((_ctx, evt) => {
        if (evt.type !== 'RESTART') return {}

        return {
          value: '',
          errorMessage: null,
          retries: 0,
        }
      }),
      resetErrorCount: assign((_ctx, evt) => {
        if (evt.type !== 'CREATE_LINK') return {}

        return {
          retries: 0,
        }
      }),
      incrementRetries: assign((ctx) => {
        return {
          retries: ctx.retries + 1,
        }
      }),
      prependLink: assign((ctx, evt) => {
        if (evt.type !== 'done.invoke.creatingLink') return {}

        return {
          linkHistory: [evt.data, ...ctx.linkHistory],
        }
      }),
      clearErrorMessage: assign((_ctx, evt) => {
        if (evt.type !== 'done.invoke.validateUrl') return {}

        return {
          errorMessage: null,
        }
      }),
      setErrorMessage: assign((_ctx, evt) => {
        if (evt.type === 'error.platform.validatingUrl' || evt.type === 'error.platform.creatingLink') {
          return {
            errorMessage: evt.data.message,
          }
        }

        return {}
      }),
    },
  }
)