<template>
  <div
    class="ivyforms-styled-form-preview ivyforms-flex ivyforms-flex-1 ivyforms-gap-8 ivyforms-flex-direction-column"
  >
    <PageSection>
      <IvyScrollbar modifier="outside-vertical">
        <div :class="outerWrapperClasses">
          <div
            :class="[
              'ivyforms-styled-form-preview__wrapper',
              'ivyforms-form-wrapper',
              `ivyforms-form-wrapper-${previewFormId}`,
            ]"
            :style="wrapperAlignmentStyle"
          >
            <h2
              v-if="formBuilderStore.showTitle"
              class="ivyforms-styled-form-preview__title ivyforms-form-title"
            >
              {{ formBuilderStore.name || getLabel('form_title') }}
            </h2>

            <p
              v-if="formBuilderStore.showDescription"
              class="ivyforms-styled-form-preview__description ivyforms-form-description"
            >
              {{ formBuilderStore.description || getLabel('sample_form_description') }}
            </p>

            <IvyForm
              :model="formModel"
              :class="[
                'ivyforms-styled-form-preview__form',
                'ivyforms-form',
                `ivyforms-form-${previewFormId}`,
                'ivyforms-flex',
                'ivyforms-flex-direction-column',
                'ivyforms-gap-8',
              ]"
            >
              <template v-for="(row, rowIndex) in previewFieldsByRow" :key="rowIndex">
                <div
                  class="ivyforms-form-row ivyforms-flex ivyforms-mb-16 ivyforms-width-100 ivyforms-flex-wrap-wrap"
                  :style="{ gap: horizontalGapCss }"
                >
                  <template v-for="field in row" :key="field.type + '_' + field.fieldIndex">
                    <div
                      class="ivyforms-form-field"
                      :style="getRowFieldStyle(field, row, horizontalGapCss)"
                    >
                      <component
                        :is="getPreviewFieldComponent(field.type)"
                        :model-value="getFieldValue(field) as never"
                        :error="''"
                        :field-errors="{}"
                        :disabled="
                          field.type === 'checkbox' || field.type === 'radio' ? false : false
                        "
                        :field="
                          field.type === 'checkbox' || field.type === 'radio'
                            ? { ...field, readOnly: false, disabled: false }
                            : field
                        "
                        :horizontal-gap="horizontalGapCss"
                        @update:model-value="(value) => updateFieldValue(field, value)"
                      />
                    </div>
                  </template>
                </div>
              </template>

              <div
                :class="[
                  'ivyforms-form-submit',
                  `ivyforms-form-submit--${formBuilderStore.submitButtonSettings.position}`,
                ]"
              >
                <IvyButtonAction priority="tertiary" type="border">
                  {{ formBuilderStore.submitButtonSettings.label || getLabel('submit') }}
                </IvyButtonAction>
              </div>
            </IvyForm>
          </div>
        </div>
      </IvyScrollbar>
      <IvyButtonAction
        class="ivyforms-sample-view-btn"
        priority="tertiary"
        type="ghost"
        icon-start="eye-opened"
        @click="toggleSampleView"
      >
        {{ getLabel(formBuilderStore.showSampleView ? 'back_to_form' : 'sample_view') }}
      </IvyButtonAction>
    </PageSection>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, provide, watch, ref, type CSSProperties } from 'vue'
