import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import { createI18n } from 'vue-i18n'

import ReservationTaskFieldRenderer from '@/components/reservation/ReservationTaskFieldRenderer.vue'
import zhCN from '@/i18n/locales/zh-CN'
import type { ReservationTaskFieldResult } from '@/types/reservation'

const fields: ReservationTaskFieldResult[] = [
  {
    row_number: 1,
    card_name: 'New Booking',
    display_area: '客人信息',
    field_path: 'guest.name',
    display_name: '客人姓名',
    visible: 'Y',
    editable: 'Y',
    input_editable: 'Y',
    select_editable: 'N',
    date_picker: 'N',
    number_input: 'N',
    file_display: 'N',
    table_editable: 'N',
    enum_options: null,
    required_rule: 'Y',
    display_condition: null,
    validation_rule: null,
    write_path: 'reservation.guest.name',
    opera_write_participation: 'Y',
    opera_parameter_mapping: 'profile.name',
    notes: null,
    value: '王建国',
  },
  {
    row_number: 2,
    card_name: 'New Booking',
    display_area: '预订信息',
    field_path: 'room.type',
    display_name: '房型',
    visible: 'Y',
    editable: 'Y',
    input_editable: 'N',
    select_editable: 'Y',
    date_picker: 'N',
    number_input: 'N',
    file_display: 'N',
    table_editable: 'N',
    enum_options: '豪华 Q1A, 行政套房',
    required_rule: 'Y',
    display_condition: null,
    validation_rule: null,
    write_path: 'reservation.room.type',
    opera_write_participation: 'Y',
    opera_parameter_mapping: 'roomType',
    notes: null,
    value: '豪华 Q1A',
  },
]

function mountRenderer(readOnly = false) {
  const i18n = createI18n({
    legacy: false,
    locale: 'zh-CN',
    messages: {
      'zh-CN': zhCN,
    },
  })

  return mount(ReservationTaskFieldRenderer, {
    props: {
      fields,
      modelValue: {
        'guest.name': '王建国',
        'room.type': '豪华 Q1A',
      },
      readOnly,
      validationErrors: {},
    },
    global: {
      plugins: [i18n],
    },
  })
}

describe('ReservationTaskFieldRenderer', () => {
  it('emits updates using field_path as key', async () => {
    const wrapper = mountRenderer()
    const input = wrapper.find('textarea')

    await input.setValue('Mark Lee')

    expect(wrapper.emitted('update:modelValue')?.[0]?.[0]).toMatchObject({
      'guest.name': 'Mark Lee',
      'room.type': '豪华 Q1A',
    })
  })

  it('renders editable select from enum options', () => {
    const wrapper = mountRenderer()

    expect(wrapper.find('select').exists()).toBe(true)
    expect(wrapper.findAll('option')).toHaveLength(2)
  })

  it('renders static values when the task is read only', () => {
    const wrapper = mountRenderer(true)

    expect(wrapper.find('textarea').exists()).toBe(false)
    expect(wrapper.text()).toContain('王建国')
  })

  it('shows validation errors next to their fields', () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'zh-CN',
      messages: {
        'zh-CN': zhCN,
      },
    })

    const wrapper = mount(ReservationTaskFieldRenderer, {
      props: {
        fields,
        modelValue: {
          'guest.name': '',
          'room.type': '豪华 Q1A',
        },
        readOnly: false,
        validationErrors: {
          'guest.name': '客人姓名为必填项',
        },
      },
      global: {
        plugins: [i18n],
      },
    })

    expect(wrapper.text()).toContain('客人姓名为必填项')
    expect(wrapper.find('textarea').attributes('aria-invalid')).toBe('true')
  })

  it('renders file fields as attachment items instead of raw JSON', () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'zh-CN',
      messages: {
        'zh-CN': zhCN,
      },
    })
    const fileField: ReservationTaskFieldResult = {
      ...fields[0]!,
      row_number: 3,
      display_area: '证据',
      field_path: 'attachments',
      display_name: '相关附件',
      editable: 'N',
      input_editable: 'N',
      file_display: 'Y',
      required_rule: 'N',
      notes: '附件、图片、PDF、表格证据展示。',
      value: null,
    }

    const wrapper = mount(ReservationTaskFieldRenderer, {
      props: {
        fields: [fileField],
        modelValue: {
          attachments: [
            {
              id: 'att-1',
              name: 'WYNDHAM LIANTAI 2026 UPDATE BOOKING 12-05-2026 NO.1.xlsx',
              content_type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            },
            {
              id: 'att-2',
              file_name: 'Rooming List.pdf',
              mime_type: 'application/pdf',
            },
          ],
        },
        readOnly: true,
        validationErrors: {},
      },
      global: {
        plugins: [i18n],
      },
    })

    expect(wrapper.findAll('.field-file-item')).toHaveLength(2)
    expect(wrapper.text()).toContain('WYNDHAM LIANTAI 2026 UPDATE BOOKING 12-05-2026 NO.1.xlsx')
    expect(wrapper.text()).toContain('Rooming List.pdf')
    expect(wrapper.text()).toContain('Excel')
    expect(wrapper.text()).toContain('PDF')
    expect(wrapper.text()).not.toContain('{"id"')
    expect(wrapper.text()).not.toContain('"name"')
    expect(wrapper.text()).not.toContain('content_type')
  })

  it('only renders http and https attachment urls as links', () => {
    const i18n = createI18n({
      legacy: false,
      locale: 'zh-CN',
      messages: {
        'zh-CN': zhCN,
      },
    })
    const fileField: ReservationTaskFieldResult = {
      ...fields[0]!,
      row_number: 3,
      display_area: '证据',
      field_path: 'attachments',
      display_name: '相关附件',
      editable: 'N',
      input_editable: 'N',
      file_display: 'Y',
      required_rule: 'N',
      notes: null,
      value: null,
    }

    const wrapper = mount(ReservationTaskFieldRenderer, {
      props: {
        fields: [fileField],
        modelValue: {
          attachments: [
            {
              id: 'safe-1',
              name: '安全附件.pdf',
              external_url: 'https://oss.example/safe.pdf',
            },
            {
              id: 'unsafe-js',
              name: '脚本附件.pdf',
              external_url: 'javascript:alert(1)',
            },
            {
              id: 'unsafe-data',
              name: '内联数据附件.pdf',
              download_url: 'data:text/html;base64,PHNjcmlwdD5iYWQoKTwvc2NyaXB0Pg==',
            },
            {
              id: 'unsafe-file',
              name: '本地文件附件.pdf',
              oss_url: 'file:///tmp/private.pdf',
            },
          ],
        },
        readOnly: true,
        validationErrors: {},
      },
      global: {
        plugins: [i18n],
      },
    })

    const links = wrapper.findAll('.field-file-item a')

    expect(links).toHaveLength(1)
    expect(links[0]?.text()).toBe('安全附件.pdf')
    expect(links[0]?.attributes('href')).toBe('https://oss.example/safe.pdf')
    expect(wrapper.text()).toContain('脚本附件.pdf')
    expect(wrapper.text()).toContain('内联数据附件.pdf')
    expect(wrapper.text()).toContain('本地文件附件.pdf')
    expect(wrapper.html()).not.toContain('javascript:alert')
    expect(wrapper.html()).not.toContain('data:text/html')
    expect(wrapper.html()).not.toContain('file:///tmp/private.pdf')
  })
})
