package com.ruoyi.system.domain;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.annotation.Excel;
import lombok.Data;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Set;

import javax.persistence.GeneratedValue;

/**
 * 用户信息对象 info_user
 *
 * @author ruoyi
 * @date 2023-06-25
 */
@Data
@TableName(value = "info_user")
@EqualsAndHashCode(callSuper = false)
public class InfoUser
{
    private static final long serialVersionUID = 1L;

    @TableId(type = IdType.AUTO)
    @GeneratedValue
    /** 用户ID */
    private Long userId;

    /** 用户名 */
    @Excel(name = "用户名")
    private String userName;

    /** 手机号码 */
    @Excel(name = "手机号码")
    private String phone;

    /** 用户昵称 */
    @Excel(name = "用户昵称")
    private String nickName;

    /** 用户类型: 0普通用户 1 商家  2 骑手  3夜市  */
    @Excel(name = "用户类型")
    private String userType;

    /** 用户邮箱 */
    @Excel(name = "用户邮箱")
    private String email;

    /** 用户性别（0男 1女 2未知） */
    @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
    private String sex;

    /** 头像地址 */
    @Excel(name = "头像地址")
    private String avatar;

    /** 密码 */
    @Excel(name = "密码")
    private String password;

    /** 帐号状态（0正常 1停用） */
    @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
    private String status;

    /** 分管账号所属商家主账号ID */
    private Long merchantOwnerId;

    /** 主账号控制状态（0正常 1停用） */
    private String subaccountStatus;

    /** 最近一次商家端成功登录时间 */
    private Date lastLoginAt;

    /** 删除标志（0代表存在 1代表删除） */
    @Excel(name = "删除标志", readConverterExp = "0=代表存在,1=代表删除")
    private String delFlag;

    /** 会员标识 */
    @Excel(name = "会员标识")
    private transient String vip;

    /** 用户唯一标识 */
    @Excel(name = "用户唯一标识")
    private String cid;

    /** 设备类型（如 ios/android），区分设备类型 */
    private String cidType;

    /** 我的邀请码 */
    @Excel(name = "我的邀请码")
    private String mycode;

    /** 被邀请标识 */
    @Excel(name = "被邀请标识")
    private String thiscode;

    /** 抽成 */
    @Excel(name = "抽成")
    private Double commission;

    /** 附件 */
    @Excel(name = "附件")
    private String annex;

    /** 审核状态 */
    @Excel(name = "审核状态", readConverterExp = "0=待审核,1=审核通过,2=审核不通过")
    private String auditStatus;

    /** 审核不通过原因 */
    @Excel(name = "审核不通过原因")
    private String auditRejectReason;
    /** 司机审核状态 */
    @Excel(name = "司机审核状态", readConverterExp = "0=未审核,1=已审核")
    private String shijStatus;
    /** 联系电话 */
    @Excel(name = "联系电话")
    private String telPhone;
    /** 驾驶证 */
    @Excel(name = "驾驶证")
    private String driversLicense;
    /** 行驶证 */
    @Excel(name = "行驶证")
    private String drivingLicense;
    /** 车辆照片 */
    @Excel(name = "车辆照片")
    private String vehiclePhotos;
    /** 车牌 */
    @Excel(name = "车牌")
    private String licensePlate;
    /** 骑手车型（1机车 2轿车） */
    @Excel(name = "骑手车型")
    private String vehicleType;

    /** 骑手配送类型（FOOD美食外送、FLASH闪送，逗号分隔多选；空视为两者兼容） */
    @Excel(name = "配送类型")
    private String deliveryType;

    /** 骑手审核大头照（图片URL） */
    @Excel(name = "骑手审核大头照")
    private String riderHeadPhoto;

    /** 预上线城市（骑手申请时选择） */
    @Excel(name = "预上线城市")
    private String preLaunchCity;

    /** 出生日期（yyyy-MM-dd，骑手申请时填写，用于年满18岁校验） */
    @Excel(name = "出生日期")
    private String birthday;

    /** 强制险或电子保险卡（图片URL，多张逗号分隔） */
    @Excel(name = "强制险或电子保险卡")
    private String insurancePhoto;

    /** 良民证（图片URL，可后补） */
    @Excel(name = "良民证")
    private String policeCertificate;