import type { Component } from 'vue'
import PageSection from '@/views/admin/parts/PageSection.vue'
import IvyScrollbar from '@/views/_components/scrollbar/IvyScrollbar.vue'
import IvyForm from '@/views/_components/form/IvyForm.vue'
import IvyButtonAction from '@/views/_components/button/IvyButtonAction.vue'
import { useFormBuilder } from '@/stores/useFormBuilder'
import { useLabels } from '@/composables/useLabels'
import { generateFormCSS, injectFormCSS, parseCssClassList } from '@/utils/formStyleGenerator'
import TextFormField from '@/views/public/fields/TextFormField.vue'
import EmailFormField from '@/views/public/fields/EmailFormField.vue'
import ParagraphFormField from '@/views/public/fields/ParagraphFormField.vue'
import PhoneFormField from '@/views/public/fields/PhoneFormField.vue'
import NumberFormField from '@/views/public/fields/NumberFormField.vue'
import NameFormField from '@/views/public/fields/NameFormField.vue'
import RadioFormField from '@/views/public/fields/RadioFormField.vue'
import SelectFormField from '@/views/public/fields/SelectFormField.vue'
import CheckboxFormField from '@/views/public/fields/CheckboxFormField.vue'
import AddressFormField from '@/views/public/fields/AddressFormField.vue'
import DateFormField from '@/views/public/fields/DateFormField.vue'
import TimeFormField from '@/views/public/fields/TimeFormField.vue'
import RatingFormField from '@/views/public/fields/RatingFormField.vue'
import WebsiteFormField from '@/views/public/fields/WebsiteFormField.vue'
import RecaptchaFormField from '@/views/public/fields/RecaptchaFormField.vue'
import TurnstileFormField from '@/views/public/fields/TurnstileFormField.vue'
import HCaptchaFormField from '@/views/public/fields/HCaptchaFormField.vue'
import { useFieldWidth } from '@/composables/useFieldWidth'
import { useHorizontalSpacing } from '@/composables/useHorizontalSpacing'
import type { Field } from '@/types/field'
import api from '@/composables/IvyFormAPI'
import { buildFormPopperScopeClass } from '@/utils/form-styles/selectors'

const formBuilderStore = useFormBuilder()
const { getLabel } = useLabels()

const previewFormId = computed(() => formBuilderStore.formId ?? 'builder-preview')
const formPopperScopeClass = computed(() => buildFormPopperScopeClass(previewFormId.value))
provide('formPopperScopeClass', formPopperScopeClass)

const formIdNumber = computed(() =>
  formBuilderStore.formId ? parseInt(formBuilderStore.formId, 10) : 0,
)
const formModel = computed(() => fieldValues.value)
const styleSettings = computed(() => formBuilderStore.styleSettings)
const parsedCustomClasses = computed(() =>
  parseCssClassList(styleSettings.value?.customCssClass || ''),
)
const parsedAdditionalClasses = computed(() =>
  parseCssClassList(styleSettings.value?.additionalCssClasses || ''),
)
const outerWrapperClasses = computed(() => [
  'ivyforms-styled-form-preview__outer',
  `ivyforms-form-wrapper-${previewFormId.value}`,
  `ivyforms-form-${previewFormId.value}`,
  ...parsedCustomClasses.value,
  ...parsedAdditionalClasses.value,
])
const baseSelector = computed(() => {
  const wrapperSelector = `.ivyforms-form-wrapper-${previewFormId.value}`
  const customClassValue = parsedCustomClasses.value[0]
  if (customClassValue) {
    return `${wrapperSelector}.${customClassValue}`
  }
  return wrapperSelector
})

const horizontalGapCss = useHorizontalSpacing(styleSettings)

const wrapperAlignmentStyle = computed<CSSProperties>(() => {
  const alignment = styleSettings.value?.advancedMode?.general?.alignment || 'left'
  if (alignment === 'left') return {}
  const alignMap = { center: 'center', right: 'flex-end' }
  return {
    display: 'flex',
    flexDirection: 'column' as const,
    alignItems: (alignMap[alignment as keyof typeof alignMap] ||
      'flex-start') as CSSProperties['alignItems'],
  }
})

const labelColor = computed(() => {
  const quickMode = styleSettings.value?.quickMode
  const advancedMode = styleSettings.value?.advancedMode
  return advancedMode?.fieldLabels?.label?.fontColor || quickMode?.labelFontColor || ''
})

const buttonTextColor = computed(() => {
  const quickMode = styleSettings.value?.quickMode
  const advancedMode = styleSettings.value?.advancedMode
  return advancedMode?.buttonStates?.normal?.textColor || quickMode?.buttonText || ''
})

const requiredIndicatorColor = computed(
  () => styleSettings.value?.advancedMode?.fieldLabels?.requiredIndicator?.fontColor || '#E53E3E',
)

const fieldValues = ref<Record<string, unknown>>({})
const { groupFieldsByRow, getFieldWidthStyle } = useFieldWidth()

const getFieldKey = (field: Field) => `${field.type}_${field.fieldIndex}`

const getFieldValue = (field: Field) => {
  const key = getFieldKey(field)
  if (fieldValues.value[key] !== undefined) {
    return fieldValues.value[key]
  }
  return field.defaultValue || ''
}

