/**
 * 备品配套の設定
 */
public with sharing class FixtureSetManageController extends CreateRelationListPagingCtrlBase {
    public override Integer getSearchNumMax() {
        //各ページに制御あれば、最大件数を指定する
        // searchNumMax = Integer.valueOf(Label.Product_Select_Limit);
        // searchNumMax = 100;
        pagesize = '100';
        return searchNumMax;
    }

    /* 選択されたデータ取得用Soql　Fromから*/
    public override String getSelectedDataSql() {
        // オブジェクトAPI名
        selectedDataSql = ' From Fixture_Set_Detail__c';
        selectedDataSql += ' where Fixture_Set__c = \'' + String.escapeSingleQuotes(parentId) + '\'';
        selectedDataSql += ' order by SortInt__c ASC nulls last';
        return selectedDataSql;
    }

    // 検索元対象オブジェクトAPI名
    public override String getOriginObjName() {
        // オブジェクトAPI名
        originObjName = 'Product2';
        return originObjName;
    }
    // 検索元対象項目セット
    public override String getOriginObjColumns() {
        // 項目セット
        originObjColumns =  'Id';
        return originObjColumns;
    }

    public override String getObjName() {
        // オブジェクトAPI名
        objName = 'Fixture_Set_Detail__c';
        return objName;
    }
    public override String getColumnLeftFieldSetName() {
        // 左の項目セット
        columnLeftFieldSetName = '';
        return columnLeftFieldSetName;
    }
    public override String getColumnRightFieldSetName() {
        // 右の項目セット
        columnRightFieldSetName = 'DetailEdit_RightFieldSet';
        return columnRightFieldSetName;
    }
    // Select 里加直接加的項目 List
    public override List<String> getColumnFieldList() {
        // strColumus 里加 field
        return new List<String>{'Id', 'Product2__r.Name', 'Fixture_Set__c', 'Product_Status_Flag__c'};
    }
    // getObjName 连 getOriginObjName 的 FK
    public override String getFKColumnField() {
        return 'Product2__c';
    }

    public override String getRecordTypeId() {
        //ページレイアウトを収得するのレコードタイプ
        recordTypeId = '';
        return recordTypeId;
    }

    // ページコントローラに検索処理は、WhereSoql作成のみ、パラメータとして、コンポーネントに渡される
    public override String getSqlWhereStr() {
        sqlWhereStr = '';

        if(getIsNeedRunSearch()){
            sqlWhereStr = this.makeSoql(family, category2, category3, category4, category5, assetModelNo, multiStatus);
        }
        system.debug('=========getSqlWhereStr:'+sqlWhereStr);
        return sqlWhereStr;

    }

    public override Boolean getIsNeedRunSearch() {
        return true;
        //if (String.isBlank(family) && String.isBlank(category2)
        //        && String.isBlank(category3) && String.isBlank(category4)
        //            && String.isBlank(category5) && String.isBlank(assetModelNo)
        //                && String.isBlank(multiStatus)) {
        //    isNeedRunSearch = false;
        //}else{
        //    isNeedRunSearch = true;
        //}
        //return isNeedRunSearch;
    }


    /*****************検索用******************/
    public String family { get; set; }
    public List<SelectOption> familyOpts { get; private set; }
    public String category2 { get; set; }
    public String category3 { get; set; }
    public String category4 { get; set; }
    public String category5 { get; set; }
    public String assetModelNo { get; set; }
    public String multiStatus { get; set; }
    public String saveType { get; set; }
    //VFで$ObjectType.Fixture_Set_Detail__c.updateableで権限を判断する場合，画面表示途中で
    //プロファイルの権限を変更したら保存時のエラーが表示されません
    public Boolean canSave {get; private set;}
    
    /*****************ソート時再検索条件（画面からの入力条件を無視するため）******************/
    private String nameForSort = null;
    private String cate1ForSort = null;
    private String cate2ForSort = null;
    private String cate3ForSort = null;
    private String cate4ForSort = null;
    private String cate5ForSort = null;
    private String statusForSort = null;
    public Fixture_Set__c parentObj { get; private set; }
    
    public FixtureSetManageController() {
        parentId = ApexPages.currentPage().getParameters().get('pt_recid');
        
        //备品配套下的所有明细
        if (!String.isBlank(this.parentId)) {
            List<Fixture_Set__c> parentObjs = [
                    select Id,Name
                      from Fixture_Set__c where Id = :parentId];
            if (parentObjs.size() > 0) {
                parentObj = parentObjs.get(0);
            }
        }
        Schema.DescribeFieldResult f = Product2.Family.getDescribe();
        List<Schema.PicklistEntry> pList = F.getPicklistValues();
        familyOpts = new List<SelectOption>();
        familyOpts.add(new SelectOption('','--无--'));
        for (Schema.PicklistEntry p : pList) {
            if (p.isActive() == true) {
                familyOpts.add(new SelectOption(p.getValue(), p.getLabel()));
            }
        }

        this.canSave = Fixture_Set_Detail__c.sObjectType.getDescribe().isUpdateable() && Fixture_Set_Detail__c.sObjectType.getDescribe().isCreateable();
    }
    
    public void init() {
        searchOppSetParam();
        getSqlWhereStr();
        //isNeedSearchFirst = true;
    }
    
    private void searchOppSetParam() {
        cate1ForSort = family;
        cate2ForSort = category2;
        cate3ForSort = category3;
        cate4ForSort = category4;
        cate5ForSort = category5;
        nameForSort = assetModelNo;
        statusForSort = multiStatus;
    }

    public PageReference searchOpp() {
        searchOppSetParam();

        if(!getIsNeedRunSearch()){
            return null;
        }
        // 選択済みの製品を取得
        myComponentController.getSelectedDataInfo();

        getSqlWhereStr();
        // コンポーネントにSoqlを発行して、ページングする
        myComponentController.searchAndPaging();
        return null;
    }

    public PageReference save() {

        if (!Fixture_Set_Detail__c.sObjectType.getDescribe().isUpdateable() || !Fixture_Set_Detail__c.sObjectType.getDescribe().isCreateable()) {
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR, '无法编辑备品配套明细'));
            return null;
        }

        List<Id> delIds = new List<String>();
        //20170906 upsert by UniqueKey__c
        List<Fixture_Set_Detail__c> mfUpsert = new List<Fixture_Set_Detail__c>();
        // MainFixture_Cnt使用的積み上げ是非同期的,为了解决入力规则(主体只能有一个)的问题,此时更新分两次进行
        Fixture_Set_Detail__c bodyMfUpsert = null;

        Savepoint sp = Database.setSavepoint();
        Set<String> clearUniqueKeySet = new Set<String>();
        try {
            viewList.sort();
            List<WrapperInfo> bodyWrap = new List<WrapperInfo>();
            List<WrapperInfo> optionWrap = new List<WrapperInfo>();
            for (WrapperInfo wprInfo : viewList) {
                if(!wprInfo.check) continue;
                if (((Fixture_Set_Detail__c) wprInfo.sobj).Is_Body__c) {
                    bodyWrap.add(wprInfo);
                } else {
                    optionWrap.add(wprInfo);
                }
            }
            // Is_Body を かならず先頭にする
            bodyWrap.addAll(optionWrap);
            Integer sortInt = 1;
            Boolean isNeedUpdateParent = false;
            for (WrapperInfo wprInfo : bodyWrap) {
                Fixture_Set_Detail__c robj = (Fixture_Set_Detail__c) wprInfo.sobj;
                if (robj.Is_Body__c) {
                    //选配 :主体の場合は、備品Set保存時に自動でFalseをセットする。
                    robj.Is_Optional__c = false;
                    robj.Is_OneToOne__c = false;
                    robj.SortInt__c     = 1;
                    robj.Name           = parentObj.Name + '-' + ('' + sortInt).leftPad(2, '0');
                    //主体备品配套明细型号
                    parentObj.Fixture_Set_Body_Model_No__c = robj.Fixture_Model_No_F__c;
                    isNeedUpdateParent = true;
                } else {
                    sortInt++;
                    robj.SortInt__c = sortInt;
                    robj.Name       = parentObj.Name + '-' + ('' + sortInt).leftPad(2, '0');
                }
            }

            for (WrapperInfo wprInfo : viewList) {
                Fixture_Set_Detail__c robj = (Fixture_Set_Detail__c) wprInfo.sobj;

                //20170906 upsert by UniqueKey__c
                // 画面上にチェックした
                if (wprInfo.check) {
                    String uniqueKeyStr = parentObj.id + ':' + robj.product2__c;
                    robj.UniqueKey__c = uniqueKeyStr;
                    if (robj.Is_Body__c) {
                        bodyMfUpsert = robj;
                    } else {
                        mfUpsert.add(robj);
                    }
                    if (String.isBlank(robj.Id)
                            && !String.isBlank(uniqueKeyStr)) {
                        // 新規の場合、ここ単純に Id にて判断
                        clearUniqueKeySet.add(uniqueKeyStr);
                    }
                }

                // 画面上にチェックなし、且つ以前がチェックされた製品
                if (!wprInfo.check && wprInfo.oldCheck && selectedIdSet.contains(robj.Id)) {
                    // 一覧から削除
                    if (!String.isBlank(robj.Id)) {
                        delIds.add(robj.Id);
                    }
                }
            }
            if(isNeedUpdateParent){
                update parentObj;
            }
            // 削除、権限ない可能性があるので、FixtureUtilに移動
            if (delIds.size() > 0) {
                FixtureUtil.delFixtureSetDetailByIds(parentObj, delIds);
            }
            List<Fixture_Set_Detail__c> allFSDList = new List<Fixture_Set_Detail__c>();
            // Upsert
            if (mfUpsert.size() > 0) { 
                //Test method error on upsert command
                //System.DmlException: Upsert failed. First exception on row 0 with id a2R0k0000000rogEAA; 
                //first error: INVALID_FIELD_FOR_INSERT_UPDATE, cannot specify Id in an insert call: [Id]
                allFSDList.addAll(mfUpsert);
            }
            if (bodyMfUpsert != null) {
                allFSDList.add(bodyMfUpsert);
            }
            if(allFSDList.size() > 0) {
                // 用batch逻辑更新【产品注册证状态】
                FixtureSetDetailDailyUpdateBatch.updateProductStatusFlag(allFSDList);
                upsert allFSDList UniqueKey__c;
            }

        } catch (Exception ex) {
            System.debug(ex.getStackTraceString());
            ApexPages.addMessages(ex);
            Database.rollback(sp);
            // Id をクリア
            for (Fixture_Set_Detail__c robj : mfUpsert) {
                if (clearUniqueKeySet.contains(robj.UniqueKey__c)) {
                    robj.Id = null;
                }
            }
            return null;
        }
        
        if (saveType == '1') {
            searchOpp();
            saveType = '';
            return null;
        } else if (saveType == '2') {
        // ソート時の変更ある
            myComponentController.getSelectedDataInfo();
            getSqlWhereStr();
            myComponentController.sortTable();
            saveType = '';
            return null;
        } else {
            return cancel();
        }
    }

    public PageReference cancel() {
        PageReference ret = null;
        if (!String.isBlank(this.parentId)) {
            ret = new PageReference('/' + this.parentId);
        }
        return ret;
    }
    
    private String makeSoql(String cate1, String cate2, String cate3, String cate4,
            String cate5, String assMode, String status) {
        // from product2
        String soql ='';
        soql += 'where IsActive = true';

        // Familyはプルダウン
        if (!String.isBlank(cate1)) {
            soql += ' and Family = \'' + String.escapeSingleQuotes(cate1.replaceAll('%', '\\%')) + '\'';
        }
        if (!String.isBlank(cate2)) {
            soql += ' and Category2__c like \'%' + String.escapeSingleQuotes(cate2.replaceAll('%', '\\%')) + '%\'';
        }
        if (!String.isBlank(cate3)) {
            soql += ' and Category3__c like \'%' + String.escapeSingleQuotes(cate3.replaceAll('%', '\\%')) + '%\'';
        }
        if (!String.isBlank(cate4)) {
            soql += ' and Category4__c like \'%' + String.escapeSingleQuotes(cate4.replaceAll('%', '\\%')) + '%\'';
        }
        if (!String.isBlank(cate5)) {
            soql += ' and Category5__c like \'%' + String.escapeSingleQuotes(cate5.replaceAll('%', '\\%')) + '%\'';
        }
        if (!String.isBlank(assMode)) {
            //soql += ' and Asset_Model_No__c like \'%' + String.escapeSingleQuotes(assMode) + '%\'';
            soql += ' and ( ';
            soql += ' Fixture_Model_No_F__c like \'%' + String.escapeSingleQuotes(assMode.replaceAll('%', '\\%')) + '%\'';
            soql += ' OR Name like \'%' + String.escapeSingleQuotes(assMode.replaceAll('%', '\\%')) + '%\'';
            soql += ' OR OT_CODE_no_link__c like \'%' + String.escapeSingleQuotes(assMode.replaceAll('%', '\\%')) + '%\'';
            soql += ' OR MDM_Model_No__c like \'%' + String.escapeSingleQuotes(assMode.replaceAll('%', '\\%')) + '%\'';
            soql += ' ) ';
            //产品名称(文本) Name_No_link__c → Name , OT CODE OT_CODE_no_link__c, MDM製品型番 MDM_Model_No__c
        }
        if (!String.isBlank(status)) {
            soql += ' and (';
            List<String> vals = status.split('_', -1);
            for (Integer i = 0; i < vals.size(); i++) {
                if (i == vals.size() - 1) {
                    soql += ' SFDA_Status__c = \'' + String.escapeSingleQuotes(vals[i]) + '\')';
                } else {
                    soql += ' SFDA_Status__c = \'' + String.escapeSingleQuotes(vals[i]) + '\' or';
                }
            }
        }

        system.debug(soql);
        return soql;
    }

    // List<Product2>
    public override void setViewList(List<SObject> queryList) {
        viewList = new List<WrapperInfo>();

        // 選択済みの明细
        if (selectedData.size() > 0) {
            for (Integer i = 0; i < selectedData.size(); i++) {
                /* not include the selected data num */
                // 501を超えた場合前500のみを出す  
                //if (i == getSearchNumMax()) continue;
                WrapperInfo w = new WrapperInfo(selectedData[i], myComponentController);
                w.lineNo = i;
                w.orderNo = i + 1;
                w.check = true;
                w.oldCheck = true;
                viewList.add(w);
            }
        }

        if (queryList.size() == 0) {
            return;
        }

        // queryList に 数式項目を取得
        Savepoint sp = Database.setSavepoint();

        // 数式項目値を取れるのために、一回Insertする
        List<Fixture_Set_Detail__c> tempList = new List<Fixture_Set_Detail__c>();
        for (Integer i = 0; i < queryList.size(); i++) {
            // 501を超えた場合前500のみを出す
            if (i == getSearchNumMax()) { break; }
            Fixture_Set_Detail__c mf = new Fixture_Set_Detail__c();
            mf.Fixture_Set__c        = parentId;
            mf.Product2__c           = queryList[i].Id;
            mf.Is_Body__c            = false;
            mf.Is_OneToOne__c        = false;
            mf.Quantity__c           = 1;
            mf.Is_Optional__c        = false;
            mf.DataMigration_Flag__c = true;
//            mf.recalculateFormulas();
            tempList.add(mf);
        }

        Database.SaveResult[] results = Database.insert(tempList, false);

        final String soqlStr = 'Select {0} {1} ';
        String whereStr = ' FROM Fixture_Set_Detail__c WHERE ID in: tempList';
        String soql = String.format(soqlStr, new String[] {myComponentController.strColumus, whereStr});

        tempList = Database.query(soql);
        if (queryList.size() != tempList.size()) {
            //error message 検索処理正しくありません、システム管理者に連絡してください。
           Database.SaveResult dmlResult = results[0];
            if (!dmlResult.isSuccess()) {
                System.debug(System.LoggingLevel.ERROR, '第[' + (1) + ']条 insert error:' + dmlResult);
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,
                '第[' + (1) + ']条 insert error:' + dmlResult));
                // 1件目だけlogに出す
            }
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,
                    System.Label.CreateRelationListSearchError));
            return;
        }
        // 強制ロールバック
        Database.rollback(sp);
        Map<String, SObject> fsDMap = new Map<String,SObject>();
        for(Fixture_Set_Detail__c fsd : tempList){
            Fixture_Set_Detail__c robj = fsd.clone(false);
            robj.DataMigration_Flag__c = false;
            fsDMap.put(fsd.Product2__c, robj);
        }

        Integer addedNum = 0;
        for (Integer i = 0; i < queryList.size(); i++) {

            addedNum ++;
            // 501を超えた場合前500のみを出す
            if (addedNum == getSearchNumMax()) { break; }
            SObject mf = fsDMap.get(queryList[i].Id);
            viewList.add(new WrapperInfo(mf, myComponentController));
            viewList[viewList.size() - 1].lineNo = viewList.size() - 1;
        }

system.debug('●●●●● setViewList END ' );
    }
}