import { describe, expect, it } from 'vitest'

import type { ReservationTaskFieldResult } from '@/types/reservation'
import {
  buildInitialFieldValues,
  buildEditableFieldValues,
  groupReservationFields,
  isReservationFieldEditable,
  isReservationManualReviewFieldWritable,
  isSelectField,
  validateReservationFieldValues,
} from '@/utils/reservationFieldRules'

function createField(overrides: Partial<ReservationTaskFieldResult>): ReservationTaskFieldResult {
  return {
    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: null,
    display_condition: null,
    validation_rule: null,
    write_path: null,
    opera_write_participation: 'N',
    opera_parameter_mapping: null,
    notes: null,
    value: null,
    ...overrides,
  }
}

describe('validateReservationFieldValues', () => {
  it('validates required, enum, date, and number fields from backend metadata', () => {
    const errors = validateReservationFieldValues(
      [
        createField({
          field_path: 'guest.name',
          display_name: '客人姓名',
          required_rule: 'Y',
        }),
        createField({
          field_path: 'room.type',
          display_name: '房型',
          select_editable: 'Y',
          enum_options: '豪华 Q1A, 行政套房',
        }),
        createField({
          field_path: 'stay.arrival_date',
          display_name: '入住日期',
          date_picker: 'Y',
        }),
        createField({
          field_path: 'room.count',
          display_name: '房间数',
          number_input: 'Y',
        }),
      ],
      {
        'guest.name': '',
        'room.type': '不存在的房型',
        'stay.arrival_date': '2026/07/08',
        'room.count': 'abc',
      },
    )

    expect(errors).toMatchObject({
      'guest.name': {
        code: 'required',
        field_name: '客人姓名',
      },
      'room.type': {
        code: 'enum',
        field_name: '房型',
      },
      'stay.arrival_date': {
        code: 'date',
        field_name: '入住日期',
      },
      'room.count': {
        code: 'number',
        field_name: '房间数',
      },
    })
  })

  it('groups all backend-returned fields without rebuilding display-condition logic', () => {
    const groups = groupReservationFields(
      [
        createField({
          field_path: 'case_keys.group_code',
          display_name: 'Group Code',
          display_condition: '对象为Group Block或Allotment时展示',
        }),
        createField({
          field_path: 'case_keys.confirmation_number',
          display_name: 'Confirmation No.',
          display_condition: '对象为FIT Reservation时展示',
        }),
      ],
      '基础信息',
      {
        'extracted_fields.booking_object_type': 'Group Block',
        'case_keys.group_code': 'GRP-001',
      },
    )

    expect(groups.flatMap((group) => group.fields.map((field) => field.field_path))).toEqual([
      'case_keys.group_code',
      'case_keys.confirmation_number',
    ])
  })

  it('builds a backend-safe editable payload without readonly or omitted fields', () => {
    const payload = buildEditableFieldValues(
      [
        createField({
          field_path: 'visible_reason',
          display_name: '生成原因',
          editable: 'N',
          input_editable: 'N',
          required_rule: 'Y',
        }),
        createField({
          field_path: 'case_keys.group_code',
          display_name: 'Group Code',
          display_condition: '对象为Group Block或Allotment时展示',
        }),
      ],
      {
        visible_reason: 'AI extracted this task.',
        'case_keys.group_code': 'GRP-001',
        'case_keys.confirmation_number': 'CNF-NOT-RETURNED',
        'extracted_fields.booking_object_type': 'Group Block',
      },
      false,
    )

    expect(payload).toEqual({
      'case_keys.group_code': 'GRP-001',
    })
  })

  it('treats detail.fields as the authoritative backend-filtered field set', () => {
    const fields = [
      createField({
        field_path: 'extracted_fields.booking_object_type',
        display_name: '订单对象类型',
        select_editable: 'Y',
        input_editable: 'N',
        enum_options: 'Group Block, FIT Reservation',
        value: 'Group Block',
      }),
      createField({
        field_path: 'case_keys.group_code',
        display_name: 'Group Code',
        value: 'GRP-001',
      }),
    ]
    const values = buildInitialFieldValues(fields, null, '20260711-p0')
    const groups = groupReservationFields(fields, '基础信息', {
      ...values,
      'case_keys.confirmation_number': 'CNF-SHOULD-NOT-RENDER',
      attachments: [
        {
          name: 'hidden-attachment.pdf',
        },
      ],
    })
    const payload = buildEditableFieldValues(
      fields,
      {
        ...values,
        'case_keys.confirmation_number': 'CNF-SHOULD-NOT-SUBMIT',
        attachments: [
          {
            name: 'hidden-attachment.pdf',
          },
        ],
      },
      false,
    )

    expect(groups.flatMap((group) => group.fields.map((field) => field.field_path))).toEqual([
      'extracted_fields.booking_object_type',
      'case_keys.group_code',
    ])
    expect(payload).toEqual({
      'extracted_fields.booking_object_type': 'Group Block',
      'case_keys.group_code': 'GRP-001',
    })
    expect(payload).not.toHaveProperty('case_keys.confirmation_number')
    expect(payload).not.toHaveProperty('attachments')
  })

  it('uses field control metadata before legacy editable flags when building payloads', () => {
    const payload = buildEditableFieldValues(
      [
        createField({
          field_path: 'case_keys.group_code',
          display_name: 'Group Code',
          value: 'GRP-001',
          control_type: 'text',
          edit_scope: 'normal_and_manual_review',
          write_target: 'field_values',
          raw_readonly: false,
        } as Partial<ReservationTaskFieldResult>),
        createField({
          field_path: 'source_message.attachments',
          display_name: '来源附件',
          value: [{ name: 'rooming-list.pdf' }],
          editable: 'Y',
          input_editable: 'Y',
          control_type: 'file',
          edit_scope: 'never',
          write_target: 'none',
          raw_readonly: true,
        } as Partial<ReservationTaskFieldResult>),
        createField({
          field_path: 'route_code',
          display_name: '路由代码',
          value: 'R01_NEW_BOOKING_NORMAL',
          editable: 'Y',
          input_editable: 'Y',
          control_type: 'workflow_state',
          edit_scope: 'system_only',
          write_target: 'none',
          raw_readonly: false,
        } as Partial<ReservationTaskFieldResult>),
      ],
      {
        'case_keys.group_code': 'GRP-001',
        'source_message.attachments': [{ name: 'rooming-list.pdf' }],
        route_code: 'R01_NEW_BOOKING_NORMAL',
      },
      false,
    )

    expect(payload).toEqual({
      'case_keys.group_code': 'GRP-001',
    })
  })

  it('submits dual draft and review fields in normal editable payloads', () => {
    const payload = buildEditableFieldValues(
      [
        createField({
          field_path: 'case_keys.group_code',
          display_name: 'Group Code',
          value: 'GRP-001',
          control_type: 'text',
          edit_scope: 'normal_and_manual_review',
          write_target: 'draft_payload_and_review_resolution',
          raw_readonly: false,
        } as Partial<ReservationTaskFieldResult>),
      ],
      {
        'case_keys.group_code': 'GRP-001',
      },
      false,
    )

    expect(payload).toEqual({
      'case_keys.group_code': 'GRP-001',
    })
  })

  it('allows manual review overrides only for fields opened by backend metadata', () => {
    expect(
      isReservationManualReviewFieldWritable(
        createField({
          field_path: 'extracted_fields.room_items.0.pms_room_type_code',
          field_pointer: '/extracted_fields/room_items/0/pms_room_type_code',
          control_type: 'select',
          edit_scope: 'manual_review_only',
          write_target: 'review_resolution.field_overrides',
          raw_readonly: false,
        }),
      ),
    ).toBe(true)
    expect(
      isReservationManualReviewFieldWritable(
        createField({
          field_path: 'case_keys.group_code',
          field_pointer: '/case_keys/group_code',
          control_type: 'text',
          edit_scope: 'normal_and_manual_review',
          write_target: 'draft_payload_and_review_resolution',
          raw_readonly: false,
        }),
      ),
    ).toBe(true)
    expect(
      isReservationManualReviewFieldWritable(
        createField({
          field_path: 'route_code',
          control_type: 'workflow_state',
          edit_scope: 'system_only',
          write_target: 'none',
          raw_readonly: false,
        }),
      ),
    ).toBe(false)
    expect(
      isReservationManualReviewFieldWritable(
        createField({
          field_path: 'source_message.attachments',
          control_type: 'file',
          edit_scope: 'never',
          write_target: 'none',
          raw_readonly: true,
        }),
      ),
    ).toBe(false)
  })

  it('does not render review-resolution-only fields as normal editable controls', () => {
    expect(
      isReservationFieldEditable(
        createField({
          field_path: 'extracted_fields.room_items.0.pms_room_type_code',
          control_type: 'select',
          edit_scope: 'manual_review_only',
          write_target: 'review_resolution.field_overrides',
          enum_options: 'RM1, RM2',
          raw_readonly: false,
        }),
        false,
      ),
    ).toBe(false)
    expect(
      isReservationManualReviewFieldWritable(
        createField({
          field_path: 'extracted_fields.room_items.0.pms_room_type_code',
          field_pointer: '/extracted_fields/room_items/0/pms_room_type_code',
          control_type: 'select',
          edit_scope: 'manual_review_only',
          write_target: 'review_resolution.field_overrides',
          enum_options: 'RM1, RM2',
          raw_readonly: false,
        }),
      ),
    ).toBe(true)
  })

  it('does not treat catalog-backed select metadata as a static enum select', () => {
    const catalogField = createField({
      field_path: 'extracted_fields.room_items.0.pms_room_type_code',
      control_type: 'select',
      edit_scope: 'manual_review_only',
      write_target: 'review_resolution.field_overrides',
      options_source: 'active_pms_room_type_catalog',
      enum_options: 'Q1A, DLX',
      raw_readonly: false,
    })
    const staticField = createField({
      field_path: 'extracted_fields.payment_method',
      control_type: 'select',
      edit_scope: 'normal_task',
      write_target: 'draft_payload.field_values',
      options_source: 'static_enum',
      enum_options: 'PREPAID, HOTEL_COLLECT',
      raw_readonly: false,
    })

    expect(isSelectField(catalogField)).toBe(false)
    expect(isReservationManualReviewFieldWritable(catalogField)).toBe(true)
    expect(isSelectField(staticField)).toBe(true)
  })

  it('honors edit scope white lists for normal payload and manual review writes', () => {
    const manualOnlyPayloadField = createField({
      field_path: 'case_keys.confirmation_number',
      control_type: 'text',
      edit_scope: 'manual_review_only',
      write_target: 'field_values',
      raw_readonly: false,
    })
    const workflowDualTargetField = createField({
      field_path: 'review_status',
      control_type: 'text',
      edit_scope: 'workflow_only',
      write_target: 'draft_payload_and_review_resolution',
      raw_readonly: false,
    })
    const normalOnlyReviewTargetField = createField({
      field_path: 'case_keys.group_code',
      control_type: 'text',
      edit_scope: 'normal_task',
      write_target: 'review_resolution.field_overrides',
      raw_readonly: false,
    })

    expect(isReservationFieldEditable(manualOnlyPayloadField, false)).toBe(false)
    expect(isReservationFieldEditable(workflowDualTargetField, false)).toBe(false)
    expect(isReservationManualReviewFieldWritable(manualOnlyPayloadField)).toBe(false)
    expect(isReservationManualReviewFieldWritable(workflowDualTargetField)).toBe(false)
    expect(isReservationManualReviewFieldWritable(normalOnlyReviewTargetField)).toBe(false)
    expect(buildEditableFieldValues(
      [manualOnlyPayloadField, workflowDualTargetField],
      {
        'case_keys.confirmation_number': 'CNF-001',
        review_status: 'PENDING',
      },
      false,
    )).toEqual({})
  })

  it('hydrates P0 room_items fields from field_values and submits main field_path keys', () => {
    const roomTypeField = createField({
      field_path: 'extracted_fields.room_items.0.room_type_raw',
      field_pointer: '/extracted_fields/room_items/0/room_type_raw',
      legacy_field_path: 'extracted_fields.room_type',
      display_name: '房型原文',
    })
    const pmsCodeField = createField({
      field_path: 'extracted_fields.room_items.0.pms_room_type_code',
      field_pointer: '/extracted_fields/room_items/0/pms_room_type_code',
      legacy_field_path: 'extracted_fields.pms_room_type_code',
      display_name: 'PMS 房型代码',
    })

    const values = buildInitialFieldValues(
      [roomTypeField, pmsCodeField],
      {
        field_values: {
          'extracted_fields.room_items.0.room_type_raw': 'Deluxe Q1A',
          'extracted_fields.room_items.0.pms_room_type_code': 'Q1A',
        },
      },
      '20260711-p0',
    )
    const payload = buildEditableFieldValues([roomTypeField, pmsCodeField], values, false)

    expect(values).toMatchObject({
      'extracted_fields.room_items.0.room_type_raw': 'Deluxe Q1A',
      'extracted_fields.room_items.0.pms_room_type_code': 'Q1A',
    })
    expect(payload).toEqual({
      'extracted_fields.room_items.0.room_type_raw': 'Deluxe Q1A',
      'extracted_fields.room_items.0.pms_room_type_code': 'Q1A',
    })
    expect(payload).not.toHaveProperty('extracted_fields.room_type')
    expect(payload).not.toHaveProperty('extracted_fields.pms_room_type_code')
  })

  it('hydrates P0 fields from nested field_values as a defensive fallback', () => {
    const values = buildInitialFieldValues(
      [
        createField({
          field_path: 'extracted_fields.room_items.0.room_quantity',
          field_pointer: '/extracted_fields/room_items/0/room_quantity',
          legacy_field_path: 'extracted_fields.room_quantity',
          display_name: '房间数量',
        }),
      ],
      {
        field_values: {
          extracted_fields: {
            room_items: [
              {
                room_quantity: 2,
              },
            ],
          },
        },
      },
      '20260711-p0',
    )

    expect(values).toEqual({
      'extracted_fields.room_items.0.room_quantity': 2,
    })
  })

  it('hydrates code-v1 historical fields from legacy_field_values into P0 main keys', () => {
    const values = buildInitialFieldValues(
      [
        createField({
          field_path: 'extracted_fields.room_items.0.pms_room_type_code',
          field_pointer: '/extracted_fields/room_items/0/pms_room_type_code',
          legacy_field_path: 'extracted_fields.pms_room_type_code',
          display_name: 'PMS 房型代码',
        }),
      ],
      {
        field_values: {
          'extracted_fields.room_items.0.pms_room_type_code': 'NEW',
        },
        legacy_field_values: {
          'extracted_fields.pms_room_type_code': 'LEGACY',
        },
      },
      'code-v1',
    )

    expect(values).toEqual({
      'extracted_fields.room_items.0.pms_room_type_code': 'LEGACY',
    })
  })

  it('hydrates code-v1 historical fields from legacy effective_payload when legacy_field_values is absent', () => {
    const values = buildInitialFieldValues(
      [
        createField({
          field_path: 'extracted_fields.room_items.0.pms_room_type_code',
          field_pointer: '/extracted_fields/room_items/0/pms_room_type_code',
          legacy_field_path: 'extracted_fields.pms_room_type_code',
          display_name: 'PMS 房型代码',
        }),
      ],
      {
        effective_payload: {
          extracted_fields: {
            pms_room_type_code: 'LEGACY-NESTED',
          },
        },
      },
      'code-v1',
    )

    expect(values).toEqual({
      'extracted_fields.room_items.0.pms_room_type_code': 'LEGACY-NESTED',
    })
  })

  it('does not create frontend required errors for readonly evidence fields missing in V3 payloads', () => {
    const errors = validateReservationFieldValues(
      [
        createField({
          field_path: 'visible_reason',
          display_name: '生成原因',
          editable: 'N',
          input_editable: 'N',
          required_rule: 'Y',
          value: null,
        }),
        createField({
          field_path: 'extracted_fields.room_items.0.pms_room_type_code',
          display_name: 'PMS 房型代码',
          field_pointer: '/extracted_fields/room_items/0/pms_room_type_code',
          legacy_field_path: 'extracted_fields.pms_room_type_code',
          required_rule: 'Y',
          value: '',
        }),
      ],
      {
        relevant_message_excerpt: 'Please book a Deluxe Q1A room.',
        'extracted_fields.room_items.0.pms_room_type_code': '',
      },
    )

    expect(errors).toEqual({
      'extracted_fields.room_items.0.pms_room_type_code': {
        code: 'required',
        field_name: 'PMS 房型代码',
      },
    })
  })
})
