package org.example.Entity.Control.Container;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.example.Entity.Control.Fields.ComboBox;
import org.example.Entity.Control.Fields.Field;
import org.example.Entity.Control.Validators.VBase;
import org.example.Entity.System.ModuleEntity;
import org.example.Enums.SystemEnums;
import org.example.Utils.DataTableUtil;
import org.example.Utils.IPublicUtil;
import org.example.Utils.NativeExtensionUtils;
import org.example.Utils.PublicUtil;

import java.util.Arrays;
import java.util.Map;
import java.util.Objects;

import static org.example.Utils.NativeExtensionUtils.*;

// 假设 Field 类是 RowColumn 的父类
public class RowColumn extends Field {

    public RowColumn(Map<String, Object> _row, boolean selfEdit) {
        super(_row);
        this.selfEdit = selfEdit;
    }

    public RowColumn(Map<String, Object> _row, boolean selfEdit, IPublicUtil util) {
        super(_row, util);
        this.selfEdit = selfEdit;
    }

    private String _xtype;

    @Override
    public String getXtype() {
        if (_xtype == null || _xtype.isEmpty()) {
            _xtype = PublicUtil.GetEColumnTypeByCType(getFdType());

            if (getEditor() != null && !isValeqkey()) {
                _xtype = "editor.editColumn";
                if (getDataSource() == null || getDataSource().isEmpty()) {
                    _xtype = "gridcolumn";
                }
            } else if (!isEditable() && getUneditor() != null) {
                _xtype = "editor.comboboxColumn";
                if (getDataSource() == null || getDataSource().isEmpty()) {
                    _xtype = "gridcolumn";
                }
            } else if ("gridcolumn".equals(_xtype) && getFieldDbType() > 0) {
                _xtype = PublicUtil.TypeToColumnType(PublicUtil.SqlxtypeToProType(getFieldDbType()));

            }

            if (getEditor() != null && isValeqkey()) {
                setFormat("");
            }
        }
        return _xtype;
    }

    @Override
    public void setXtype(String xtype) {
        this._xtype = xtype;
    }


    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("Linknames")
    public String[] linknames;


    private Boolean _locked;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("Locked")
    public Boolean getLocked() {
        if (_locked == null) {
            _locked = DataTableUtil.getBooleanValue(_row, "locked", false);
        }
        return _locked ? _locked : null;
    }

    public void setLocked(Boolean locked) {
        this._locked = locked;
    }

    private Boolean _scanAble;

    @JsonIgnore
    public Boolean getScanAble() {
        if (_scanAble == null) {
            _scanAble = DataTableUtil.getBooleanValue(_row, "scanAble", false);
        }
        return _scanAble ? _scanAble : null;
    }

    public void setScanAble(Boolean scanAble) {
        this._scanAble = scanAble;
    }

    private Object _scanField;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("ScanField")
    public Object getScanField() {
        if (getScanAble() != null && getScanAble()) {
            _scanField = getUtil().createControl(_row, module, false);
        }
        return _scanField;
    }

    @JsonIgnore
    public ModuleEntity module;


    public Integer width;

    @Override
    public Integer getWidth() {
        return ToInt32(DataTableUtil.getIntValue(_row, "width", 100));
    }

    public Integer height;

    @Override
    public Integer getHeight() {
        return null;
    }


    @Override
    public Boolean getHidden() {
        return super.getColHidden();
    }


    public Boolean getAutoRowspan() {
        Boolean _r = DataTableUtil.getBooleanValue(_row, "rowspan", false);
        return _r ? _r : null;
    }

    public int ControlTabIndex;

    private SystemEnums.ControlType _FieldType;

    @JsonIgnore
    public SystemEnums.ControlType getFdType() {
        if (_FieldType == null) {
            try {
                Object obj = Enum.valueOf(SystemEnums.ControlType.class, String.valueOf(getFieldType()));
                if (obj != null) {
                    _FieldType = (SystemEnums.ControlType) obj;
                }
            } catch (IllegalArgumentException e) {
                _FieldType = SystemEnums.ControlType.LabText;
            }
        }

        if (PublicUtil.SqlxtypeToProType(getFieldDbType()) == Boolean.class) {
            _FieldType = SystemEnums.ControlType.LabCheckBox;
        } else if (isIsSum() && (getFormat() == null || getFormat().toLowerCase().indexOf("yy") < 0)) {
            _FieldType = SystemEnums.ControlType.LabTextInt;
        }

        return _FieldType != null ? _FieldType : SystemEnums.ControlType.LabText;
    }

