package com.ruoyi.system.domain.changerecord.annotation;

import com.ruoyi.system.domain.changerecord.enums.OperationType;
import com.ruoyi.system.domain.changerecord.enums.SubjectType;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 数据变更日志注解。
 *
 * <p>标注在 Mapper 方法上，用于声明该写操作需要向 {@code data_change_record} 写入一条变更记录。</p>
 *
 * <p>同一个方法可以重复声明多个 {@link DataChangeLog}（例如 mapping 表同时需要记录房源侧和经营主体侧）。</p>
 *
 * <h3>idExpr 表达式语法</h3>
 * <ul>
 *     <li>{@code "."} — 参数本身即为 subject_id，适用于 {@code void xxx(String id)} 这种单个裸参数的场景。</li>
 *     <li>{@code "fieldName"} — 从参数中按属性名取值，适用于 POJO 或 Map / {@code @Param("xxx")} 场景。</li>
 *     <li>{@code "listKey[*].fieldName"} — 从参数中取一个 List 再逐个取字段值，适用于批量操作
 *         （如 {@code @Param("list") List<HouseResource> list}）。</li>
 *     <li>{@code "@preload[*].fieldName"} — 从 {@link #preLoadMapper()} 指定的查询结果集里逐个取字段值。</li>
 * </ul>
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(DataChangeLogs.class)
public @interface DataChangeLog {

    /** 主体类型。 */
    SubjectType subjectType();

    /** 操作类型。 */
    OperationType operation();

    /** subject_id 取值表达式，详见类注释。 */
    String idExpr();

    /**
     * 预加载 Mapper 方法的全限定名（例如
     * {@code com.ruoyi.system.mapper.house.HouseResourceBusinessEntityInfoMappingMapper.selectByHouseResourceId}）。
     *
     * <p>用于"写操作前需要先查出被影响 id"的场景（如 mapping 的 deleteByHouseResourceId）。
     * 为空时不触发预加载。预加载结果通过 {@code @preload[*].xxx} 表达式访问。</p>
     */
    String preLoadMapper() default "";
}