    /** 负责人 */
    @Excel(name = "负责人")
    private String fullName;

    /** 身份证/护照号 */
    @Excel(name = "身份证/护照号")
    private String idNumber;

    /** 商户类型 */
    @Excel(name = "商户类型")
    private String merchantType;

    /** 银行信息 */
    @Excel(name = "银行信息")
    private String bankAccount;

    /** 身份证照片 */
    @Excel(name = "身份证照片")
    private String passportPhoto;

    /** 银行信息照片 */
    @Excel(name = "银行信息照片")
    private String bankPhoto;

    /** 银行账户户名（商家审核资料：收款账户的户名，如负责人姓名或公司户名） */
    @Excel(name = "银行账户户名")
    private String bankAccountName;

    /** 银行名称（商家审核资料：下拉选择，取字典 taiwan_bank_list 的银行中文名） */
    @Excel(name = "银行名称")
    private String bankName;

    /** 银行账号（商家审核资料：收款银行账号） */
    @Excel(name = "银行账号")
    private String bankAccountNo;

    /** 商家说明 */
    @Excel(name = "商家说明")
    private String merchantIntroduction;

    /** 營業登記證證明（图片URL，多张逗号分隔，如有） */
    @Excel(name = "營業登記證")
    private String businessLicense;

    /** 董監事資料查詢截圖（图片URL，多张逗号分隔） */
    @Excel(name = "董監事资料查询截图")
    private String directorsScreenshot;

    /** 食品業者登錄字號證明（图片URL，如有） */
    @Excel(name = "食品業者登錄字號證明")
    private String foodPermit;

    /** 實質受益人聲明書 UBO（图片URL，如有） */
    @Excel(name = "實質受益人聲明書")
    private String uboStatement;

    /** 创建时间 */
    @TableField(fill = FieldFill.INSERT)
    private Date createdAt;

    /** 积分钱包 */
    @TableField(exist = false)
    private Long pointsWallet;

    /** 骑手星数 */
    @TableField(exist = false)
    private Double star;

    /** 离线标识 :0 在线  1 离线*/
    private String offline;
    /** 关联摊位ID（摊位主使用） */
    private Long storeId;
    /** 夜市地址 */
    private String address;
    /** 夜市经度 */

    private BigDecimal longitude;

    /** 夜市纬度 */

    private BigDecimal latitude;

    /** 距离(km) */
    @TableField(exist = false)
    private Double juli;

    /** IM 平台 API 密钥（extCreate 返回） */
    @Excel(name = "IM apiKey")
    private String imApiKey;

    /** IM 平台用户ID（extCreate 返回，长整型）。序列化为字符串，规避前端 Long 精度丢失 */
    @Excel(name = "IM userId")
    @JsonSerialize(using = ToStringSerializer.class)
    private Long imUserId;

    /** 设备推送 token（普通推送）：Android FCM token / iOS APNs device token */
    private String deviceToken;

    /** iOS VoIP 推送 token（PushKit，用于语音/视频来电推送）。显式映射列 voip_token，避免 MyBatis-Plus 驼峰转下划线歧义 */
    @TableField("voip_token")
    private String voIPToken;

    /**
     * 补充用户信息(商家、骑手调整用户信息)
     */
    @TableField(exist = false)
    private Boolean updateUserInfo;


    public void setUserId(Long userId)
    {
        this.userId = userId;
    }

    public Long getUserId()
    {
        return userId;
    }

    public void setUserName(String userName) {this.userName = userName;}
    public String getUserName() { return userName; }

    public void setPhone(String phone)
    {
        this.phone = phone;
    }

    public String getPhone()
    {
        return phone;
    }
    public void setNickName(String nickName)
    {
        this.nickName = nickName;
    }

    public String getNickName()
    {
        return nickName;
    }
    public void setUserType(String userType)
    {
        this.userType = userType;
    }

    public String getUserType()
    {
        return userType;
    }
    public void setEmail(String email)
    {
        this.email = email;
    }

    public String getEmail()
    {
        return email;
    }
    public void setSex(String sex)
    {
        this.sex = sex;
    }

