public with sharing class TransferAgencyShipmentController {
    public List<EsdInfo> esdList { get; set; }
    public String apply_no { get; private set; }
    public Boolean done_flg { get; set; }
    private String taId;
    public Boolean readOnly { get;  set; }
    public FixtureDeliverySlip__c slip { get; set; }
    public List<LabelValue> outputFieldList {get; set;}

    public TransferAgencyShipmentController() {
        taId = ApexPages.currentPage().getParameters().get('id');
        outputFieldList = setFieldSet('TransferApplyDetail__c', 'TransferAgencyShipment');
    }
    public PageReference init() {
        esdList = new List<EsdInfo>();
        done_flg = false;
        String jsonStr;

        if (taId != null) {
            readOnly = false;
            List<TransferApplyDetail__c> eList = getDetails();

            if (eList.size() > 0) {
                for (TransferApplyDetail__c tad : eList) {
                    if(tad.TransferApply__r.Shipment_Slip_tmp__c != null && jsonStr == null) {
                        jsonStr = tad.TransferApply__r.Shipment_Slip_tmp__c;
                    }
                    if(String.isBlank(apply_no)) {
                        apply_no = tad.TransferApply__r.Name;
                    }
                    if (tad.TransferApply__r.Yi_loaner_arranged__c > 0) {
                        readOnly = true;
                    }
                    EsdInfo ei = new EsdInfo(tad);
                    esdList.add(ei);
                }
            }
            else {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '没有调拨明细！'));
                return null;
            }
        }
        if (jsonStr != null) {
            try {
                slip = (FixtureDeliverySlip__c)JSON.deserialize(jsonStr, FixtureDeliverySlip__c.class);
            } catch (Exception ex) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage()));
                slip = new FixtureDeliverySlip__c();
            }
        }
        else {
            slip = new FixtureDeliverySlip__c();
        }
        if (slip.Wh_Staff__c == null) {
            slip.Wh_Staff__c = Userinfo.getUserId();
        }
        slip.IsForTransfer__c = true;

        return null;
    }
    private List<LabelValue> setFieldSet(String objApi, String fieldSetApi) {
        List<LabelValue> lvList = new List<LabelValue>();
        Map<String, Schema.FieldSet> fsMap = Schema.getGlobalDescribe().get(objApi).getDescribe().fieldSets.getMap();
        Schema.FieldSet fs = fsMap.get(fieldSetApi);
        List<FieldSetMember> fsmList = fs.getFields();

        for (FieldSetMember fsm : fsmList) {
            lvList.add(new LabelValue(fsm.getLabel(), fsm.getFieldPath()));
        }
        return lvList;
    }
    public PageReference searchSlip() {
        done_flg = false;
        Map<String,boolean> esdIdMap = new Map<String,boolean>();
        String qryString = 'select Id, Name, DeliveryCompany_SlipNo__c,DeliveryType__c,Distributor_method__c,DeliveryCompany__c,Wh_Staff__c '
                + 'from FixtureDeliverySlip__c '
                + 'where Name =\''+ slip.Name +'\' and DeliveryType__c = \'发货\'';
        if (String.isNotBlank(slip.Distributor_method__c)) {
            qryString += ' and Distributor_method__c = \''+ slip.Distributor_method__c +'\'';
        }
        if (String.isNotBlank(slip.DeliveryCompany__c)) {
            qryString += ' and DeliveryCompany__c = \''+ slip.DeliveryCompany__c +'\'';
        }
        List<FixtureDeliverySlip__c> slipList = Database.query(qryString);

        if (slipList.size() > 0) {
            if (slipList.size() > 1) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '当前条件检索到复数条运输单，请追加检索条件!'));
                return null;
            }
            slip = slipList[0];
        }
        else {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.WARNING, '没有检索出符合条件的运输单'));
        }
        return null;
    }
    // 保存物流信息按钮
    public void saveSlip() {
        done_flg = false;
        if(readOnly) return;
        Savepoint sp = Database.setSavepoint();
        try {
            String jsonstr = JSON.serialize(slip);
            TransferApply__c ta = [SELECT Shipment_Slip_tmp__c, Yi_loaner_arranged__c FROM TransferApply__c WHERE Id=:taId];
            if(ta.Yi_loaner_arranged__c > 0) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '调拨明细已发货，无法保存物流信息！'));
                return ;
            }
            ta.Shipment_Slip_tmp__c = jsonstr;
            update ta;
            done_flg = true;
        }
        catch (Exception ex) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage()));
            Database.rollback(sp);
            done_flg = false;
        }
    }
    private List<TransferApplyDetail__c> getDetails() {
        List<TransferApplyDetail__c> eList = [
                select SerialNumber_F__c, OneToOneAccessory__c, Main_OneToOne__c, TransferApplySummary__c
                        , Internal_Asset_number_key__c, Fixture_Model_No_F__c, TAESD_Status__c
                        , TransferApply__c, Shippment_loaner_time__c
                        , TransferApply__r.Shipment_Slip_tmp__c
                        , TransferApply__r.Yi_loaner_arranged__c
                        , TransferApply__r.Name
                        , DeliverySlip__c
                        , LastModifiedDate
                        , LastModifiedBy.Name
                        , Fixture_Model_No__c
                        , Approved_F__c, Fixture_Name_F__c, TransferApplySummary__r.Fixture_Set__r.Name
                        , Fixture_QRCode_F__c, TransferApplySummary__r.Name, Pre_inspection_time__c, StockDown__c
                        , StockDown_time__c, Id, Name, Asset__c, Asset__r.Name, Asset__r.SerialNumber, Asset__r.Product_Serial_No__c,
                       Asset__r.Remark__c, Asset__r.ImageAsset__c, Asset__r.ImageSerial__c, Asset__r.ImageAssetUploadedTime__c, Asset__r.ImageSerialUploadedTime__c,
                       Loaner_CDS_Info__c, Inspection_result__c, Check_lost_Item__c, Pre_disinfection__c, Water_leacage_check__c, Inspection_result_after__c, Arrival_in_wh__c,
                       Asset__r.Pre_Reserve_TAES_Detail__c, Asset__r.Pre_Reserve_TAES_Detail__r.After_Inspection_time__c,
                       Inspection_result_after_ng__c, Inspection_result_ng__c, Lost_item_giveup__c, CDS_complete__c, Loaner_accsessary__c
                  from TransferApplyDetail__c
                 where TransferApply__c = :taId
                   AND Cancel_Select__c = False
                 order by TransferApplySummary__r.Name, Name
        ];
        return eList;
    }
    private Map<Id, TransferApplyDetail__c> getDetailMap() {
        List<TransferApplyDetail__c> tadList = getDetails();
        Map<Id, TransferApplyDetail__c> tadMap = new Map<Id, TransferApplyDetail__c>();
        for(TransferApplyDetail__c tad:tadList) {
            tadMap.put(tad.Id, tad);
        }
        return tadMap;
    }
    private Boolean isRaStatusOK() {
        //检查是否可以继续
        List<Rental_Apply__c> RaTarList = [
            SELECT Campaign__c
                 , Repair__c
                 , Campaign__r.Status,repair__r.Return_Without_Repair_Date__c
                 , Repair__r.Repair_Final_Inspection_Date__c
                 , Repair__r.Repair_Shipped_Date__c
              FROM Rental_Apply__c
             WHERE id =:taId
        ];
        for (Rental_Apply__c RaTar : RaTarList) {
            if( RaTar.Campaign__r.Status == '取消'){
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '学会已取消，不能继续操作了'));
                return false;
            }
            else if(RaTar.Repair__r.Repair_Final_Inspection_Date__c != null){
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '存在修理最终检测日，不能继续了'));
                return false;
            }
            else if(RaTar.repair__r.Return_Without_Repair_Date__c != null && RaTar.repair__c!=null ){
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '未修理归还日不为空，不能出库'));
                return false;
            }
            else if(RaTar.Repair__r.Repair_Shipped_Date__c != null){
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '存在RC修理返送日，不能继续了'));
                return false;
            }
        }
        return true;
    }
    // 下架按钮
    public PageReference stockDown() {
        done_flg = false;
        //检查是否可以继续
        if(!isRaStatusOK()) {
            return null;
        }
        Set<Id> oneToOneTas = new Set<Id>();

        String userid = Userinfo.getUserId();
        Datetime now = System.Now();
        Map<Id, TransferApplyDetail__c> tadMap = getDetailMap();
        List<TransferApplyDetail__c> updateList = new List<TransferApplyDetail__c>();
        Boolean hasChecked = false;
        for (EsdInfo esdInfo : esdList) {
            if (!esdInfo.editable){
                continue;
            }
            TransferApplyDetail__c esd = esdInfo.rec;
            if(!tadMap.containsKey(esd.Id)) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '明细数量有变化，请刷新画面重试！'));
                return null;
            }
            TransferApplyDetail__c tad = tadMap.get(esd.Id);
            if(esdInfo.checked || oneToOneTas.contains(esd.TransferApplySummary__c)) {
                hasChecked = true;
                if(esd.LastModifiedDate != tad.LastModifiedDate) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.Fixture_Model_No__c + ':后台数据被 ' + tad.LastModifiedBy.Name + ' 修改，请刷新画面！'));
                    return null;
                }
                if(esd.StockDown__c && !tad.Approved_F__c) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.Fixture_Model_No__c + ':明细未批准，不能下架！'));
                    return null;
                }
                // 下架
                if(esd.StockDown__c && !tad.StockDown__c && tad.StockDown_time__c == null) {
                    tad.StockDown__c = true;
                    tad.StockDown_time__c = now;
                    tad.StockDown_staff__c = userId;
                    tad.Shipment_request_time2__c = now;
                    updateList.add(tad);
                }
                // 恢复到未下架
                else if (!esd.StockDown__c && tad.StockDown__c) {
                    tad.StockDown__c = false;
                    tad.StockDown_time__c = null;
                    tad.StockDown_staff__c = null;
                    tad.Shipment_request_time2__c = null;
                    updateList.add(tad);
                }
                if(esd.Main_OneToOne__c) {
                    oneToOneTas.add(esd.TransferApplySummary__c);
                }
            }
        }
        if(!hasChecked) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '未勾选下架的一览!'));
            return null;
        }
        Savepoint sp = Database.setSavepoint();
        try {
            if(!updateList.isEmpty()) {
                FixtureUtil.withoutUpdate(new List<TransferApply__c> {new TransferApply__c(Id=taId, Status__c='已出库指示')});
                FixtureUtil.withoutUpdate(updateList);
                done_flg = true;
            }
            if(done_flg) {
                init();
                done_flg = true;
            }
        } catch (Exception ex) {
            system.debug('=====' + ex.getMessage());
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage()));
            Database.rollback(sp);
            done_flg = false;
        }
        return null;
    }
    // 发货按钮
    public PageReference shipment() {
        done_flg = false;

        //检查是否可以继续
        if(!isRaStatusOK()) {
            return null;
        }

        //检查是否可以继续
        String userid = Userinfo.getUserId();
        Set<Id> eSet = new Set<Id>();
        Set<Id> oneToOneTas = new Set<Id>();
        List<TransferApplyDetail__c> eList = new List<TransferApplyDetail__c>();
        //申请书set
        for (EsdInfo esdInfo : esdList) {
            TransferApplyDetail__c esd = esdInfo.rec;
            if (esdInfo.checked || oneToOneTas.contains(esd.TransferApplySummary__c)) {
                eSet.add(esd.Id);
                if(esd.Main_OneToOne__c) {
                    oneToOneTas.add(esd.TransferApplySummary__c);
                }
            }
            else{
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '发货时必须全部勾选！'));
                return null;
            }
        }
        if(String.isBlank(slip.Name)
            || String.isBlank(slip.DeliveryCompany__c)
            || String.isBlank(slip.Distributor_method__c)
            || String.isBlank(slip.Wh_Staff__c)) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '发货物流信息必填！'));
            return null;
        }
        eList = [
            SELECT TransferApply__c, TransferApply__r.Shippment_ng_num__c, TransferApply__r.Pre_inspection_ng_num__c, TransferApplySummary__r.Inspection_not_finish__c, Fixture_Name_F__c, TransferApplySummary__r.Fixture_Set__r.Name, TransferApplySummary__r.TransferApply__r.Name, TransferApplySummary__r.Name, Pre_inspection_time__c, StockDown__c, StockDown_time__c, Id, Name, Asset__c, Asset__r.Name, Asset__r.SerialNumber, Asset__r.Product_Serial_No__c,
                           TransferApply__r.Name, Asset__r.Remark__c, Asset__r.ImageAsset__c, Asset__r.ImageSerial__c, Asset__r.ImageAssetUploadedTime__c, Asset__r.ImageSerialUploadedTime__c,
                           Loaner_CDS_Info__c, Inspection_result__c, Check_lost_Item__c, Pre_disinfection__c, Water_leacage_check__c, Inspection_result_after__c, Arrival_in_wh__c,
                           Asset__r.Pre_Reserve_TAES_Detail__c, Asset__r.Pre_Reserve_TAES_Detail__r.After_Inspection_time__c,
                           Inspection_result_after_ng__c, Inspection_result_ng__c, Lost_item_giveup__c, CDS_complete__c, Loaner_accsessary__c
              FROM TransferApplyDetail__c
             WHERE TransferApply__c =: taId
               AND Cancel_Select__c = false
               AND Shippment_loaner_time_F__c = null
               FOR UPDATE
        ];
        if (eList.size() == 0) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '没有可发货的调拨明细，请刷新画面重试！'));
            return null;
        }

        Set<Id> astForLock = new Set<Id>();
        for (TransferApplyDetail__c esd : eList) {
            if(!eSet.contains(esd.Id)) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '有新追加的明细未在画面上显示，请刷新画面重试！'));
                return null;
            }
            if (esd.StockDown__c == false) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '未下架明细不能发货！'));
                return null;
            }
            astForLock.add(esd.Asset__c);
        }
        List<Asset> astLock = [
            SELECT Id
              FROM Asset
             WHERE id in :astForLock
               FOR UPDATE
        ];

        if (slip.Id != null) {
            List<FixtureDeliverySlip__c> slipList = [
                SELECT Combine_Pack__c, Name, Id, DeliveryCompany_SlipNo__c,DeliveryType__c,Distributor_method__c,DeliveryCompany__c,Wh_Staff__c
                  FROM FixtureDeliverySlip__c
                 WHERE Id =:slip.Id
                   FOR UPDATE
            ];
            if(!slipList.isEmpty()) {
                slip = slipList[0];
            }
            else {
                slip.Id = null;
            }
        }
        slip.Shippment_loaner_time__c = Datetime.now();

        List<TransferApply__c> raList = [
            SELECT Id
                 , DeliverySlip__c
              FROM TransferApply__c
             WHERE Id =:taId
               AND Status__c != '取消'
        ];
        if(raList.isEmpty()) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '调拨申请不存在或已取消！'));
            return null;
        }
        Savepoint sp = Database.setSavepoint();
        try {
            Datetime now = System.now();
            FixtureUtil.withoutUpsertObjects(new List<FixtureDeliverySlip__c>{ slip });
            for (TransferApplyDetail__c esd : eList) {
                esd.DeliverySlip__c = slip.Id;
                // 20210706 ljh 1719
                // esd.Pre_inspection_time__c = now;
                // esd.Inspection_staff__c = userId;
                // esd.Inspection_result__c = 'OK';
                // 20210706 ljh 1719
            }

            for (TransferApply__c ra : raList) {
                String jsonstr = JSON.serialize(slip);
                ra.DeliverySlip__c = slip.Id;
                ra.Shipment_Slip_tmp__c = jsonstr;
            }
            FixtureUtil.withoutUpsertObjects(eList);
            FixtureUtil.withoutUpsertObjects(raList);
            //esdList.clear();
            //eList = getDetails();
            //for (TransferApplyDetail__c esd : eList) {
            //    EsdInfo ei = new EsdInfo(esd);
            //    esdList.add(ei);
            //}
            //readOnly = true;
            init();
            done_flg = true;

        } catch (Exception ex) {
            String msg = ex.getMessage();
            if (msg != null && msg.contains('DUPLICATE_VALUE') && msg.contains('DeliveryCompany_SlipNo__c')) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '系统已存在相同的运输单。如果继续使用该运输单发货，请输入运输单号检索，检索后再勾选配套发货。'));
            } else {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, msg));
            }
            Database.rollback(sp);
            done_flg = false;
        }

        return null;
    }
    // 取消明细按钮
    public void cancelDetail() {
        done_flg = false;
        Map<Id, TransferApplySummary__c> updateTasMap = new Map<Id, TransferApplySummary__c>();
        Map<Id, TransferApplyDetail__c> updateTadMap = new Map<Id, TransferApplyDetail__c>();
        Boolean hasChecked = false;
        Savepoint sp = Database.setSavepoint();
        try {
            Map<Id, TransferApplyDetail__c> tadMap = getDetailMap();
            for (EsdInfo esdInfo : esdList) {
                if (!esdInfo.editable){
                    continue;
                }
                TransferApplyDetail__c esd = esdInfo.rec;
                if(esdInfo.checked) {
                    hasChecked = true;
                    if(!tadMap.containsKey(esd.Id)) {
                        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.Fixture_Model_No__c + ':明细不存在或已取消，请刷新画面重试！'));
                        return;
                    }
                    TransferApplyDetail__c tad = tadMap.get(esd.Id);
                    if(esd.LastModifiedDate != tad.LastModifiedDate) {
                        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.Fixture_Model_No__c + ':后台数据被 ' + tad.LastModifiedBy.Name + ' 修改，请刷新画面！'));
                        return;
                    }
                    if(tad.DeliverySlip__c != null) {
                        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.Fixture_Model_No__c + ':明细已发货，不可取消！'));
                        return;
                    }
                    // 有主体的配套要按配套取消
                    if(esd.Main_OneToOne__c) {
                        updateTasMap.put(esd.TransferApplySummary__c,
                            new TransferApplySummary__c(Id=esd.TransferApplySummary__c,
                                Cancel_Select__c = true,
                                Cancel_Reason__c = '主动取消'));
                    }
                    // 非一对一附属品按明细取消
                    else if(!esd.OneToOneAccessory__c) {
                        tad.Cancel_Select__c = true;
                        tad.Cancel_Reason__c = '主动取消';
                    }
                    updateTadMap.put(esd.Id, tad);
                }
            }
            if(!hasChecked) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '未勾选取消的一览!'));
                return;
            }
            if(!updateTadMap.isEmpty()) {
                update updateTadMap.values();
            }
            if(!updateTasMap.isEmpty()) {
                update updateTasMap.values();
            }
            init();
            done_flg = true;
        }
        catch (Exception ex) {
            System.debug(ex.getStackTraceString());
            ApexPages.addMessages(ex);
            Database.rollback(sp);
        }
    }
    public class EsdInfo {
        public TransferApplyDetail__c rec { get; set; }
        // 回库はSet単位で、明細一つ一つのquickCheck要らない
        public Boolean checked {get;set;}
        public boolean editable { get; set; }
        public String fsName {get;set;}
        public String tasId {get;set;}

        public EsdInfo(TransferApplyDetail__c rec) {
            this.rec = rec;
            this.checked = false;
            this.editable = rec.Approved_F__c && rec.Shippment_loaner_time__c == null;
            this.fsName = rec.TransferApplySummary__r.Name+'：'+rec.TransferApplySummary__r.Fixture_Set__r.Name;
            this.tasId = rec.TransferApplySummary__r.Id;
        }
    }
    public class LabelValue {
        public String label {get; set;}
        public String value {get; set;}

        public LabelValue(String l, String v) {
            label = l;
            value = v;
        }
    }
}