import type { PropType } from 'vue';
import { computed, defineComponent, onMounted, ref, toRef, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
import { costanti } from '@costanti'
import { fieldsTable } from '@store/Modules/fieldsTable'
import { shared_consts } from '@src/common/shared_vuejs'
import type { IColGridTable } from 'model';
import { IOperators } from 'model'
import { tools } from '@tools'
import { useProducts } from 'app/src/store/Products';

export default defineComponent({
  name: 'CMySelect',
  emits: ['update:value', 'update:arrvalue', 'changeval', 'clear', 'searchOnGM'],
  props: {
    options: {
      type: Array,
      required: true,
    },
    arrvalue: {
      type: Array,
      required: true,
    },
    value: [String, Number, Object],
    label: {
      type: String,
      required: false,
      default: undefined,
    },
    addstrrequired: {
      type: String,
      required: false,
      default: '',
    },
    myclass: {
      type: String,
      required: false,
      default: ''
    },
    tablesel: {
      type: String,
      required: false,
      default: ''
    },
    type_out: {
      type: Number,
      required: false,
    },
    row: {
      type: Object,
      required: false,
      default: () => {
        return {}
      },
    },
    col: {
      type: Object as PropType<IColGridTable>,
      required: false,
      default: () => {
        return { name: '' }
      },
    },
    filter_table: {
      type: String,
      required: false,
      default: ''
    },
    filter_field: {
      type: String,
      required: false,
      default: ''
    },
    filter_extra: {
      type: [Object, String],
      required: false,
      default: null
    },
    value_extra: {
      type: [String, Number],
      required: false,
      default: ''
    },
    optlab: [String, Function],
    optval: {
      type: String,
      required: true,
    },
    useinput: {
      type: Boolean,
      required: false,
      default: true
    },
    pickup: {
      type: Boolean,
      required: false,
      default: false
    },
    addall: {
      type: Boolean,
      required: false,
      default: false
    },
    addnone: {
      type: Boolean,
      required: false,
      default: false
    },
    addlast: {
      type: Boolean,
      required: false,
      default: false
    },
    dense: {
      type: Boolean,
      required: false,
      default: true
    },
    multiple: {
      type: Boolean,
      required: false,
      default: false
    },
    newvaluefunc: {
      type: Function,
      required: false,
    },
    funcgetvaluebyid: {
      type: Function,
      required: false,
    },
    multiselect_by_server: {
      type: Boolean,
      default: false,
    },
    sola_lettura: {
      type: Boolean,
      default: false,
    },
    focus: {
      type: Boolean,
      default: false,
    },
    withToggle: {
      type: Boolean,
      default: false,
    },
    icon_alternative: {
      type: String,
      required: false,
      default: '',
    },
    filter: {
      type: Function,
      required: false,
    }
  },
  components: {},
  setup(props, { emit }) {
    const $q = useQuasar()
    const { t } = useI18n()
    const userStore = useUserStore()
    const globalStore = useGlobalStore()

    const optFiltered = ref(<any>[])
    const valori = ref(<any>[])

    const myvalue = ref(<string | number | object>'')
    const myarrvalue = ref(<any[]>[])
    const arrtempOpt = ref(<any[]>[])

    const optionsreal: any = []

    const selectMultiServer = ref(null)
    const selectPickup = ref(null)
    const selectMultiple = ref(null)
    const selectGeneric = ref(null)

    const productStore = useProducts()

    const mystr = ref('')

    const valoriload = computed(() => {
      return updateArrOptions()
    })

    watch(() => props.options, (value: any, oldval: any) => {
      if (!props.multiselect_by_server) {
        valori.value = valoriload.value
      } else {
        // console.log('@@@ VALORI CHANGED (1)', valori.value)
      }
    },
    )
    watch(() => props.value, (value: any, oldval: any) => {
      update()
    },
    )

    watch(() => props.arrvalue, (value: any, oldval: any) => {
      // console.log(' MODIF props.arrvalue', props.arrvalue)
      update()
    },
    )

    function saveOptInCookie(arrval: any) {
      // console.log('saveOptInCookie')

      if (arrval) {
        for (const id of arrval) {
          const trovato = arrtempOpt.value.find((rec) => rec._id === id)
          if (!trovato) {
            const rec = valori.value.find((rec: any) => rec._id === id)
            if (rec) {
              // console.log('SAVE OPT rec', rec)
              const obj: any = {}
              obj[`${props.optval}`] = id
              obj[`${props.optlab}`] = rec[`${props.optlab}`]
              arrtempOpt.value.push(obj)
              let num = localStorage.getItem(props.tablesel + 'NUM') || 0
              try {
                if (!num) {
                  num = 0
                } else {
                  num = parseInt(num.toString(), 10)
                }
              } catch (e) {
                num = 0
              }
              // console.log('-----------  valori.value', valori.value)
              // console.log('-----------  arrtempOpt.value', arrtempOpt.value)

              tools.localStSetItem(props.tablesel + num + props.optval, id)
              const mysaved = tools.getValueByFunzOrVal(rec, props.optlab)
              tools.localStSetItem(props.tablesel + num + props.optlab, mysaved)

              console.log('   SAVED: ', props.tablesel + num + props.optlab, '=', mysaved)

              num += 1
              tools.localStSetItem(props.tablesel + 'NUM', num.toString())
            }
          }
        }
      }
    }


    function changeval(newval: any) {
      // console.log(' ½½½½½½½ changeval', newval)
      if (props.multiple || props.multiselect_by_server) {
        // tools.localStSetItem(props.tablesel + '_' + newval, valori.value[newval])

        if (props.type_out === costanti.FieldType.object) {
          const arrout = []
          for (const val of newval) {
            const obj: any = {}
            if (typeof val !== 'object') {
              obj[props.optval] = val
              arrout.push(obj)
            } else {
              arrout.push(val)
            }
          }
          myarrvalue.value = arrout
        } else {
          myarrvalue.value = newval && newval['arrvalue'] ? newval['arrvalue'] : newval
        }

        saveOptInCookie(newval)

        console.log(' ----- Myselect changeval Arrvalue', myarrvalue.value)
        emit('update:arrvalue', myarrvalue.value)
        emit('changeval', myarrvalue.value)


      } else {

        if (props.tablesel === shared_consts.TAB_COUNTRY)
          myvalue.value = newval && newval['value'] ? newval['value'] : newval
        else if (props.tablesel === shared_consts.TAB_CITIES)
          myvalue.value = newval && newval['value'] ? newval['value'] : newval
        else if (props.tablesel === shared_consts.TAB_PHONES)
          myvalue.value = newval && newval['code'] ? newval['code'] : newval
        else
          myvalue.value = newval
        // console.log('Myselect changeval', myvalue.value)

        if (myvalue.value && JSON.stringify(myvalue.value)) {
          saveLastOpt(props.optval, JSON.stringify(myvalue.value))
        }
        saveOptInCookie([myvalue.value])

        emit('update:value', myvalue.value)
        emit('changeval', myvalue.value)
      }
    }

    function saveLastOpt(key: string, myval: any) {

      let ind = 9

      // get free number
      for (let i = 0; i < 10; i++) {
        let myoldval = tools.getItemLS(props.tablesel + 'last_VAL' + i.toString())
        myoldval = tools.strToObj(myoldval)
        if (myoldval && myoldval[key]) {
          if (myoldval[key] === myval) {
            // already exist
            return
          }
          // if (myoldval[key] !== myval) {
          if (!myoldval[key]) {
            ind = i
            break
          }
        } else {
          ind = i
          break
        }
      }

      // console.log('saveLastOpt', ind, 'key', key, 'myval', myval)
      tools.localStSetItem(props.tablesel + 'last_OPT' + ind.toString(), key)
      tools.localStSetItem(props.tablesel + 'last_VAL' + ind.toString(), myval)
    }

    function mounted() {
      console.log('CMYSELECT: mounted')
      optionsreal.value = props.options
      if (props.focus) {
        focusVisibleSelect()
      }

      update()

    }

    function focusVisibleSelect() {

      try {
        if (selectMultiServer.value && props.multiselect_by_server) {
          selectMultiServer.value.focus()
        } else if (selectPickup.value && props.pickup) {
          selectPickup.value.focus()
        } else if (selectMultiple.value && props.multiple) {
          selectMultiple.value?.focus()
        } else {
          if (selectGeneric.value)
            selectGeneric.value?.focus()
        }
      } catch (e) {
        console.error('Err', e)
      }
    }

    function update() {
      console.log('update', props.value, props)
      // console.log(' #### mounted myselect', props.options, 'arrvalue', myarrvalue.value)
      let rec: any
      if (optionsreal.value) {
        if (!props.multiselect_by_server) {
          rec = optionsreal.value.find((myrec: any) => myrec[`${props.optval}`] === props.value)
        }
      }
      if (props.multiselect_by_server) {
        const num = parseInt(localStorage.getItem(props.tablesel + 'NUM')!, 10)
        // console.log('num LOADED ', num)
        arrtempOpt.value = []
        if (props.addall) {
          let myobj: any = {}
          if (typeof props.optlab === 'string') {
            myobj = tools.setRecordByField(props.optlab, myobj, '(Tutti)')
            myobj = tools.setRecordByField(props.optval, myobj, costanti.FILTER_TUTTI)
          }

          arrtempOpt.value.push(myobj)
        }
        if (props.addnone) {
          const myobj: any = {}
          if (typeof props.optlab === 'string') {
            myobj[props.optlab] = '[Nessuno]'
            myobj[props.optval] = costanti.FILTER_NESSUNO
          }

          arrtempOpt.value = [myobj, ...arrtempOpt.value]
        }
        for (let i = 0; i < num; i++) {
          const itemId = parseInt(localStorage.getItem(props.tablesel + i + props.optval)!, 10)
          const itemlab = localStorage.getItem(props.tablesel + i + props.optlab)
          if (itemId) {
            const obj: any = {}
            obj[`${props.optval}`] = itemId
            obj[`${props.optlab}`] = itemlab
            if (!arrtempOpt.value.find((rec) => rec._id === itemId))
              arrtempOpt.value.push(obj)
          }
        }

        // Check if exist other array:
        if (props.col) {

          if (props.col.remote_table && props.col.remote_key && props.col.remote_field) {

            try {
              const myarrremote = props.row[props.col.remote_table]

              for (const myrec of myarrremote) {
                const myidkey = myrec[props.col.remote_key]
                if (!arrtempOpt.value.includes(myidkey)) {
                  const myobj: any = {}
                  myobj[props.col.remote_key] = myidkey
                  if (props.col.remote_field === 'comune' && !!myrec['prov']) {
                    myobj[props.col.remote_field] = myrec[props.col.remote_field] + ' (' + myrec['prov'] + ')'
                  } else {
                    myobj[props.col.remote_field] = myrec[props.col.remote_field]
                  }

                  arrtempOpt.value.push(myobj)
                }
              }

            } catch (e) { }

          }
        }

        myarrvalue.value = []
        const myarr = props.arrvalue
        for (const val of myarr) {
          rec = arrtempOpt.value.find((myrec: any) => val === (myrec[`${props.optval}`]))
          if (rec) {
            myarrvalue.value.push(rec[`${props.optval}`])
          } else {
            myarrvalue.value.push(val)
          }
        }
      } else {
        if (props.addnone) {
          const myobj: any = {}
          if (typeof props.optlab === 'string') {
            myobj[props.optlab] = '[Nessuno]'
            myobj[props.optval] = costanti.FILTER_NESSUNO
          }

          myarrvalue.value = [myobj, ...myarrvalue.value]
        }
      }

      if (props.tablesel === 'friendsandme') {
        // debugger;
      }

      if (props.multiple) {

        const arrrec = []
        let myarr = props.arrvalue
        if (myarr && !tools.isArray(myarr)) {
          myarr = [myarr]
        }

        if (myarr) {
          for (const val of myarr) {
            rec = optionsreal.value.find((myrec: any) => val === (myrec[`${props.optval}`]))
            if (rec) {
              arrrec.push(rec[`${props.optval}`])
            }
          }
        }
        if (arrrec.length > 0) {
          if (props.funcgetvaluebyid)
            myarrvalue.value = props.funcgetvaluebyid(arrrec)
          else
            myarrvalue.value = arrrec
        } else {
          if (props.arrvalue) {
            myarrvalue.value = props.arrvalue
          }
        }
      } else {
        if (rec) {
          if (props.funcgetvaluebyid)
            myvalue.value = props.funcgetvaluebyid(rec[`${props.optval}`])
          else
            myvalue.value = tools.getValueByFunzOrVal(rec, props.optlab)
        } else {
          // if (!props.useinput) {
          if (props.value) {
            myvalue.value = props.value
          } else {
            myvalue.value = ''
          }
          // }
        }
        // console.log('myvalue', props.tablesel, myvalue.value)
        // console.log('props.value', props.value)
      }

      if (props.multiselect_by_server) {
        valori.value = arrtempOpt.value
      } else {
        valori.value = valoriload.value
      }
      // console.log('cmyselect: myvalue.value', myvalue.value)
    }

    function updateArrOptions() {

      let myarr: any = []

      // console.log(props.col.jointable, props.filter)
      if (props && props.col && props.col.jointable) {
        optionsreal.value = globalStore.getTableJoinByName(props.col.jointable, props.col.addall, props.col.addnone, props.filter)
        // console.log('optionsreal.value', optionsreal.value)
      } else {
        optionsreal.value = props.options
      }

      // console.log('optionsreal.value', optionsreal.value)

      myarr = optionsreal.value
      if (!fieldsTable.tableRemotePickup.includes(props.tablesel)) {

        const needle: any = props.value_extra

        // console.log('needle', needle, 'props.multiple', props.multiple)
        if (props.filter_table) {
          // console.log('  FILTERTABLE', props.filter_field, myarr)
          if (props.multiple) {
            myarr = myarr.filter((rec: any) => rec[props.filter_field] === needle)
          } else {

            myarr = myarr.filter((rec: any) => {
              if (tools.isArray(rec[props.filter_field]))
                return rec[props.filter_field].includes(needle)
              else
                return false
            })
          }
          // console.log('  RISSSSSSSSS: ', myarr)
        }
      }

      if (props.addall) {
        let myobj: any = {}
        // if (typeof props.optlab === 'string') {
        myobj = tools.setRecordByField(props.optlab, myobj, '(Tutti)')
        myobj = tools.setRecordByField(props.optval, myobj, costanti.FILTER_TUTTI)
        // }

        if (myarr && !tools.isObjectEmpty(myobj))
          myarr = [myobj, ...myarr]
      }

      if (props.addnone) {
        const myobj: any = {}
        if (typeof props.optlab === 'string') {
          myobj[props.optlab] = '[Nessuno]'
          myobj[props.optval] = costanti.FILTER_NESSUNO
        }

        if (myarr)
          myarr = [myobj, ...myarr]
      }

      if (props.addlast) {
        myarr = getLastInserted(myarr)
      }

      // console.log('     myarr: ', myarr)
      return myarr
    }

    function getLastInserted(myarr: any) {
      for (let ind = 0; ind < 10; ind++) {
        const optlab = tools.getItemLS(props.tablesel + 'last_OPT' + ind.toString())
        let optval = tools.getItemLS(props.tablesel + 'last_VAL' + ind.toString())
        if (optval)
          optval = JSON.parse(optval)
        // console.log(ind, '¶¶¶¶¶¶¶¶¶¶ optlab', optlab, 'optval', optval)

        const myobj2: any = {}
        if (typeof props.optlab === 'string') {
          if (optval && !!optval['comune']) {
            myobj2[props.optlab] = optval['comune']
            myobj2[props.optval] = optval[optlab]
            myarr = [...myarr, myobj2]
          }
        }
      }

      return myarr
    }

    function filterFn(val: any, update: any, abort: any) {
      update(
        async () => {
          // console.log('Filter val:', val, 'len=', val.length)
          // console.log('props.filter_extra', props.filter_extra)
          // console.log('valori.value', valori.value)

          let myarr: any = []

          mystr.value = val.toLocaleLowerCase()

          myarr = updateArrOptions()
          if (!fieldsTable.tableRemotePickup.includes(props.tablesel)) {
            if (myarr && myarr.length > 0) {
              valori.value = myarr
            } else {
              if (props.filter_table) {
                valori.value = []
              }
            }

            if (!props.multiple && !props.multiselect_by_server) {

              if (val === '') {
                valori.value = myarr
              } else {
                const optlab: any = props.optlab ? '' + props.optlab : ''
                if (optlab) {
                  valori.value = myarr.filter((v: any) => {
                    const mioval = tools.getRecordByField(optlab, v)
                    if (mioval)
                      return mioval?.toLowerCase().indexOf(mystr.value) > -1
                    else
                      return false

                  })
                }
              }
            }

            return
          }


          if (val.length <= 1 && !(fieldsTable.tableRemotePickup.includes(props.tablesel) && props.filter_extra)) {
            console.log('@@@ LENGTH <= 1')
            abort()
            return
          }

          // console.log('props.tablesel', props.tablesel)

          if (fieldsTable.tableRemotePickup.includes(props.tablesel)) {
            try {
              // myarr = optionsreal.value
              myarr = []
              if (mystr.value !== '' || props.filter_extra)
                // myarr = [{_id:1, prov: 'RN', descr: 'Rimini'}]
                /*
                if (val === '1') {
                  myarr.push({ _id: 1, comune: 'PROVA 1', prov: 'AL' })
                  myarr.push({ _id: 2, comune: 'PROVA 1b', prov: 'AL' })
                }else if (val === '2') {
                  myarr.push({ _id: 1, comune: 'PROVA 2', prov: 'AL' })
                  myarr.push({ _id: 2, comune: 'PROVA 2B', prov: 'AL' })

                }*/ { // @ts-ignore
                myarr = await globalStore.loadPickup({ table: props.tablesel, search: mystr.value.trim(), filter: props.filter_extra })
              }

              if (myarr === null) {
                console.log('@@@ VALORI VALUE XXX', valori.value)
                valori.value = arrtempOpt.value
              }
            } catch (e) {
              console.log('@@@ VALORI VALUE XXX', valori.value)
              valori.value = arrtempOpt.value
            }
            // const needle = val.toLocaleLowerCase()
            // optFiltered.value = optFiltered.value.filter((v: any) => v.toLocaleLowerCase().indexOf(needle) > -1)
            if (props.addall) {
              let myobj: any = {}
              if (typeof props.optlab === 'string') {
                myobj = tools.setRecordByField(props.optlab, myobj, '(Tutti)')
                myobj = tools.setRecordByField(props.optval, myobj, costanti.FILTER_TUTTI)
              }

              myarr = [myobj, ...myarr]
            }
            if (props.addnone) {
              const myobj: any = {}
              if (typeof props.optlab === 'string') {
                myobj[props.optlab] = '[Nessuno]'
                myobj[props.optval] = costanti.FILTER_NESSUNO
              }

              myarr = [myobj, ...myarr]
            }

            if (props.addlast) {
              myarr = getLastInserted(myarr)
            }
          }

          if (myarr && myarr.length > 0) {
            valori.value = myarr
            if (props.multiselect_by_server) {
              // console.log('@@@ VALORI CHANGED (3)', valori.value)
            }
          } else {
            valori.value = []
          }

          console.log('*** OUT: tablesel', props.tablesel, 'filterFn', myarr)
        },
        // "ref" is the Vue reference to the QSelect
        (ref: any) => {
          if (!props.useinput) {
            // console.log('ref.options', ref.options)
            if (val !== '' && ref.options.length > 0) {
              ref.setOptionIndex(-1) // reset optionIndex in case there is something selected
              ref.moveOptionSelection(1, true) // focus the first selectable option and do not update the input-value
            }
          }
        }
      )
    }

    function abortFilterFn() {
      console.log('delayed filter aborted')
    }

    function checkIfShowRec(rec: any) {
      return (rec._id > 0 && typeof rec._id === 'number') || rec._id !== 'number'
    }

    async function newvaluefuncfirst(value: any, done: any) {
      if (props.newvaluefunc && props.col) {
        const fieldval = fieldsTable.getLabelByTable(props.col.jointable)
        // console.log('fieldval', fieldval, 'optionsreal.value', optionsreal.value)
        // Se esiste già, non crearlo
        const esiste = optionsreal.value.find((rec: any) => {
          // console.log('rec[fieldval]',rec[fieldval], value.toLowerCase())
          return rec[fieldval]?.toLowerCase() === value.toLowerCase() && (rec[props.filter_field] === props.value_extra)
        })
        console.log('esiste', esiste)
        if (!esiste || (esiste && esiste.length === 0)) {
          // console.log('non esiste, lo creo ! ', value)
          const newrec = await props.newvaluefunc(tools.CapitalizeAllWords(value))
          if (newrec) {
            if (props.col && props.col.jointable) {
              // Reload
              // console.log('  A1', optionsreal.value)
              // valori.value = valoriload.value
              // optionsreal.value = valori.value
              console.log('DOPO', optionsreal.value)
            }
            console.log('newrec', newrec)
            const myid = fieldsTable.getKeyByTable(props.col.jointable)
            const recfound = valori.value.find((rec: any) => rec[myid] === newrec[myid])
            if (!recfound) {
              done(newrec, 'add-unique')
            }

            // console.log('myid', myid, optionsreal.value)
            // console.log('recfound',recfound)
            // console.log('newrec[myid]',newrec[myid])
            /*if (recfound) {
              const arrout = [...myarrvalue.value]
              if (!arrout.includes(recfound[myid])) {
                arrout.push(recfound[myid])
              }
              console.log('  arrout (1)', arrout)
              if (props.multiple || props.multiselect_by_server) {
                if (myid) {
                  done(newrec, 'add-unique')
                }
              } else {
                done(recfound[myid], 'add-unique')
              }

              /* if (props.multiple || props.multiselect_by_server) {
                console.log('arrout (2)', arrout)
                changeval(arrout)

              }
            }*/
          }
        }
      }
    }

    function getIcon() {
      if (props.icon_alternative)
        return props.icon_alternative
      if (props.col && props.col['icon']) {
        return props.col['icon']
      }
      return ''
    }

    function selectText(event: any) {
      // Seleziona tutto il testo all'interno della casella di testo
      event.target.select();
    }

    function getLabelValue(opt: any): string {
      const collabel = props.optlab

      if (typeof collabel === 'function') {
        // Se collabel è una funzione, chiamala con opt
        return collabel(opt)
      } else if (typeof collabel === 'string') {
        // Se collabel è una stringa, usa il valore della proprietà corrispondente
        return opt[collabel] || 'N/A'
      }

      // Fallback generico
      return 'N/A';
    }

    function getOptionLabel(option: any): string {
      // console.log('getOptionLabel', option)
      if (typeof props.optlab === 'function') {
        return props.optlab(option); // Se optlab è una funzione, chiamala
      } else {
        return option[props.optlab]; // Se optlab è una stringa, usa la proprietà corrispondente
      }
    }

    function clear() {
      emit('clear')
      myvalue.value = ''
      mystr.value = ''
    }

    function searchOnGM(mystr: string) {
      emit('searchOnGM', mystr)
    }

    function applyLabelColorBasedOnProductStatus(myrec: any) {
      let classi = ''
      if (props.tablesel === 'products') {
        if (productStore.isNonVendibile(myrec)) {
          classi = 'bg-grey'
        }
        if (!productStore.isDisponibile(myrec)) {
          classi = 'bg-red-1'
        }
      }
      return classi
    }


    onMounted(mounted)


    return {
      changeval,
      myvalue,
      myarrvalue,
      valori,
      filterFn,
      fieldsTable,
      checkIfShowRec,
      abortFilterFn,
      newvaluefuncfirst,
      getIcon,
      tools,
      selectText,
      getLabelValue,
      getOptionLabel,
      clear,
      mystr,
      searchOnGM,
      applyLabelColorBasedOnProductStatus,
    }
  }
})

