public with sharing class InventoryLostReportController {
    public Inventory_Header__c lh { get; set; }
    // 明细行项目
    public List<LineInfo> lineInfoList { get; set; }
    //备品申请书ID
    public String lhId { get; private set; }
    public Boolean hasError { get; private set; }
    //现有备品数量（基于备品一览数量）
    public Integer EquipmentSetCnt{get;set;}
    public String lrId { get; private set; }
    public String sortKey { get; set; }
    public String preSortKey { get; set; }
    public Boolean sortOrderAsc { get; set; }
    public String[] sortOrder { get; set; }                 // TODO sortOrderLeft と sortOrderRight
    public String[] columus { get; private set; }
    public List<List<String>> columnsApi { get; private set; }         // 参照項目用 
    public Set<String> columusSet = new Set<String>();
    public List<String> titleList { get; set; }
    public String alertInfo { get; set; }
    public Boolean canSave { get; set; }
    private static Set<String> mustFieldSet = new Set<String> {'LostReport_Detail__c',
                                                               'Inventory_Header__c',
                                                               'Auto_Lost_item_giveup__c',
                                                               'LostReport_Detail__r.LostReport__r.Name',
                                                               'LostReport_Detail__r.LostReport__r.Status__c',
                                                               'LostReport_Detail__r.LostReport__r.Id',
                                                               'LostReport_Detail__r.Id'};
    public InventoryLostReportController() {
        lhId = ApexPages.currentPage().getParameters().get('lhid');
        canSave = true;
    }
    // 画面初始化
    public void init() {
        hasError = false;
        lh = new Inventory_Header__c();
        alertInfo = ApexPages.currentPage().getParameters().get('alertInfo');
        if (!String.isBlank(alertInfo)) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, alertInfo));
        }
        try {
            if (lhId != null && lhId.length() > 0) {
                // 备品借出申请取得
                List<Inventory_Header__c> raList = [
                                                    SELECT Id,
                                                           Name
                                                      FROM Inventory_Header__c
                                                     WHERE Id = :lhId];
                if (raList.size() > 0) {
                    lh = raList[0];
                } else {
                    throw new ControllerUtil.myException('盘点报告不存在 请确认');
                }
            } else {
                throw new ControllerUtil.myException('盘点报告不存在 请确认');
            }
            String whereStr = ' AND Internal_Asset_Flg__c = true ' +
                              ' AND Inventory_Deviation__c < 0 ' +
                              ' AND (Inventory_Time__c != null)' +
                              ' ORDER BY LostReport_Detail__c NULLS FIRST';
            setColumus();
            this.sortOrderAsc = true;
            this.sortOrder = new String[columus.size()];
            for (Integer i = 0; i < columus.size(); i++) {
                this.sortOrder[i] = '　';
            }
            whereStr += ' limit 1000 ';
            List<Inventory_Detail__c> ldList = getRaesd(null, lh.Id, whereStr);
            if (ldList.size() == 0) {
                throw new ControllerUtil.myException('此盘点单中没有可以创建丢失报告的盘点明细');
            }else{
                EquipmentSetCnt = ldList.size();
                // 明细行做成
                reSetInfo(ldList);
            }
        }
        catch (Exception ex) {
            canSave = false;
            system.debug('=====' + ex.getMessage());
            hasError = true;
            ApexPages.addMessages(ex);
        }
    }
    private void setColumus() {
        // 获得订单一览
        Map<String, Schema.FieldSet> fsMap = Schema.getGlobalDescribe().get('Inventory_Detail__c').getDescribe().fieldSets.getMap();
        Schema.FieldSet fs = fsMap.get('Inventory_losses_Fields');
        List<FieldSetMember> fsmList = fs.getFields();
        columus = new List<String>();
        titleList = new List<String>();
        columnsApi = new List<List<String>>();
        for (FieldSetMember fsm : fsmList) {
            if (columusSet.contains(fsm.getFieldPath()) == false) {
                titleList.add(fsm.getLabel());
                columus.add(fsm.getFieldPath());
                columusSet.add(fsm.getFieldPath());
                columnsApi.add(fsm.getFieldPath().split('\\.'));
            }
        }
    }
    public void sortTable() {
            String whereStr = ' AND Internal_Asset_Flg__c = true ' +
                              ' AND Inventory_Deviation__c < 0 ' +
                              ' AND (Inventory_Time__c != null OR Inventory_Header__r.Inventory_Submit_Date__c != null)' +
                              ' AND (LostReport_Detail__c = null ' +
                                    ' OR LostReport_Detail__r.LostReport__r.Status__c = \'草案中\'' +
                                    ' OR LostReport_Detail__r.CancelLostReport__c = true)' +
                              ' ORDER BY ';
        String psortKey = ApexPages.currentPage().getParameters().get('psortKey');
        if(String.isNotBlank(psortKey)){
            this.sortKey = psortKey;
        }
        if (this.sortKey == this.preSortKey) {
            if (String.isBlank(this.sortKey) == false) {
                // 方向が変わるのみ
                this.sortOrderAsc = !this.sortOrderAsc;
                this.sortOrder[Integer.valueOf(this.sortKey)] = (this.sortOrderAsc == true ? '↑' : '↓');
            }
        } else {
            this.sortOrderAsc = true;
            if (String.isBlank(this.preSortKey) == false) {
                this.sortOrder[Integer.valueOf(this.preSortKey)] = '　';
            }
            this.sortOrder[Integer.valueOf(this.sortKey)] = (this.sortOrderAsc == true ? '↑' : '↓');
        }
        this.preSortKey = this.sortKey;
        whereStr += columus[Integer.valueOf(this.sortKey)] + ' ' + (sortOrderAsc == true ? 'ASC NULLS FIRST' : 'DESC NULLS LAST');
        whereStr += ' limit 1000 ';
        reSetInfo(getRaesd(null, lh.Id, whereStr));
    }
    // 保存按钮
    // https://sohobb.backlog.jp/view/OLY_OCM-152#comment-20041467
    // TODO OLY_OCM-206 select from 一対一Link, 把 分配数 清 0
    public PageReference saveBtn() {
        alertInfo = '';
        hasError = false;
        String lostReportName;
        // 保存
        Savepoint sp = Database.setSavepoint();
        try {
            Map<Id, Integer> needAddLRMap = new Map<Id, Integer>();
            Map<Id, Inventory_Detail__c> needCancelLRMap = new Map<Id, Inventory_Detail__c>();
            // Boolean isGiveUp = null;
            for (Integer i = 0; i < lineInfoList.size(); i ++) {
                LineInfo info = lineInfoList[i];
                if (info.oldSelect != info.isSelect) {
                    if (info.isSelect) {
                        // if (isGiveUp == null) {
                        //     isGiveUp = info.raesd.Lost_item_giveup__c;
                        // }
                        // else if (isGiveUp != info.raesd.Lost_item_giveup__c) {
                        //     throw new ControllerUtil.myException('请选择欠品明细或者放弃明细');
                        // }
                        needAddLRMap.put(info.ldObject.id, i + 1);
                    }
                    // 已经提交过遗失申请，草案中，不批准，取消提交状态的话删除遗失申请明细
                    else {
                        // if (info.ldObject.LostReport_Detail__r.LostReport__r.Status__c == '草案中') {
                            needCancelLRMap.put(info.ldObject.Id, info.ldObject);
                        // }
                    }
                }
            }
            if (needAddLRMap.isEmpty() && needCancelLRMap.isEmpty()) {
                throw new ControllerUtil.myException('没有需要提交或者取消的遗失报告的明细');
            }
            LostReport__c lr;
            List<LostReport_Detail__c> upsertLR = new List<LostReport_Detail__c>();
            List<Inventory_Detail__c> ldList = new List<Inventory_Detail__c>();
            Map<Id, LostReport_Detail__c> needAddLrdMap = new Map<Id, LostReport_Detail__c>();
            if (needAddLRMap.isEmpty() == false) {
                 ldList = getRaesd(needAddLRMap.keySet(), null, ' FOR UPDATE');
                if (ldList.size() <= 0) {
                    throw new ControllerUtil.myException('需要提交遗失的明细不存在，请刷新画面重试');
                }
                else {
                    for (Inventory_Detail__c ld : ldList) {
                        if (ld.Inventory_Deviation__c >= 0
                            || ld.LostReport_Detail__c != null) {
                            throw new ControllerUtil.myException(needAddLRMap.get(ld.id) + '行明细:' + '需要提交遗失报告的明细已经更新，请刷新画面重试');
                        }
                    }
                }
                List<LostReport__c> lrList = [SELECT Id, Name
                                            FROM LostReport__c
                                           WHERE Inventory_Header__c = :ldList[0].Inventory_Header__c
                                             AND Status__c = '草案中'
                                             ];
                if (lrList.size() > 0) {
                    lr = lrList[0];
                    lostReportName = lr.Name;
                }
                else {
                    lr = new LostReport__c();
                    lr.Inventory_Header__c = ldList[0].Inventory_Header__c;
                    FixtureUtil.withoutInsert(new LostReport__c[]{lr});
                    lostReportName = [SELECT Id, Name FROM LostReport__c WHERE Id = :lr.Id].Name;
                }
                for (Inventory_Detail__c ld : ldList) {
                    LostReport_Detail__c lrd = new LostReport_Detail__c();
                    lrd.LostReport__c = lr.Id;
                    lrd.Inventory_Detail__c = ld.Id;
                    lrd.Asset__c = ld.Asset__c;
                    lrd.Quantity__c = 1;
                    needAddLrdMap.put(ld.Id, lrd);
                }
                upsertLR = needAddLrdMap.values();
            }
            List<LostReport_Detail__c> deleteLR = new List<LostReport_Detail__c>();
            if (needCancelLRMap.isEmpty() == false) {
                for (Id deleLRId : needCancelLRMap.keySet()) {
                    if (lr == null) {
                        lr = needCancelLRMap.get(deleLRId).LostReport_Detail__r.LostReport__r;
                        lostReportName = lr.Name;
                    }
                    upsertLR.add(new LostReport_Detail__c(Id = needCancelLRMap.get(deleLRId).LostReport_Detail__c,
                                                          CancelLostReport__c = true,
                                                          DeleteLostReport_Detail_Reason__c = needCancelLRMap.get(deleLRId).DeleteLostReport_Detail_Reason__c));
                    Inventory_Detail__c ld = new Inventory_Detail__c(Id = deleLRId);
                    ld.LostReport_Detail__c = null;
                    ldList.add(ld);
                }
            }
            // 追加更新的遗失报告申请明细
            FixtureUtil.withoutUpsertObjects(upsertLR);
            for (Inventory_Detail__c raesd : ldList) {
                if (needCancelLRMap.containsKey(raesd.Id) == false) {
                    raesd.LostReport_Detail__c = needAddLrdMap.get(raesd.Id).Id;
                }
            }
            // 更新借出申请明细关联遗失报告明细的字段
            FixtureUtil.withoutUpdate(ldList);
            // reSetInfo(ldList);
            if (lr != null) {
                lrId = lr.Id;
            }
            // 创建好遗失报告后提醒已经创建遗失报告，并显示遗失报告编号

            alertInfo = '已经保存遗失报告, 遗失报告编号: ' + lostReportName;
        } catch (Exception ex)    {
            system.debug('=====' + ex.getStackTraceString());
            hasError = true;
            ApexPages.addMessages(ex);
            Database.rollback(sp);
            return null;
        }
        // ApexPages.currentPage().getParameters().put('lostRaesdId', null);
        return null;
    }
    private List<Inventory_Detail__c> getRaesd(Set<Id> idSet, String ihId, String elseWhere) {
        String strColumus = String.join(columus, ',');
        for (String mustField : mustFieldSet) {
            if (columusSet.contains(mustField) == false) {
                strColumus += ', ' + mustField;
            }
        }
        String soqlStr = 'SELECT Id,' + strColumus +
                         ' FROM Inventory_Detail__c ' +
                         ' WHERE Id != null ';
        if (idSet != null) {
            soqlStr += ' AND Id = :idSet ';
        }
        if (String.isNotBlank(ihId)) {
            soqlStr += ' AND Inventory_Header__c = :ihId ';
        }
        if (String.isNotBlank(elseWhere)) {
            soqlStr += elseWhere;
        }
        System.debug(soqlStr);
        return Database.query(soqlStr);
    }
    private void reSetInfo(List<Inventory_Detail__c> ldList) {
        lineInfoList = new List<LineInfo>();
        for (Inventory_Detail__c raesd : ldList) {
            LineInfo lineInfo = new LineInfo(raesd);
            lineInfoList.add(lineInfo);
        }
    }
    @TestVisible
    class LineInfo {
        // 选择
        public boolean isSelect { get; set; }
        public boolean oldSelect { get; set; }
        public boolean checkboxDis { get; set; }
        public Inventory_Detail__c ldObject { get; set; }
        public LineInfo(Inventory_Detail__c r) {
            ldObject = r;
            this.isSelect = r.LostReport_Detail__c != null;
            this.oldSelect = this.isSelect;
            checkboxDis = this.isSelect == true && r.Auto_Lost_item_giveup__c;
        }
    }
}