const updateFieldValue = (field: Field, value: unknown) => {
  fieldValues.value[getFieldKey(field)] = value
}

const getNormalizedField = (field: Field, fallbackIndex: number): Field => {
  return {
    ...field,
    formId: formIdNumber.value,
    fieldIndex: field.fieldIndex ?? fallbackIndex,
    id: field.id || 0,
    position: field.position ?? fallbackIndex,
    label: field.label || '',
    defaultValue: field.defaultValue || '',
    required: field.required || false,
    placeholder: field.placeholder || '',
    fieldOptions: field.fieldOptions || [],
  }
}

const buildNamePreviewField = (field: Field, fallbackIndex: number): Field => {
  const normalized = getNormalizedField(field, fallbackIndex)
  const nameFields = field.nameFields || []
  const nameFieldTypes = field.nameFieldTypes?.length
    ? field.nameFieldTypes
    : nameFields.map((_, idx) => `nameField${idx + 1}`)

  const decorated: Record<string, unknown> = { ...normalized, nameFieldTypes }

  nameFieldTypes.forEach((type, idx) => {
    const data = nameFields[idx]
    decorated[`${type}Label`] = data?.label || ''
    decorated[`${type}Placeholder`] = data?.placeholder || ''
    decorated[`${type}Required`] = !!data?.required
    decorated[`${type}Description`] = data?.description || ''
    decorated[`${type}HideLabel`] = !!data?.optionHide
    decorated[`${type}RequiredMessage`] = data?.requiredMessage || ''
  })

  return decorated as Field
}

const buildAddressPreviewField = (field: Field, fallbackIndex: number): Field => {
  const normalized = getNormalizedField(field, fallbackIndex)
  const addressFields = field.addressFields || []
  const addressFieldTypes = field.addressFieldTypes?.length
    ? field.addressFieldTypes
    : addressFields.map((entry) => entry.type)

  const decorated: Record<string, unknown> = { ...normalized, addressFieldTypes }

  addressFieldTypes.forEach((type) => {
    const data = addressFields.find((entry) => entry.type === type)
    decorated[`${type}Label`] = data?.label || ''
    decorated[`${type}Placeholder`] = data?.placeholder || ''
    decorated[`${type}Required`] = !!data?.required
    decorated[`${type}Description`] = data?.description || ''
    decorated[`${type}HideLabel`] = !!data?.hideLabel
    decorated[`${type}Visible`] = data?.visible !== false
    decorated[`${type}RequiredMessage`] = data?.requiredMessage || ''
  })

  return decorated as Field
}

const previewFields = computed(() =>
  formBuilderStore.fields.map((field, index) => {
    if (field.type === 'name') {
      return buildNamePreviewField(field, index)
    }
    if (field.type === 'address') {
      return buildAddressPreviewField(field, index)
    }
    return getNormalizedField(field, index)
  }),
)

const previewFieldsByRow = computed(() => {
  const rows = groupFieldsByRow(previewFields.value)
  return Array.from(rows.entries())
    .sort((a, b) => a[0] - b[0])
    .map(([, rowFields]) => rowFields)
})

const getRowFieldStyle = (field: Field, rowFields: Field[], gap: string) => ({
  width: getFieldWidthStyle(field, rowFields, gap),
  flex: '0 0 auto',
})

const getPreviewFieldComponent = (fieldType: string): Component => {
  let base: Component

  switch (fieldType) {
    case 'text':
      base = TextFormField
      break
    case 'email':
      base = EmailFormField
      break
    case 'textarea':
    case 'paragraph':
      base = ParagraphFormField
      break
    case 'tel':
    case 'phone':
      base = PhoneFormField
      break
    case 'number':
      base = NumberFormField
      break
    case 'website':
      base = WebsiteFormField
      break
    case 'recaptcha':
      base = RecaptchaFormField
      break
    case 'turnstile':
      base = TurnstileFormField
      break
    case 'hcaptcha':
      base = HCaptchaFormField
      break
    case 'name':
      base = NameFormField
      break
    case 'radio':
      base = RadioFormField
      break
    case 'checkbox':
      base = CheckboxFormField
      break
    case 'select':
    case 'dropdown':
    case 'multi-select':
      base = SelectFormField
      break
    case 'address':
      base = AddressFormField
      break
    case 'date':
      base = DateFormField
      break
    case 'time':
      base = TimeFormField
      break
    case 'rating':
      base = RatingFormField
      break
    default:
      base = TextFormField
      break
  }

  try {
    const filtered = api.hooks.applyFilters('ivyforms/template/field/filter/component', base, {
      type: fieldType,
    }) as Component
    return filtered || base
  } catch {
    return base
  }
}

