<template>
  <div
    class="ivyforms-google-sheets-form ivyforms-gap-24 ivyforms-flex ivyforms-flex-1 ivyforms-flex-direction-column"
  >
    <div
      v-if="!formLoading"
      class="ivyforms-google-sheets-form__option-bar ivyforms-pb-8 ivyforms-flex"
    >
      <div
        class="ivyforms-google-sheets-form__option-bar__left ivyforms-flex ivyforms-gap-8 ivyforms-align-items-center"
      >
        <IvyToggle
          :model-value="integrationData.enabled"
          :title="getLabel('active')"
          size="s"
          text-position="left"
          @update:model-value="(value: boolean) => updateIntegrationData({ enabled: value })"
        />
      </div>

      <div
        class="ivyforms-google-sheets-form__option-bar__right ivyforms-flex ivyforms-gap-8 ivyforms-align-items-center ivyforms-justify-content-end"
      >
        <IvyButtonAction priority="tertiary" @click="$emit('cancel')">
          {{ getLabel('cancel') }}
        </IvyButtonAction>
        <IvyButtonAction priority="primary" :loading="loading" @click="handleSave">
          {{ isEditing ? getLabel('update') : getLabel('save') }}
        </IvyButtonAction>
      </div>
    </div>

    <IvyScrollbar v-if="!formLoading" ref="scrollbarRef" modifier="outside-vertical">
      <div
        class="ivyforms-google-sheets-form__fields ivyforms-flex ivyforms-flex-direction-column ivyforms-gap-24"
      >
        <IvyFormItem
          :label="getLabel('spreadsheet')"
          secondary
          required
          v-bind="validationErrors.spreadsheet_id ? { error: validationErrors.spreadsheet_id } : {}"
        >
          <IvySelectInput
            :model-value="integrationData.spreadsheet_id"
            :placeholder="getLabel('choose_value')"
            :loading="loadingSpreadsheets"
            @update:model-value="onSpreadsheetChange"
          >
            <IvySelectOption
              v-for="sheet in spreadsheets"
              :key="sheet.id"
              :value="sheet.id"
              :label="sheet.name"
            />
          </IvySelectInput>
        </IvyFormItem>

        <IvyFormItem
          :label="getLabel('worksheet_name')"
          secondary
          required
          v-bind="validationErrors.worksheet_name ? { error: validationErrors.worksheet_name } : {}"
        >
          <IvySelectInput
            :model-value="integrationData.worksheet_name"
            :placeholder="getLabel('choose_value')"
            :loading="loadingWorksheets"
            :disabled="!integrationData.spreadsheet_id"
            @update:model-value="onWorksheetChange"
          >
            <IvySelectOption
              v-for="worksheet in worksheets"
              :key="worksheet.title"
              :value="worksheet.title"
              :label="worksheet.title"
            />
          </IvySelectInput>
        </IvyFormItem>

        <div v-if="integrationData.worksheet_name" class="ivyforms-google-sheets-form__mapping">
          <div class="medium-14 ivyforms-mb-12">{{ getLabel('map_fields') }}</div>
          <p class="regular-14 ivyforms-mb-16 text-secondary">
            {{ getLabel('map_fields_description') }}
          </p>

          <div class="ivyforms-google-sheets-form__mapping-grid">
            <div class="ivyforms-google-sheets-form__mapping-header">
              <div class="medium-12">{{ getLabel('form_fields') }}</div>
              <div class="medium-12">{{ getLabel('spreadsheet_columns') }}</div>
              <div></div>
            </div>

            <div
              v-for="(mapping, index) in fieldMappingRows"
              :key="index"
              class="ivyforms-google-sheets-form__mapping-row"
            >
              <IvySelectInput
                :model-value="mapping.formFieldKey"
                :placeholder="getLabel('select_form_field')"
                secondary
                @update:model-value="(value: string) => updateMappingFormField(index, value)"
              >
                <IvySelectOption
                  v-for="field in formFields"
                  :key="field.key"
                  :value="field.key"
                  :label="field.label"
                />
              </IvySelectInput>

              <IvySelectInput
                :model-value="mapping.column"
                :placeholder="getLabel('select_spreadsheet_column')"
                secondary
                :loading="loadingColumns"
                @update:model-value="(value: string) => updateMappingColumn(index, value)"
              >
                <IvySelectOption
                  v-for="col in columns"
                  :key="col.column"
                  :value="col.column"
                  :label="col.label"
                />
              </IvySelectInput>

              <div class="ivyforms-google-sheets-form__mapping-actions">
                <IvyButtonAction
                  icon-only
                  icon-start="plus"
                  size="s"
                  type="ghost"
                  priority="secondary"
                  @click="addMappingRow"
                />
                <IvyButtonAction
                  v-if="fieldMappingRows.length > 1"
                  icon-only
                  icon-start="minus"
                  size="s"
                  type="ghost"
                  priority="secondary"
                  @click="removeMappingRow(index)"
                />
              </div>
            </div>
          </div>
        </div>

        <component
          :is="IntegrationSmartLogicOptions"
          v-if="IntegrationSmartLogicOptions"
          integration-name="google_sheets"
          :settings="smartLogicSettings"
          :fields="formFieldsRaw"
          :get-label="getLabel"
          @update:settings="handleSmartLogicSettingsUpdate"
        />
      </div>
    </IvyScrollbar>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick, type Component, type PropType } from 'vue'
