package cn.reghao.bnt.web.devops.app.model.po.config;

import cn.reghao.bnt.web.devops.app.model.constant.AppType;
import cn.reghao.bnt.web.devops.app.model.dto.AppConfigDto;
import cn.reghao.bnt.web.devops.app.model.dto.AppConfigUpdateDto;
import cn.reghao.bnt.web.devops.build.model.po.CompilerConfig;
import cn.reghao.bnt.web.devops.build.model.po.PackerConfig;
import cn.reghao.bnt.web.devops.build.model.po.RepoAuthConfig;
import cn.reghao.bnt.web.devops.build.model.vo.BuildConfig;
import cn.reghao.bnt.web.devops.builder.model.AppDto;
import cn.reghao.bnt.web.devops.builder.model.BuildConfigDto;
import cn.reghao.bnt.web.util.BaseEntity;
import cn.reghao.jutil.jdk.web.validator.ValidEnum;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

/**
 * @author reghao
 * @date 2020-02-28 14:11:02
 */
@NoArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "devops_app_config")
public class AppConfig extends BaseEntity implements Cloneable {
    @Column(nullable = false, unique = true)
    @NotBlank(message = "应用 ID 不能为空字符串")
    @Length(min = 4, max = 32, message = "应用 ID 仅可包含数字, 小写字母和短横线(-)等字符, 长度为 4 ～ 32 个字符")
    private String appId;
    @NotBlank(message = "应用名字不能为空白字符串")
    private String appName;
    @NotNull
    @ValidEnum(value = AppType.class, message = "请选择正确的应用类型")
    private String appType;
    @NotBlank(message = "环境不能为空白字符串")
    private String env;
    @NotNull
    @NotBlank(message = "应用仓库不能为空白字符串")
    private String appRepo;
    @NotNull
    @NotBlank(message = "仓库分支不能为空白字符串")
    private String repoBranch;

    /* 构建配置 */
    private String projDirname;
    @NotNull
    @NotBlank(message = "应用根目录不能为空白字符串")
    private String appRootPath;
    private String bindPorts;
    private String healthCheck;
    private String domains;

    // buildConfig
    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "repo_auth_config_id")
    @NotNull
    private RepoAuthConfig repoAuthConfig;
    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "compiler_config_id")
    @NotNull
    private CompilerConfig compilerConfig;
    @ManyToOne(cascade = CascadeType.REFRESH)
    @JoinColumn(name = "packer_config_id")
    @NotNull
    private PackerConfig packerConfig;
    // TODO packType 是 docker 时使用
    @Lob
    @Column(columnDefinition="text")
    private String dockerfile;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public AppConfig(AppConfigDto appConfigDto, String projDirname, BuildConfig buildConfig) {
        this.appId = appConfigDto.getAppId();
        this.appName = appConfigDto.getAppName();
        this.appType = appConfigDto.getAppType();
        this.env = appConfigDto.getEnv();
        this.appRepo = appConfigDto.getAppRepo();
        this.repoBranch = appConfigDto.getRepoBranch();

        this.projDirname = projDirname;
        this.appRootPath = appConfigDto.getAppRootPath();
        this.bindPorts = appConfigDto.getBindPorts();
        this.healthCheck = "";

        this.repoAuthConfig = buildConfig.getRepoAuth();
        this.compilerConfig = buildConfig.getCompiler();
        this.packerConfig = buildConfig.getPacker();
        this.dockerfile = appConfigDto.getDockerfile();
    }

    public AppConfig update(AppConfigUpdateDto appConfigUpdateDto, BuildConfig buildConfig) {
        this.appName = appConfigUpdateDto.getAppName();
        this.repoBranch = appConfigUpdateDto.getRepoBranch();

        this.repoAuthConfig = buildConfig.getRepoAuth();
        this.compilerConfig = buildConfig.getCompiler();
        this.packerConfig = buildConfig.getPacker();
        this.dockerfile = appConfigUpdateDto.getDockerfile();
        return this;
    }

    public AppDto getAppDto() {
        BuildConfigDto buildConfigDto = new BuildConfigDto(this.repoAuthConfig.getRepoAuth(),
                this.compilerConfig.getCompilerDto(), this.packerConfig.getPackerDto(), this.packerConfig.getDockerAuth());

        return new AppDto(this.appId, this.env, this.appType, this.appRepo, this.repoBranch, this.projDirname,
                this.appRootPath, this.dockerfile, buildConfigDto);
    }
}
