<template>
  <div
    :class="[
      page === 'list' ? 'section-header' : '',
      page === 'form' ? 'form-part-title' : ''
    ]">
    <i class="ico-c ico-section back-grad-title" v-if="icon !== undefined && icon !== ''">
      <svg height="20">
        <use :href="icourl + '#' + icon" />
      </svg>
    </i>
    <h1 v-if="title !== undefined && title !== ''">
      <span>{{ title }}</span>
      <span class="section-header-count">{{ localTotalRecord }} {{ listText }}</span>
    </h1>
    <h4 v-if="formTitle !== undefined && formTitle !== ''">{{ formTitle }}</h4>
    <div class="section-header-buttons-c collapsable" v-if="!isPreview">
      <div class="header-extra-buttons-C"><slot name="extraButtons"></slot></div>
      <div class="list-search-c" v-if="search">
        <i
          class="ico-c ico-section ico-section-header-btn btn-list-search menu-have-sub"
          @click="OpenSearchForm($event)">
          <svg>
            <use href="@/assets/images/icons.svg#search" />
          </svg>
        </i>
        <div
          v-if="searchForm"
          class="menu-sub menu-sub-top menu-sub-right menu-sub-mobile-fix section-header-search"
          :style="searchFieldPos">
          <div id="list-search-form">
            <input
              :id="'listsearch' + rnd"
              type="text"
              placeholder="Ara"
              v-model="localQuery"
              @keyup="SearchInputKeyUp" />
            <button @click="SearchQuery">
              <svg>
                <use href="@/assets/images/icons.svg#search" />
              </svg>
            </button>
          </div>
        </div>
      </div>
      <div class="header-buttons-C">
        <div class="menu-have-sub section-header-mobile-menu" @click="OpenMobileButtons">
          <i class="ico-c ico-section ico-section-header-btn">
            <svg>
              <use href="@/assets/images/icons.svg#oplist" />
            </svg>
          </i>
        </div>

        <div
          class="section-header-buttons menu-sub menu-sub-right menu-sub-top"
          v-if="mobileButtons">
          <icon-button
            v-if="export"
            classList="ico-section ico-section-header-btn"
            @click="exportPanel = !exportPanel"
            icon="export" />
          <icon-button
            v-if="filterable()"
            classList="ico-section ico-section-header-btn"
            @click="OpenFilterPanel"
            icon="filter" />
          <icon-button
            v-if="addRoute !== undefined && addRoute !== ''"
            classList="ico-section ico-section-header-btn"
            :toRoute="addRoute"
            icon="plus" />

          <icon-button
            v-else-if="addAction !== undefined && addAction !== ''"
            classList="ico-section ico-section-header-btn"
            @click="localAddAction"
            icon="plus" />
        </div>
      </div>
    </div>
  </div>
  <div
    :class="[
      page === 'list' ? 'section-content section-inner' : '',
      page === 'form' ? 'form-part-content' : ''
    ]">
    <div class="list-filter-wrapper" v-if="filters() || searched">
      <h4>Filtreler ve Arama</h4>
      <div class="list-filter-content">
        <template v-if="localQuery !== ''">
          <div class="list-filter-item" data-filter="durum-onaylanmis">
            <strong>Arama:</strong>
            <span>
              {{ localQuery }}
            </span>
            <span class="list-filter-close" @click="RemoveSearch"></span>
          </div>
        </template>
        <template v-for="(filter, k) in filterParams">
          <div class="list-filter-item" data-filter="durum-onaylanmis">
            <strong>{{ filter.title }}:</strong>
            <span>
              {{ filter.text || filter.val }} {{ filter.op === '=' ? '' : filter.op }}
            </span>
            <span class="list-filter-close" @click="RemoveFilterKey(k as string)"></span>
          </div>
        </template>
      </div>
    </div>
    <slot name="datatable">
      <data-table
        :tableHeader="tableHeader"
        :tableData="localTableData"
        :rowAction="rowAction"
        v-model:sortData="localSort"
        v-model:pagination="localPagination"
        :rowNumber="rowNumber"
        :totalValues="localTotalValues"
        :isPreview="isPreview"
        :rowActions="rowActions"
        :actionFixed="actionFixed"
        :rowActionStyle="rowActionStyle" />
    </slot>
  </div>

  <panel-wrapper v-if="filterPanel" v-model="filterPanel" :panel-title="'Filtreleme'">
    <template #panelContent>
      <panel-filter :filterHead="tableHeader" v-model:filterParams="localFilterParams" />
    </template>
    <template #footerButton>
      <div class="button-c button-save" @click="FilterData">Filtrele</div>
    </template>
  </panel-wrapper>
  <panel-wrapper v-if="exportPanel" v-model="exportPanel" :panel-title="'Dışa Aktar'">
    <template #panelContent>
      <panel-export v-model:selectedExport="selectedExport" />
    </template>
  </panel-wrapper>
