// noPage
// useLibs

import { getAuth } from '@react-native-firebase/auth';
import { get, getDatabase, onValue, ref, set } from '@react-native-firebase/database';
import { collection, getCountFromServer, getDocs, getFirestore, orderBy, query, where } from '@react-native-firebase/firestore';
import { EventTms_homeProperty } from 'esoftplay/cache/event/tms_home/import';
import { LibCurl } from 'esoftplay/cache/lib/curl/import';
import { LibObject } from 'esoftplay/cache/lib/object/import';
import { LibToastProperty } from 'esoftplay/cache/lib/toast/import';
import esp from 'esoftplay/esp';
import useGlobalState from 'esoftplay/global';
import { createTimeout } from 'esoftplay/timeout';

function getEventPath() {
  return "event" + (esp.isDebug("cc") ? "BBT" : "BBO")
}
function getRandomSuffix(time: number): number {
  return Number(time + "" + (Math.floor(Math.random() * 9000) + 1000))
}


export const eventIdQueue = useGlobalState(0)
export const eventQueueConfig = useGlobalState<any>({})
const state = useGlobalState(0)
export const lastKeyInPages = useGlobalState<string[]>([])
export const userIdKeyReplacer = useGlobalState<any>({})

function isValidEventId(event_id: string): boolean {
  return !!event_id && event_id !== "undefined"
}