    @JsonIgnore
    public int getFieldDbType() {
        String val = DataTableUtil.getStringValue(_row, new String[]{"FieldDbType"}, "");
        return ToInt32(val);
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("DataType")
    public String getDataType() {
        String datatype = DataTableUtil.getStringValue(_row, new String[]{"datatype"}, "");
        switch (datatype.toLowerCase()) {
            case "varchar":
                return "textfield";
            case "datetime":
                return "datefield";
            default:
                return "";
        }
    }


    public Boolean getDisabled() {
        return null;
    }

    @JsonIgnore
    public String getFieldName() {
        return ((String) DataTableUtil.getRowVal(_row, new String[]{"fieldname"}, "")).toLowerCase();
    }

    public String getDataIndex() {
        return getFieldName();
    }


    @JsonIgnore
    @Override
    public Integer getLeft() {
        return super.getLeft();
    }

    @JsonIgnore
    @Override
    public void setLeft(Integer left) {
        super.setLeft(left);
    }


    @JsonIgnore
    @Override
    public Integer getTop() {
        return super.getTop();
    }

    @JsonIgnore
    @Override
    public void setTop(Integer top) {
        super.setTop(top);
    }


    public String getText() {
        String label = getFieldLabel();
        return (label == null || label.isEmpty()) ? getDataIndex() : label;
    }


    public Integer getTextAlign() {
        int textAlign = ToInt32(DataTableUtil.get(_row, "TextAlign", getFieldLabel(), 0));
        return textAlign != 0 ? textAlign : null;
    }

    private String _fieldLabel;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("FieldLabel")
    public String getFieldLabel() {
        String label = (String) DataTableUtil.get(_row, "FieldCaption", _fieldLabel, "");
        if (label != null && !label.isEmpty()) {
            label = label.replace("\r\n", "");
            if (label.indexOf("|") > -1) {
                String[] ls = label.split("\\|");
                return ls[1];
            }
        }
        return label;
    }

    public void setFieldLabel(String fieldLabel) {
        this._fieldLabel = fieldLabel;
    }

    private Boolean selfEdit;

    private Boolean _editable;

    public boolean isEditable() {
        if (_editable != null) {
            return _editable;
        }
        _editable = !super.isReadOnly() && selfEdit;
        return _editable;
    }

    public void setEditable(boolean editable) {
        this._editable = editable;
        if (getEditor() != null && getEditor() instanceof Field) {
            ((Field) getEditor()).setReadOnly(false);
        }
    }

    private Object _uneditor;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    public Object getUneditor() {
        if (_uneditor == null) {
            Object _tmp = getEditor();
        }
        return _uneditor;
    }

    public void setUneditor(Object uneditor) {
        this._uneditor = uneditor;
    }

    private Object _editor;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    public Object getEditor() {
        Boolean resultdisabled = getDisabled() != null ? getDisabled() : false;

        if (getFdType() != SystemEnums.ControlType.LabCheckBox && _editor == null && !resultdisabled) {
            boolean[] valeqkeyHolder = new boolean[1];
            _editor = getUtil().getGridColumnEditType(this, _row, module, valeqkeyHolder);
            this._valekey = valeqkeyHolder[0];
            if (!valeqkeyHolder[0] && _editor != null && _editor instanceof ComboBox) {
                _uneditor = _editor;
            }
        }

        if (!isEditable()) {
            return null;
        }

        _uneditor = null;
        return _editor;
    }

    public String tdCls;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("TdCls")
    public String getTdCls() {
        return isEditable() ? "editable" : null;
    }

    private Boolean _valekey = null;

    public Boolean isValeqkey() {
        if (_valekey == null && getEditor() == null) {
            _valekey = true;
        }
        return (_valekey != null) ? _valekey : true;
    }

    public void setValeqkey(Boolean valeqkey) {
        this._valekey = valeqkey;
    }


    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("TagId")
    public Integer getTagId() {
        int _tagId = DataTableUtil.getIntValue(_row, "tagid", 0);
        return _tagId > 0 ? _tagId : null;
    }

    private Object _fDefaultVal;

    @JsonProperty("fDefaultVal")
    public Object getFDefaultVal() {
        if (_fDefaultVal == null) {
            _fDefaultVal = DataTableUtil.getRowVal(_row, "defaultValue", null);
            if (_fDefaultVal != null && _fDefaultVal.toString().startsWith("@")) {
                _fDefaultVal = "";
            }
        }
        return _fDefaultVal;
    }


    @JsonProperty("StoreFieldType")
    public String getStoreFieldType() {
        return PublicUtil.GetEFieldTypeByCType(getFdType(), getFormat());
    }


    @JsonIgnore
    public Object getStoreField() {
        Object DefaultValue = getDefaultval();
        if (DefaultValue == null || DefaultValue.toString().isEmpty()) {
            DefaultValue = PublicUtil.GetDefaultValByCType(getFdType());
        }

        Object Validators = null;
        if (!isAllowBlank()) {
            Validators = new VBase[]{new VBase("Presence")};
        }

        Object finalDefaultValue = DefaultValue;
        Object finalValidators = Validators;
        return new Object() {
            public final String text = getText();
            public final String name = getDataIndex();
            public final String type = getStoreFieldType();
            public final Object defaultValue = finalDefaultValue;
            public final String dateFormat = getFormat();
            public final Object validators = finalValidators;
        };
    }


    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("BandTitle")
    public String getBandTitle() {
        String label = DataTableUtil.getStringValue(_row, "FieldCaption", _fieldLabel);
        if (label != null && !label.isEmpty() && label.indexOf("|") > -1) {
            String[] ls = label.split("\\|");
            return ls[0];
        }
        return DataTableUtil.getStringValue(_row, "bandtitle", "");
    }


    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("BandFields")
    public String[] getBandFields() {
        if (!isNullOrEmpty(getBandTitle())) {
            if (isNullOrEmpty(DataTableUtil.getStringValue(_row, "bandtitle", ""))) {
                return new String[]{getDataIndex()};
            }
            String fields = (String) DataTableUtil.getStringValue(_row, "bandfield", null);
            if (!isNullOrEmpty(fields)) {
                String[] result = Arrays.stream(fields.toLowerCase().split("[|,]"))
                        .filter(str -> str != null && !str.trim().isEmpty())
                        .toArray(String[]::new);
                return result;
            }
            return null;
        }
        return null;
    }
}