</template>

<script setup lang="ts">
  import { ref, reactive, onBeforeMount, watch, computed } from 'vue'
  import axios from 'axios'

  import { useGlobalStore } from '@/stores/globalStore'
  const globalStore = useGlobalStore()
  import { useDataStore } from '@/stores/dataStore'
  const dataStore = useDataStore()

  import icourl from '@/assets/images/icons.svg'
  import PanelWrapper from '@/components/PanelWrapper.vue'
  import PanelFilter from './PanelFilter.vue'
  import PanelExport from './PanelExport.vue'

  interface ITableHead {
    [key: string]: any
    title: string
    name: string
    compute?: Function
    computeHtml?: Function
    sort?: boolean
    filter?: Record<string, any>
  }
  interface IPagination {
    [key: string]: any
    pageNumber?: number | string
    pageSize: number | string
    totalRecords: number | string
  }
  interface ISort {
    [key: string]: any
    sortColumn?: string
    sortOrder?: string
  }
  export interface Props {
    tableHeader: ITableHead[]
    tableData?: Record<string, any>[]
    pagination?: IPagination
    rowAction?: Function | string
    title?: string
    formTitle?: string
    listText?: string
    icon?: string
    apiList?: string
    addRoute?: string
    addAction?: Function | string
    filterData?: Record<string, any>
    sortData?: ISort
    totalRecord?: string | number
    query?: string
    apiText?: string
    page?: string
    refresh?: boolean
    export?: boolean
    search?: boolean
    rowNumber?: boolean
    totalValues?: Record<string, any>
    isPreview?: boolean
    rowActions?: Record<string, any>[]
    actionFixed?: boolean
    rowActionStyle?:string
  }

  const props = withDefaults(defineProps<Props>(), {
    tableData: () => [],
    totalRecord: 0,
    apiText: '',
    page: 'list',
    refresh: false,
    export: true,
    search: true,
    rowNumber: false,
    isPreview: false,
    actionFixed:false
  })

  const emit = defineEmits([
    'click',
    'update:tableData',
    'update:pagination',
    'update:sortData',
    'update:query',
    'update:refresh',
    'update:totalRecord'
  ])

  const rnd = ref<number>(Number(Math.floor(Math.random() * 1000000000)))
  const filterPanel = ref<boolean>(false)
  const exportPanel = ref<boolean>(false)
  const searchForm = ref<boolean>(false)
  const mobileButtons = ref<boolean>(false)
  const selectedExport = ref<number | null>(null)
  const searched = ref<boolean>(false)

  const localSort = ref<ISort>({} as ISort)
  const localPagination = ref<IPagination>({} as IPagination)
  const localTotalValues = reactive<Record<string, any>>({})
  const searchFieldPos = ref<string>('')

  if (props.totalValues !== undefined) Object.assign(localTotalValues, props.totalValues)

  if (props.pagination !== undefined)
    Object.assign(localPagination.value, props.pagination)
  const localTableData = ref<Record<string, any>[]>([])
  if (props.tableData !== undefined) localTableData.value = props.tableData
  const localQuery = ref<string>('')

  const localTotalRecord = ref<string | number>(0)
  if (props.totalRecord !== undefined) localTotalRecord.value = props.totalRecord

  const localFilterParams = ref<Record<string, any>>({})
  const filterParams = reactive<Record<string, any>>({})

  const OpenFilterPanel = () => {
    Object.assign(localFilterParams.value, filterParams)
    filterPanel.value = true
  }

  const EqualObjects = (source: Record<string, any>, dest: Record<string, any>) => {
    Object.keys(source).forEach((keys, is) => {
      if (dest[keys] === undefined) delete source[keys]
    })
  }

  const FilterData = async () => {
    Object.assign(filterParams, localFilterParams.value)
    EqualObjects(filterParams, localFilterParams.value)
    setTimeout(async () => {
      await GetLocalData()
      filterPanel.value = false
    }, 50)
  }

  const localAddAction = () => {
    if (props.addAction !== undefined && props.addAction !== '')
      (props.addAction as Function)()
  }

  const filterable = () => {
    return props.tableHeader.filter((e) => e.hasOwnProperty('filter')).length > 0
  }

  const filters = (): boolean => {
    return Object.keys(filterParams).length > 0
  }

  const RemoveFilterKey = (k: string) => {
    delete localFilterParams.value[k]
    delete filterParams[k]
    GetLocalData()
  }
  const RemoveSearch = () => {
    localQuery.value = ''
    searched.value = false
    GetLocalData()
  }
  const GetLocalData = async () => {
    if (selectedExport.value !== null) {
      const exportUrl =
        axios.defaults.baseURL + dataStore.apiBase + props.apiList + '?isPdf=true'

      const link = document.createElement('a')
      link.href = exportUrl
      document.body.appendChild(link)
      link.dispatchEvent(
        new MouseEvent('click', { bubbles: true, cancelable: true, view: window })
      )
      link.remove()
      window.URL.revokeObjectURL(link.href)

      selectedExport.value = null
      exportPanel.value = false
    } else {
      let apiData: Record<string, any> = {
        params: {
          pageNumber: props.isPreview ? 0 : localPagination.value.pageNumber || 1,
          pageSize: globalStore.perPage
        }
      }

      if (localSort.value.sortColumn !== undefined) {
        apiData.params.sortColumn = localSort.value.sortColumn
        if (localSort.value.sortOrder !== undefined && localSort.value.sortOrder !== '')
          apiData.params.sortOrder = localSort.value.sortOrder
      }
      if (localQuery.value !== '') {
        apiData.params.searchString = localQuery.value
      } else {
        delete apiData.params.searchString
      }

      if (props.apiText !== undefined && props.apiText !== '')
        apiData.text = props.apiText

      var filterparam: Record<string, any> = {}

      if (filters()) {
        Object.keys(filterParams).forEach((f, k) => {
          filterparam['Filters[' + f + ']'] = filterParams[f].op + filterParams[f].val
        })
        Object.assign(apiData.params, filterparam)
      }
      let dt = await dataStore.dataGet(props.apiList as string, apiData)

      // buraya dikkat cekilis itiraz modulunde liste duzgun calışması için nullable kullanıldı
      if (dt !== 'errorfalse') localTableData.value = dt.data ?? dt
      else localTableData.value = []

      localPagination.value.totalRecords = dt.totalRecords
      localPagination.value.pageSize = dt.pageSize

      localTotalRecord.value = dt.totalRecords || localTableData.value.length

      if (props.pagination !== undefined) emit('update:pagination', localPagination.value)
      if (props.totalRecord !== undefined)
        emit('update:totalRecord', localTotalRecord.value)
      if (props.totalValues !== undefined) {
        Object.keys(props.totalValues).forEach((key, i) => {
          localTotalValues[key] = dt[props.totalValues![key]]
        })
      }
      emit('update:refresh', false)
    }
  }
  const OpenMobileButtons = () => {
    searchForm.value = false
    mobileButtons.value = !mobileButtons.value
  }
  const OpenSearchForm = (e: Event) => {
    searchFieldPos.value = ''
    if (globalStore.screenWidth <= globalStore.breakPoints.tabletp) {
      mobileButtons.value = false
      let eltRect = (e.target as HTMLElement).getBoundingClientRect() as DOMRect
      searchFieldPos.value = `top:${eltRect.top + eltRect.height}px;`
    }

    searchForm.value = !searchForm.value
    if (searchForm.value) {
      setTimeout(() => {
        let el: HTMLInputElement = document.getElementById(
          'listsearch' + rnd.value
        ) as HTMLInputElement
        el.focus
        el.select()
      }, 50)
    }
  }
  const SearchInputKeyUp = (e: KeyboardEvent) => {
    if (e.key === 'Enter') SearchQuery()
  }
  const SearchQuery = () => {
    if (props.apiList !== undefined) GetLocalData()
    else emit('update:query', localQuery.value)
    searchForm.value = false
    searched.value = true
  }
  const Resize = () => {
    searchForm.value = false
    mobileButtons.value = false
  }
  onBeforeMount(() => {
    if (globalStore.screenWidth >= globalStore.breakPoints.tabletp)
      mobileButtons.value = true

    if (props.apiList !== undefined) GetLocalData()

    window.addEventListener('resize', Resize)
  })

  watch(
    () => localSort.value,
    () => {
      GetLocalData()
    },
    { deep: true }
  )

  watch(
    () => localPagination.value.pageNumber,
    () => {
      GetLocalData()
    }
  )
  watch(
    () => props.refresh,
    () => {
      if (props.refresh) GetLocalData()
    }
  )
  watch(
    () => localQuery.value,
    () => {
      if (props.apiList !== undefined && localQuery.value.length === 0) GetLocalData()
      else if (localQuery.value.length === 0) emit('update:query', localQuery.value)
    }
  )
  watch(
    () => selectedExport.value,
    () => {
      if (selectedExport.value !== null) GetLocalData()
    }
  )
</script>
