package cn.nianxx.thhotel.workflows.reservation.service.impl;

import cn.nianxx.thhotel.workflows.reservation.common.dto.ReservationTaskCardFieldDefinition;
import cn.nianxx.thhotel.workflows.reservation.common.enums.ReservationTaskCardType;
import cn.nianxx.thhotel.workflows.reservation.service.ReservationTaskCardFieldDefinitionProvider;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

/**
 * JSON 任务卡字段定义提供者。JSON 由《任务卡展示编辑矩阵.xlsx》机械生成，代码只负责加载和筛选。
 */
@Service
public class JsonReservationTaskCardFieldDefinitionProvider implements ReservationTaskCardFieldDefinitionProvider {

    private static final String MATRIX_RESOURCE = "reservation-task-card/field-matrix-v20260706.json";
    private static final Map<String, String> CARD_NAME_BY_TYPE = Map.ofEntries(
            Map.entry(ReservationTaskCardType.NEW_BOOKING.name(), "New Booking 卡"),
            Map.entry(ReservationTaskCardType.UPDATE_BOOKING.name(), "Update Booking 卡"),
            Map.entry(ReservationTaskCardType.CANCEL_BOOKING.name(), "Cancel Booking 卡"),
            Map.entry(ReservationTaskCardType.CANCEL_ALLOTMENT.name(), "Cancel Allotment 卡"),
            Map.entry(ReservationTaskCardType.VOUCHER_RECEIVED.name(), "Voucher Received 卡"),
            Map.entry(ReservationTaskCardType.PAYMENT_EVIDENCE.name(), "Payment Evidence 卡"),
            Map.entry(ReservationTaskCardType.ROOMING_LIST.name(), "Rooming List 卡"),
            Map.entry(ReservationTaskCardType.AMEND_GROUP_CODE.name(), "Amend Group Code 卡"),
            Map.entry(ReservationTaskCardType.TRACE_RESERVATION_NOTES.name(), "Trace / Reservation Notes 卡"),
            Map.entry(ReservationTaskCardType.TA_RECORDER.name(), "TA Recorder 卡"),
            Map.entry(ReservationTaskCardType.INVOICE_GENERATION.name(), "Invoice Generation 卡"),
            Map.entry(ReservationTaskCardType.INVOICE_RECEIVED.name(), "Invoice Received 卡"),
            Map.entry(ReservationTaskCardType.PAYMENT_NOTICE.name(), "Payment Notice 卡"),
            Map.entry(ReservationTaskCardType.MANUAL_RATE_CODE.name(), "Manual RateCode 卡"),
            Map.entry(ReservationTaskCardType.MESSAGE_NOTIFICATION.name(), "Message Notification 信息提醒卡"),
            Map.entry(ReservationTaskCardType.FALLBACK_REVIEW.name(), "Fallback 人工复核卡"),
            Map.entry(ReservationTaskCardType.ADAPTER_CONTRACT_ERROR.name(), "Adapter 契约错误卡"),
            Map.entry(ReservationTaskCardType.SOURCE_MESSAGE_ONLY.name(), "Source Message Only 只读卡")
    );

    private final ObjectMapper objectMapper;
    private List<ReservationTaskCardFieldDefinition> definitions = List.of();

    /**
     * 注入 JSON 解析器，字段矩阵资源在应用启动后加载。
     */
    public JsonReservationTaskCardFieldDefinitionProvider(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    /**
     * 加载字段矩阵 JSON 资源；资源缺失属于配置错误，应阻止服务错误运行。
     */
    @PostConstruct
    public void loadDefinitions() {
        try (InputStream inputStream = new ClassPathResource(MATRIX_RESOURCE).getInputStream()) {
            MatrixResource resource = objectMapper.readValue(inputStream, MatrixResource.class);
            this.definitions = resource.fields().stream()
                    .map(RawFieldDefinition::toDefinition)
                    .toList();
        } catch (IOException exception) {
            throw new IllegalStateException("任务卡字段矩阵资源加载失败", exception);
        }
    }

    /**
     * 按系统任务卡类型读取对应矩阵字段。result_type 当前仅用于后续扩展，不做中文卡名反推。
     */
    @Override
    public List<ReservationTaskCardFieldDefinition> listDefinitions(String taskCardType, String resultType) {
        String cardName = CARD_NAME_BY_TYPE.get(taskCardType);
        if (cardName == null) {
            return List.of();
        }
        return definitions.stream()
                .filter(definition -> cardName.equals(definition.cardName()))
                .toList();
    }

    /**
     * 字段矩阵 JSON 顶层结构。
     */
    private record MatrixResource(
            List<RawFieldDefinition> fields
    ) {
    }

    /**
     * 字段矩阵 JSON 单行结构，与生成后的 snake_case 字段保持一致。
     */
    private record RawFieldDefinition(
            @JsonProperty("row_number")
            Integer rowNumber,
            @JsonProperty("card_name")
            String cardName,
            @JsonProperty("result_type")
            String resultType,
            @JsonProperty("task_type")
            String taskType,
            @JsonProperty("task_subtype")
            String taskSubtype,
            @JsonProperty("applicable_scenario")
            String applicableScenario,
            @JsonProperty("display_area")
            String displayArea,
            @JsonProperty("field_path")
            String fieldPath,
            @JsonProperty("display_name")
            String displayName,
            @JsonProperty("field_source")
            String fieldSource,
            String visible,
            String editable,
            @JsonProperty("input_editable")
            String inputEditable,
            @JsonProperty("select_editable")
            String selectEditable,
            @JsonProperty("date_picker")
            String datePicker,
            @JsonProperty("number_input")
            String numberInput,
            @JsonProperty("file_display")
            String fileDisplay,
            @JsonProperty("table_editable")
            String tableEditable,
            @JsonProperty("enum_options")
            String enumOptions,
            @JsonProperty("required_rule")
            String requiredRule,
            @JsonProperty("default_value_source")
            String defaultValueSource,
            @JsonProperty("display_condition")
            String displayCondition,
            @JsonProperty("validation_rule")
            String validationRule,
            @JsonProperty("write_path")
            String writePath,
            @JsonProperty("opera_write_participation")
            String operaWriteParticipation,
            @JsonProperty("opera_parameter_mapping")
            String operaParameterMapping,
            String notes
    ) {

        /**
         * 将资源行转换为模块内部字段定义，避免业务服务依赖资源 JSON 结构。
         */
        private ReservationTaskCardFieldDefinition toDefinition() {
            return new ReservationTaskCardFieldDefinition(
                    rowNumber,
                    cardName,
                    resultType,
                    taskType,
                    taskSubtype,
                    applicableScenario,
                    displayArea,
                    fieldPath,
                    displayName,
                    fieldSource,
                    visible,
                    editable,
                    inputEditable,
                    selectEditable,
                    datePicker,
                    numberInput,
                    fileDisplay,
                    tableEditable,
                    enumOptions,
                    requiredRule,
                    defaultValueSource,
                    displayCondition,
                    validationRule,
                    writePath,
                    operaWriteParticipation,
                    operaParameterMapping,
                    notes);
        }
    }
}