    public String getSex()
    {
        return sex;
    }
    public void setAvatar(String avatar)
    {
        this.avatar = avatar;
    }

    public String getAvatar()
    {
        return avatar;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }

    public String getPassword()
    {
        return password;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }

    public String getStatus()
    {
        return status;
    }

    public Long getMerchantOwnerId() {
        return merchantOwnerId;
    }

    public void setMerchantOwnerId(Long merchantOwnerId) {
        this.merchantOwnerId = merchantOwnerId;
    }

    public String getSubaccountStatus() {
        return subaccountStatus;
    }

    public void setSubaccountStatus(String subaccountStatus) {
        this.subaccountStatus = subaccountStatus;
    }

    public Date getLastLoginAt() {
        return lastLoginAt;
    }

    public void setLastLoginAt(Date lastLoginAt) {
        this.lastLoginAt = lastLoginAt;
    }
    public void setDelFlag(String delFlag)
    {
        this.delFlag = delFlag;
    }

    public String getDelFlag()
    {
        return delFlag;
    }
    public void setCid(String cid)
    {
        this.cid = cid;
    }

    public String getCid()
    {
        return cid;
    }
    public void setMycode(String mycode)
    {
        this.mycode = mycode;
    }

    public String getMycode()
    {
        return mycode;
    }
    public void setThiscode(String thiscode)
    {
        this.thiscode = thiscode;
    }

    public String getThiscode()
    {
        return thiscode;
    }

    public void setCommission(Double commission)
    {
        this.commission = commission;
    }

    public Double getCommission()
    {
        return commission;
    }

    public String getAnnex() {
        return annex;
    }

    public void setAnnex(String annex) {
        this.annex = annex;
    }

    public String getAuditStatus() {
        return auditStatus;
    }

    public void setAuditStatus(String auditStatus) {
        this.auditStatus = auditStatus;
    }

    public String getAuditRejectReason() {
        return auditRejectReason;
    }

    public void setAuditRejectReason(String auditRejectReason) {
        this.auditRejectReason = auditRejectReason;
    }

    public String getTelPhone() {
        return telPhone;
    }

    public void setTelPhone(String telPhone) {
        this.telPhone = telPhone;
    }

    public String getShijStatus() {
        return shijStatus;
    }

    public void setShijStatus(String shijStatus) {
        this.shijStatus = shijStatus;
    }

    public String getDriversLicense() {
        return driversLicense;
    }

    public void setDriversLicense(String driversLicense) {
        this.driversLicense = driversLicense;
    }

    public String getDrivingLicense() {
        return drivingLicense;
    }

    public void setDrivingLicense(String drivingLicense) {
        this.drivingLicense = drivingLicense;
    }

    public String getVehiclePhotos() {
        return vehiclePhotos;
    }

    public void setVehiclePhotos(String vehiclePhotos) {
        this.vehiclePhotos = vehiclePhotos;
    }

    public String getLicensePlate() {
        return licensePlate;
    }

    public void setLicensePlate(String licensePlate) {
        this.licensePlate = licensePlate;
    }

    public String getVehicleType() {
        return vehicleType;
    }

    public void setVehicleType(String vehicleType) {
        this.vehicleType = vehicleType;
    }

    public String getDeliveryType() {
        return deliveryType;
    }

    public void setDeliveryType(String deliveryType) {
        this.deliveryType = deliveryType;
    }