const applyStyles = () => {
  let css = generateFormCSS(previewFormId.value, formBuilderStore.styleSettings)

  const extraRules: string[] = []

  // Label color (target all label containers and spans)
  if (labelColor.value) {
    extraRules.push(`
      ${baseSelector.value} .ivyforms-form-item__label,
      ${baseSelector.value} .ivyforms-form-item__label span,
      ${baseSelector.value} .el-form-item__label,
      ${baseSelector.value} .ivyforms-form-label,
      ${baseSelector.value} .ivyforms-form-label span {
        color: ${labelColor.value} !important;
      }
    `)
  }

  // Required indicator color (asterisk)
  if (requiredIndicatorColor.value) {
    extraRules.push(`
      ${baseSelector.value} .ivyforms-form-item__asterisk,
      ${baseSelector.value} .el-form-item__label.is-required::before {
        color: ${requiredIndicatorColor.value} !important;
      }
    `)
  }

  // Button text color (submit only)
  if (buttonTextColor.value) {
    extraRules.push(`
      ${baseSelector.value} .ivyforms-form-submit .ivyforms-button-action,
      ${baseSelector.value} .ivyforms-form-submit .ivyforms-button-action span,
      ${baseSelector.value} .ivyforms-form-submit button.ivyforms-button-action {
        color: ${buttonTextColor.value} !important;
      }
    `)
  }

  // Enable pointer events for radios/checkboxes in preview
  extraRules.push(`
    ${baseSelector.value} .ivyforms-form-field input[type="checkbox"],
    ${baseSelector.value} .ivyforms-form-field input[type="radio"] {
      pointer-events: auto !important;
      cursor: pointer !important;
    }
  `)

  if (extraRules.length) {
    css = `${css}\n${extraRules.join('\n')}`
  }

  injectFormCSS(previewFormId.value, css)
}

onMounted(() => {
  applyStyles()
})

watch(
  () => formBuilderStore.styleSettings,
  () => {
    applyStyles()
  },
  { deep: true },
)

watch(previewFormId, () => {
  applyStyles()
})

// Toggle sample view visibility from styled preview
const toggleSampleView = () => {
  formBuilderStore.showSampleView = !formBuilderStore.showSampleView
}
</script>

<style scoped lang="scss">
.ivyforms-styled-form-preview {
  max-width: 100%;
  overflow: hidden;
  position: relative;

  .el-scrollbar {
    max-width: 100%;
  }

  :deep(.el-scrollbar__wrap) {
    max-width: 100%;
    overflow-x: hidden;
  }

  :deep(.el-scrollbar__view) {
    max-width: 100%;
  }

  &__outer {
    box-sizing: border-box;
  }

  &__wrapper {
    width: 100%;
    max-width: 720px;
    margin: 0 auto;
    box-sizing: border-box;
  }

  :deep(.ivyforms-field__checkbox),
  :deep(.ivyforms-field__radio) {
    pointer-events: auto;
  }

  :deep(.ivyforms-field__checkbox .el-checkbox),
  :deep(.ivyforms-field__checkbox .el-checkbox__input),
  :deep(.ivyforms-field__checkbox .el-checkbox__label),
  :deep(.ivyforms-field__radio .el-radio),
  :deep(.ivyforms-field__radio .el-radio__input),
  :deep(.ivyforms-field__radio .el-radio__label) {
    pointer-events: auto;
    cursor: pointer;
  }

  &__container {
    max-width: 100%;
  }

  .ivyforms-sample-view-btn {
    position: absolute;
    bottom: 24px;
    right: 24px;
    z-index: 100;
    background: var(--map-ground-level-3, white);
    box-shadow: 0px 4px 15px 0px rgba(0, 0, 0, 0.05);
    border-radius: 8px;
  }
}
</style>