export default function useFirebaseSocket() {
  const [status] = state.useState()
  const isDirect = EventTms_homeProperty.state()

  function isInLocal(state: any[], code: string) {
    const encodedCode = encodeURIComponent(code)
    return state.findIndex(([url, post]) => (post.qr == encodedCode || post.user_qr == encodedCode)) == -1 ? false : true
  }

  const auth = () => {
    return getAuth()
  }
  const db = () => {
    return getDatabase()

  }

  const signInAnonym = () => { }

  // ini get yang di live
  async function _get(path: string, gate_id: string, onDone: (res: any) => void) {
    let hasDone = false
    if (isDirect.get()) {
      new LibCurl('gate_check/' + path + '?t=' + new Date().getTime(), { gate_id }, (res) => {
        hasDone = true
        onDone(res)
      }, (res) => {
        onDone(res)
        hasDone = true
      }, 1)
      return
    }

    get(ref(getDatabase(), path))
      .then((sn) => {
        hasDone = true
        if (sn.exists()) {
          onDone(sn.val())
        } else {
          onDone(null)
        }
      })
      .catch((e) => {
        // if (e && !hasDone) {
        //   getBackup(path, (res) => {
        //     if (res) {
        //       onDone(res)
        //     } else {
        //       onDone(null)
        //     }
        //   })
        // }
      })
  }

  function listenChangeTime(merchant_id: string, callback: (params: any) => void): () => void {
    const onChildChange = onValue(ref(getDatabase(), 'merchant_offline/' + merchant_id), (sn) => {
      if (sn.exists()) {
        callback(sn.val());
      }
    })
    return () => onChildChange
  }

  async function _set(path: string, data: any, onDone?: (res: any) => void) {
    const timeout = createTimeout()
    if (state.get() == 1)
      set(ref(getDatabase(), path), data)
    else
      timeout.set(() => {
        _set(path, data,)
        timeout.clear()
      }, 300);
  }

  function path(...paths: any[]): string {
    return paths.join('/')
  }

  function addQueue(path: string, event_id: string, onSuccess?: () => void) {
    const instance: any = esp.mod("firestore/index")().instance()
    const db = getFirestore(instance)

    if (!isValidEventId(event_id)) {
      return
    }

    if (userIdKeyReplacer.get()?.priority == 1 && userIdKeyReplacer.get()?.t) {
      const coll = collection(db, [getEventPath(), path, event_id].join('/'));
      const q = query(coll, orderBy('t', 'asc'), where("t", "==", userIdKeyReplacer.get().t));
      getDocs(q).then((doc) => {
        if (doc.size == 0) {
          LibToastProperty.show(esp.lang("event/firebase_socket", "priority_queue_used"))
          userIdKeyReplacer.set(LibObject.set(userIdKeyReplacer.get(), 0)('priority'))
          addQueue(path, event_id, onSuccess)
        } else if (doc.size == 1) {
          // console.log("SIJI")
          doc.forEach((d) => {
            userIdKeyReplacer.set(LibObject.set(userIdKeyReplacer.get(), d.id)('id'))
            updateQueueExp(path, event_id)
            new LibCurl('event_booking_waiting_allotment_use', { event_id: event_id })
            if (onSuccess) onSuccess?.()
          })
        } else {
          LibToastProperty.show("Antrian lebih dari 1", doc.size)
        }
        // console.log("SIZE", doc.size)
      })
    } else {
      // console.log("ora")
      if (userIdKeyReplacer.get()?.id)
        esp.mod("firestore/index")().deleteDocument?.(instance, [getEventPath?.(), path, event_id, userIdKeyReplacer.get()?.id], () => { }, (e) => { })
      const ctime = getDateTimebyGmt7().getTime()
      const time = getRandomSuffix(ctime)
      const data = { t: ctime, s: time }
      // console.log(data)
      esp.mod("firestore/index")().addCollection?.(instance, [getEventPath?.(), path, event_id], data, (dt) => {
        // console.log("KENE",)
        userIdKeyReplacer.set?.({
          id: dt?.id,
          ...data
        })
        if (onSuccess) onSuccess?.()
      }, (err) => {
        // console.log(err)
      })
    }
  }

  function getDateTimebyGmt7() {
    const ori = new Date()
    // const gmt = setTimeOffset(ori)
    return ori
  }

  // get weather function

  function getQueue(path: string, event_id: string, _limit: number, cb: (idx: number, key: string) => void) {
    if (userIdKeyReplacer.get()?.s) {
      const instance: any = esp.mod("firestore/index")().instance()
      const db = getFirestore(instance)
      const coll = collection(db, [getEventPath(), path, event_id].join('/'));
      const q = query(coll, orderBy('s', 'asc'), where("s", "<", userIdKeyReplacer.get().s));
      getCountFromServer(q).then((v) => {
        cb(v.data().count, userIdKeyReplacer.get().id)
      }).catch((e) => {
        getQueue(path, event_id, _limit, cb)
        console.log({ e })
      })
    }

    // /* cleanup */
    // const cdate = getDateTimebyGmt7().getTime()
    // if (!cdate) {
    //   LibToastProperty.show(esp.lang("lib/firebase_socket", "something_wrong_1"))
    //   return
    // }
    // if (!_limit) {
    //   LibToastProperty.show(esp.lang("lib/firebase_socket", "something_wrong_2"))
    //   return
    // }
    // if (!userIdKeyReplacer?.get()?.s) {
    //   LibToastProperty.show(esp.lang("lib/firebase_socket", "something_wrong_3"))
    //   return
    // }
    // const exp = query(collection(instance, [getEventPath(), path, event_id].join('/')), where("t", "<", cdate - _limit), orderBy('t', 'asc'), limit(10));
    // const batch = writeBatch(instance);
    // getDocs(exp).then((expd) => {
    //   expd.forEach((doc) => {
    //     if (Number(doc.data().s) < Number(userIdKeyReplacer.get().s))
    //       batch.delete(doc.ref)
    //     // console.log(doc.data().t < cdate - limit, doc.data().t, cdate - limit, cdate - limit - doc.data().t)
    //     // console.log('->' + moment(new Date(Number(doc.data().t))).localeFormat('DD MMMM YYYY HH:mm:ss'))
    //     // console.log('-->' + moment(new Date(cdate - limit)).localeFormat('DD MMMM YYYY HH:mm:ss') + '\n\n')
    //   })
    //   batch.commit()
    // })
    // /* end cleanup */
  }

  function updateQueueExp(path: string, event_id: string) {
    const instance: any = esp.mod("firestore/index")().instance()
    esp.mod("firestore/index")().updateDocument(instance, [getEventPath(), path, event_id, userIdKeyReplacer.get().id], [{ key: 't', value: getDateTimebyGmt7().getTime() }], () => { }, (e) => {
      // updateQueueExp(path, event_id, key)
    })
  }

  function doneQueue(path: string, event_id: string, key: string, cb: Function) {
    if (key) {
      const instance: any = esp.mod("firestore/index")().instance()
      esp.mod("firestore/index")().deleteDocument(instance, [getEventPath(), path, event_id, key], () => {
        cb()
        userIdKeyReplacer.reset()
      }, (e) => {
        console.warn(e)
      })
    }
  }

  function isInPricingQueueConfig(event_id: string): boolean {
    return eventQueueConfig.get(event_id) && eventQueueConfig.get(event_id).limit > 0
  }

  function useQueueConfigListener() {
    function action() {
      fetch(esp.config("events", "queue") + "?t=" + new Date().getTime(), { "method": "GET" })
        .then(res => res.json())
        .then((re) => {
          eventQueueConfig.set(re)
        })
      setTimeout(() => {
        action()
      }, 10000);

    }
    action()
  }

  return {
    status,
    auth,
    db,
    signInAnonymously: signInAnonym,
    get: _get,
    set: _set,
    isInLocal,
    // getQueueConfig,
    isInPricingQueueConfig,
    useQueueConfigListener,
    // isInBookingQueueConfig,
    addQueue,
    getQueue,
    doneQueue,
    updateQueueExp,
    listenChangeTime,
    path
  }
}