import { useLabels } from '@/composables/useLabels'
import { useApiClient } from '@/composables/useApiClient'
import IvyButtonAction from '@/views/_components/button/IvyButtonAction.vue'
import IvyToggle from '@/views/_components/toggle/IvyToggle.vue'
import IvyScrollbar from '@/views/_components/scrollbar/IvyScrollbar.vue'
import IvyFormItem from '@/views/_components/form/IvyFormItem.vue'
import IvySelectInput from '@/views/_components/input/IvySelectInput.vue'
import IvySelectOption from '@/views/_components/input/IvySelectOption.vue'
import type { Field } from '@/types/field.d.ts'
import type {
  GoogleSheetIntegration,
  GoogleSheetSmartLogic,
  GoogleSpreadsheetOption,
  GoogleWorksheetOption,
  GoogleColumnOption,
} from '@/integrations/google-sheets/types/google-sheets.types'

const { getLabel } = useLabels()
const { request } = useApiClient()

const props = defineProps({
  integrationData: {
    type: Object as PropType<Partial<GoogleSheetIntegration>>,
    required: true,
  },
  formFields: {
    type: Array as PropType<Field[]>,
    required: true,
  },
  loading: {
    type: Boolean,
    default: false,
  },
  formLoading: {
    type: Boolean,
    default: false,
  },
  isEditing: {
    type: Boolean,
    default: false,
  },
})

const emit = defineEmits<{
  save: [data: Partial<GoogleSheetIntegration>]
  cancel: []
  'update:integration-data': [data: Partial<GoogleSheetIntegration>]
}>()

interface MappingRow {
  formFieldKey: string
  column: string
}

const spreadsheets = ref<GoogleSpreadsheetOption[]>([])
const worksheets = ref<GoogleWorksheetOption[]>([])
const columns = ref<GoogleColumnOption[]>([])
const loadingSpreadsheets = ref(false)
const loadingWorksheets = ref(false)
const loadingColumns = ref(false)
const validationErrors = ref<Record<string, string>>({})
const fieldMappingRows = ref<MappingRow[]>([{ formFieldKey: '', column: '' }])
const scrollbarRef = ref<InstanceType<typeof IvyScrollbar> | null>(null)

const IntegrationSmartLogicOptions = computed(() => {
  return window.IvyForms?.components?.['IntegrationSmartLogicOptions'] as Component | undefined
})

const formFieldsRaw = computed(() => props.formFields)

const defaultSmartLogic = (): GoogleSheetSmartLogic => ({
  enabled: false,
  match: 'any',
  rules: [],
})

const smartLogicSettings = computed(() => ({
  ...props.integrationData,
  smartLogic:
    props.integrationData.smart_logic ??
    (props.integrationData as { smartLogic?: GoogleSheetSmartLogic }).smartLogic ??
    defaultSmartLogic(),
}))

const handleSmartLogicSettingsUpdate = (settings: Record<string, unknown>) => {
  const smartLogic = settings.smartLogic as GoogleSheetSmartLogic | undefined
  const { smartLogic: _ignored, ...rest } = settings

  updateIntegrationData({
    ...(rest as Partial<GoogleSheetIntegration>),
    smart_logic: smartLogic ?? props.integrationData.smart_logic ?? defaultSmartLogic(),
  })
}

const formFields = computed(() =>
  props.formFields.map((field, index) => ({
    key: `{{${field.type}_${field.fieldIndex ?? index}}}`,
    label: field.label || field.type,
  })),
)

const updateIntegrationData = (data: Partial<GoogleSheetIntegration>) => {
  emit('update:integration-data', { ...props.integrationData, ...data })
}

const buildFieldMapping = (): Array<{ column: string; value: string }> =>
  fieldMappingRows.value
    .filter((row) => row.column && row.formFieldKey)
    .map((row) => ({ column: row.column, value: row.formFieldKey }))

const loadSpreadsheets = async () => {
  loadingSpreadsheets.value = true
  const { data } = await request<{ data?: { spreadsheets: GoogleSpreadsheetOption[] } }>(
    'integrations/google-sheets/spreadsheets',
    { method: 'GET' },
  )
  spreadsheets.value = data?.data?.spreadsheets || []
  loadingSpreadsheets.value = false
}