    /**
     * 骑手是否承接指定配送类型。
     * 配送类型为空的历史骑手视为同时兼容美食外送与闪送，保持既有派单行为不变。
     */
    public boolean supportsDeliveryType(String type) {
        if (deliveryType == null || deliveryType.isBlank()) {
            return true;
        }
        for (String value : deliveryType.split(",")) {
            if (type.equalsIgnoreCase(value.trim())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 归一化客户端提交的配送类型：大写、去空白、去重并按固定顺序输出。
     * 为空返回 null；包含无法识别的值时抛出 IllegalArgumentException。
     */
    public static String normalizeDeliveryTypes(String value) {
        if (value == null || value.isBlank()) {
            return null;
        }
        Set<String> types = new LinkedHashSet<>();
        for (String token : value.split(",")) {
            String type = token.trim().toUpperCase(Locale.ROOT);
            if (!"FOOD".equals(type) && !"FLASH".equals(type)) {
                throw new IllegalArgumentException("invalid delivery type: " + token);
            }
            types.add(type);
        }
        if (types.isEmpty()) {
            return null;
        }
        return String.join(",", types);
    }

    public String getRiderHeadPhoto() {
        return riderHeadPhoto;
    }

    public void setRiderHeadPhoto(String riderHeadPhoto) {
        this.riderHeadPhoto = riderHeadPhoto;
    }

    public String getPreLaunchCity() {
        return preLaunchCity;
    }

    public void setPreLaunchCity(String preLaunchCity) {
        this.preLaunchCity = preLaunchCity;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public String getInsurancePhoto() {
        return insurancePhoto;
    }

    public void setInsurancePhoto(String insurancePhoto) {
        this.insurancePhoto = insurancePhoto;
    }

    public String getPoliceCertificate() {
        return policeCertificate;
    }

    public void setPoliceCertificate(String policeCertificate) {
        this.policeCertificate = policeCertificate;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getIdNumber() {
        return idNumber;
    }

    public void setIdNumber(String idNumber) {
        this.idNumber = idNumber;
    }

    public String getMerchantType() {
        return merchantType;
    }

    public void setMerchantType(String merchantType) {
        this.merchantType = merchantType;
    }

    public String getBankAccount() {
        return bankAccount;
    }

    public void setBankAccount(String bankAccount) {
        this.bankAccount = bankAccount;
    }

    public String getPassportPhoto() {
        return passportPhoto;
    }

    public void setPassportPhoto(String passportPhoto) {
        this.passportPhoto = passportPhoto;
    }

    public String getBankPhoto() {
        return bankPhoto;
    }

    public void setBankPhoto(String bankPhoto) {
        this.bankPhoto = bankPhoto;
    }

    public String getMerchantIntroduction() {
        return merchantIntroduction;
    }

    public void setMerchantIntroduction(String merchantIntroduction) {
        this.merchantIntroduction = merchantIntroduction;
    }

    public String getBusinessLicense() {
        return businessLicense;
    }

    public void setBusinessLicense(String businessLicense) {
        this.businessLicense = businessLicense;
    }

    public String getDirectorsScreenshot() {
        return directorsScreenshot;
    }

    public void setDirectorsScreenshot(String directorsScreenshot) {
        this.directorsScreenshot = directorsScreenshot;
    }

    public String getFoodPermit() {
        return foodPermit;
    }

    public void setFoodPermit(String foodPermit) {
        this.foodPermit = foodPermit;
    }

    public String getUboStatement() {
        return uboStatement;
    }

    public void setUboStatement(String uboStatement) {
        this.uboStatement = uboStatement;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("userId", getUserId())
            .append("userName", getUserName())
            .append("phone", getPhone())
            .append("nickName", getNickName())
            .append("userType", getUserType())
            .append("email", getEmail())
            .append("sex", getSex())
            .append("avatar", getAvatar())
            .append("password", getPassword())
            .append("status", getStatus())
            .append("merchantOwnerId", getMerchantOwnerId())
            .append("subaccountStatus", getSubaccountStatus())
            .append("lastLoginAt", getLastLoginAt())
            .append("delFlag", getDelFlag())
            .append("cid", getCid())
            .append("mycode", getMycode())
            .append("mycode", getMycode())
            .append("thiscode", getThiscode())
            .append("commission", getCommission())
            .append("annex", getAnnex())
            .append("auditStatus", getAuditStatus())
            .append("auditRejectReason", getAuditRejectReason())
            .append("telPhone", getTelPhone())
            .append("shijStatus", getShijStatus())
            .append("driversLicense", getDriversLicense())
            .append("drivingLicense", getDrivingLicense())
            .append("vehiclePhotos", getVehiclePhotos())
            .append("licensePlate", getLicensePlate())
            .append("fullName", getFullName())
            .append("idNumber", getIdNumber())
            .append("merchantType", getMerchantType())
            .append("bankAccount", getBankAccount())
            .append("passportPhoto", getPassportPhoto())
            .append("bankPhoto", getBankPhoto())
            .append("merchantIntroduction", getMerchantIntroduction())
            .toString();
    }
}