const loadWorksheets = async (spreadsheetId: string) => {
  if (!spreadsheetId) return
  loadingWorksheets.value = true
  const { data } = await request<{ data?: { worksheets: GoogleWorksheetOption[] } }>(
    `integrations/google-sheets/worksheets?spreadsheet_id=${encodeURIComponent(spreadsheetId)}`,
    { method: 'GET' },
  )
  worksheets.value = data?.data?.worksheets || []
  loadingWorksheets.value = false
}

const loadColumns = async (spreadsheetId: string, worksheetName: string) => {
  if (!spreadsheetId || !worksheetName) return
  loadingColumns.value = true
  const { data } = await request<{ data?: { columns: string[] } }>(
    `integrations/google-sheets/columns?spreadsheet_id=${encodeURIComponent(spreadsheetId)}&worksheet_name=${encodeURIComponent(worksheetName)}`,
    { method: 'GET' },
  )
  columns.value = (data?.data?.columns || []).map((col) => ({ column: col, label: col }))
  loadingColumns.value = false
}

const onSpreadsheetChange = async (spreadsheetId: string) => {
  const sheet = spreadsheets.value.find((s) => s.id === spreadsheetId)
  updateIntegrationData({
    spreadsheet_id: spreadsheetId,
    spreadsheet_name: sheet?.name || '',
    worksheet_name: '',
    field_mapping: [],
  })
  fieldMappingRows.value = [{ formFieldKey: '', column: '' }]
  await loadWorksheets(spreadsheetId)
}

const onWorksheetChange = async (worksheetName: string) => {
  updateIntegrationData({ worksheet_name: worksheetName, field_mapping: [] })
  fieldMappingRows.value = [{ formFieldKey: '', column: '' }]
  if (props.integrationData.spreadsheet_id) {
    await loadColumns(props.integrationData.spreadsheet_id, worksheetName)
  }
}

const updateMappingFormField = (index: number, value: string) => {
  fieldMappingRows.value[index].formFieldKey = value
}

const updateMappingColumn = (index: number, value: string) => {
  fieldMappingRows.value[index].column = value
}

const addMappingRow = () => {
  fieldMappingRows.value.push({ formFieldKey: '', column: '' })
}

const removeMappingRow = (index: number) => {
  fieldMappingRows.value.splice(index, 1)
}

const validate = (): boolean => {
  validationErrors.value = {}
  if (!props.integrationData.spreadsheet_id) {
    validationErrors.value.spreadsheet_id = getLabel('spreadsheet_required')
  }
  if (!props.integrationData.worksheet_name) {
    validationErrors.value.worksheet_name = getLabel('worksheet_required')
  }
  return Object.keys(validationErrors.value).length === 0
}

const handleSave = () => {
  if (!validate()) return
  emit('save', {
    ...props.integrationData,
    field_mapping: buildFieldMapping(),
  })
}

const initMappingRows = () => {
  const mappings = props.integrationData.field_mapping || []
  if (mappings.length > 0) {
    fieldMappingRows.value = mappings.map((m) => ({
      formFieldKey: m.value,
      column: m.column,
    }))
  } else {
    fieldMappingRows.value = [{ formFieldKey: '', column: '' }]
  }
}

watch(
  () => props.integrationData.field_mapping,
  () => initMappingRows(),
  { immediate: true },
)

watch(
  () => fieldMappingRows.value.length,
  async () => {
    await nextTick()
    scrollbarRef.value?.update()
  },
)

onMounted(async () => {
  await loadSpreadsheets()
  if (props.integrationData.spreadsheet_id) {
    await loadWorksheets(props.integrationData.spreadsheet_id)
  }
  if (props.integrationData.spreadsheet_id && props.integrationData.worksheet_name) {
    await loadColumns(props.integrationData.spreadsheet_id, props.integrationData.worksheet_name)
  }
})
</script>

<style lang="scss" scoped>
.ivyforms-google-sheets-form {
  height: 100%;
  min-height: 0;

  :deep(.ivyforms-scrollbar) {
    flex: 1;
    min-height: 0;
  }

  &__option-bar {
    border-bottom: 1px solid var(--map-divider);
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
  }

  &__fields {
    padding-bottom: 48px;
  }

  &__mapping-grid {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  &__mapping-header,
  &__mapping-row {
    display: grid;
    grid-template-columns: 1fr 1fr auto;
    gap: 12px;
    align-items: center;
  }

  &__mapping-header {
    color: var(--map-base-text--1);
  }

  &__mapping-actions {
    display: flex;
    gap: 4px;
  }
}
</style>
