public class ReceivingNoteTestDataFactory {
    public Map<String, Account> accountMap;
    public List<Product2> proList;
    public Map<String, Asset> assetMap;
    public List<Fixture_Set__c> fsList;
    public List<Fixture_Set_Detail__c> fsdList;
    public Map<String,List<Product2>> proMap;
    public Map<String,ReceivingNote__c> rnMap;
    public Map<String,ReceivingNoteSummary__c> rnsMap;
    public Map<String,ReceivingNoteDetail__c> rndMap;

    public ReceivingNoteTestDataFactory(){
        accountMap = new Map<String, Account>();
        proList = new List<Product2>();
        assetMap= new Map<String, Asset>();
        fsList = new List<Fixture_Set__c>();
        fsdList = new List<Fixture_Set_Detail__c>();
        rnMap = new Map<String,ReceivingNote__c>();
        rnsMap = new Map<String,ReceivingNoteSummary__c>();
        rndMap = new Map<String,ReceivingNoteDetail__c>();
        ControllerUtil.EscapeNFM001Trigger = true;
        StaticParameter.EscapeNFM001Trigger = true;
        StaticParameter.EscapeAccountTrigger = true;
        StaticParameter.EscapeNFM001AgencyContractTrigger = true;
    }
    /**
    @description 创建并插入用户
    */
    private void setupAccountMap() {
        List<Account> accountList= [
                SELECT Id
                     , Department_Name__c
                     , AgentCode_Ext__c
                  FROM Account
                 WHERE AgentCode_Ext__c =: System.Label.Account_Asset
                    OR AgentCode_Ext__c =: System.Label.Account_Asset_Client
                    OR AgentCode_Ext__c =: System.Label.Account_Asset_Client_Done];
        if(accountList.size()>0){
            for(Account account : accountList){
                accountMap.put(account.Department_Name__c,account);
            }
            return;
        }

        // 省
        Address_Level__c al = new Address_Level__c();
        al.Name = '東京';
        al.Level1_Code__c = 'CN-99';
        al.Level1_Sys_No__c = '999999';
        insert al;
        // 市
        Address_Level2__c al2 = new Address_Level2__c();
        al2.Level1_Code__c = 'CN-99';
        al2.Level1_Sys_No__c = '999999';
        al2.Level1_Name__c = '東京';
        al2.Name = '渋谷区';
        al2.Level2_Code__c = 'CN-9999';
        al2.Level2_Sys_No__c = '9999999';
        al2.Address_Level__c = al.id;
        insert al2;

        // 病院を作る
        Account hospital = new Account();
        hospital.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'HP'].id;
        hospital.Name = 'test hospital';
        hospital.Is_Active__c = '有効';
        hospital.Attribute_Type__c = '卫生部';
        hospital.Speciality_Type__c = '综合医院';
        hospital.Grade__c = '一级';
        hospital.OCM_Category__c = 'SLTV';
        hospital.Is_Medical__c = '医疗机构';
        hospital.State_Master__c = al.id;
        hospital.City_Master__c = al2.id;
        hospital.Town__c = '东京';
        insert hospital;

        // 戦略科室を得る
        Account strategicDep = new Account();
        strategicDep.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'Department_Class_OTH'].id;
        strategicDep.Name = '其它';
        strategicDep.Department_Class_Label__c = '其他';
        strategicDep.Hospital__c = hospital.Id;
        strategicDep.ParentId = hospital.Id;
        insert strategicDep;

        // 备品中心:9999963
        Account account1 = new Account();
        account1.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'Department_OTH'].id;
        account1.Name = 'Olympus社内 其他 备品';
        account1.AgentCode_Ext__c = System.Label.Account_Asset;
        account1.ParentId = strategicDep.Id;
        account1.Department_Class__c = strategicDep.Id;
        account1.Department_Name__c = '备品';
        account1.Hospital__c = hospital.Id;
        accountMap.put('备品',account1);

        // 备品待收货:9999964
        Account account2 = new Account();
        account2.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'Department_OTH'].id;
        account2.Name = 'Olympus社内 其他 备品(待收货)';
        account2.AgentCode_Ext__c = System.Label.Account_Asset_Client;
        account2.ParentId = strategicDep.Id;
        account2.Department_Class__c = strategicDep.Id;
        account2.Department_Name__c = '备品(待收货)';
        account2.Hospital__c = hospital.Id;
        accountMap.put('备品(待收货)',account2);
        
        // 备品(已收货):9999965
        Account account3 = new Account();
        account3.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'Department_OTH'].id;
        account3.Name = 'Olympus社内 其他 备品(已收货)';
        account3.AgentCode_Ext__c = System.Label.Account_Asset_Client_Done;
        account3.ParentId = strategicDep.Id;
        account3.Department_Class__c = strategicDep.Id;
        account3.Department_Name__c = '备品(已收货)';
        account3.Hospital__c = hospital.Id;
        accountMap.put('备品(已收货)',account3);

        //20210630 ljh start 
        // 备品(非集中管理):9999960
        // Olympus社内 其他 备品(非集中管理)
        Account account4 = new Account();
        account4.recordtypeId = [Select Id FROM RecordType WHERE IsActive = true and SobjectType = 'Account' and DeveloperName = 'Department_OTH'].id;
        account4.Name = 'Olympus社内 其他 备品(非集中管理)'; 
        account4.AgentCode_Ext__c = System.Label.Account_Asset_FJZ;
        account4.ParentId = strategicDep.Id;
        account4.Department_Class__c = strategicDep.Id;
        account4.Department_Name__c = '备品(非集中管理)';
        account4.Hospital__c = hospital.Id;
        accountMap.put('备品(非集中管理)',account4);
        //20210630 ljh start
        upsert accountMap.values() AgentCode_Ext__c;

    }
    private void setupProList() {
        proList = [SELECT Id from Product2 WHERE Fixture_Model_No__c LIKE 'SB-MODEL-%' ORDER BY Fixture_Model_No__c];
        if (proList.isEmpty()) {
            Product2 pro1 = new Product2(Name='name01',IsActive=true,Family='GI',
                    Fixture_Model_No__c='SB-MODEL-01',Serial_Lot_No__c='S/N tracing',
                    Fixture_Model_No_T__c = 'SB-MODEL-01', Asset_Model_No__c = 'Pro01',
                    ProductCode_Ext__c='SB-PRO-CODE-01',Manual_Entry__c=false,
                    ProductCode = 'SB-PRO-CODE-01');
            Product2 pro2 = new Product2(Name='name02',IsActive=true,Family='GI',
                    Fixture_Model_No__c='SB-MODEL-02',Serial_Lot_No__c='Lot tracing',
                    Fixture_Model_No_T__c = 'SB-MODEL-02', Asset_Model_No__c = 'Pro02',
                    ProductCode_Ext__c='SB-PRO-CODE-02',Manual_Entry__c=false,
                    ProductCode = 'SB-PRO-CODE-02');
            Product2 pro3 = new Product2(Name='name03',IsActive=true,Family='GI',
                    Fixture_Model_No__c='SB-MODEL-03',Serial_Lot_No__c='Lot tracing',
                    Fixture_Model_No_T__c = 'SB-MODEL-03', Asset_Model_No__c = 'Pro03',
                    ProductCode_Ext__c='SB-PRO-CODE-03',Manual_Entry__c=false,
                    ProductCode = 'SB-PRO-CODE-03');
            proList.add(pro1);
            proList.add(pro2);
            proList.add(pro3);
            upsert proList Asset_Model_No__c;
        }
    }
    private void setupFsList(){
        fsList = [Select Id FROM Fixture_Set__c WHERE Name = 'SB-FS-01'];
        if(fsList.isEmpty()){
            Fixture_Set__c fs = new Fixture_Set__c();
            fs.Name = 'SB-FS-01';
            fs.Fixture_Set_Body_Model_No__c = 'SB-FS-MODEL-01';
            fs.Loaner_name__c = 'SB-FS-1';
            fsList.add(fs);
            upsert fsList Loaner_name__c;
        }
    }
    private void setupFsdList(){
        fsdList = [SELECT Id from Fixture_Set_Detail__c WHERE Name LIKE 'SB-FSD-%' ORDER BY Name ];
        if(fsdList.isEmpty()){
            Fixture_Set_Detail__c fsd1 = new Fixture_Set_Detail__c();
            fsd1.Name = 'SB-FSD-1';
            fsd1.Name_CHN_Created__c = 'SB-中文FSD-1';
            fsd1.Product2__c = proList[0].Id;
            fsd1.Fixture_Set__c = fsList[0].Id;
            fsd1.Is_Body__c = true;
            fsd1.Quantity__c = 1;
            fsd1.UniqueKey__c = fsList[0].Id + ':' + proList[0].Id;
            fsd1.SortInt__c = 1;
            fsdList.add(fsd1);

            Fixture_Set_Detail__c fsd2 = new Fixture_Set_Detail__c();
            fsd2.Name = 'SB-FSD-2';
            fsd2.Name_CHN_Created__c = 'SB-中文FSD-2';
            fsd2.Product2__c = proList[1].Id;
            fsd2.Fixture_Set__c = fsList[0].Id;
            fsd2.Is_Body__c = false;
            fsd2.Quantity__c = 1;
            fsd2.UniqueKey__c = fsList[0].Id + ':' + proList[1].Id;
            fsd2.SortInt__c = 2;
            fsdList.add(fsd2);
            upsert fsdList UniqueKey__c;
        }

    }
    /**
    @description 安装master数据 2个pro，1个fs，2个fsd，3个account，5种不同类型asset
    */
    public void setupMasterData(){
        StaticParameter.EscapeNFM001AgencyContractTrigger = true;
        StaticParameter.EscapeNFM001Trigger = true;
        Oly_TriggerHandler.bypass(ContactTriggerHandler.class.getName());
        Oly_TriggerHandler.bypass(AgencyHospitalHandler.class.getName());
        // 两个pro
        setupProList();
        // 一个FS
        setupFsList();
        // 两个FSD
        setupFsdList();
        // 3个account
        setupAccountMap();

        // 固定资产 个体
        assetMap.put('固定资产,个体管理',createAsset('固定资产,个体管理',1));
        assetMap.put('附属品,个体管理',createAsset('附属品,个体管理',2));
        assetMap.put('附属品,数量管理',createAsset('附属品,数量管理',3));
        assetMap.put('耗材,数量管理',createAsset('耗材,数量管理',4));
        assetMap.put('低值易耗品,数量管理',createAsset('低值易耗品,数量管理',5));

        Asset assetShare = new Asset(Asset_Owner__c = 'Olympus');
        //assetShare.AssetManageConfirm__c = true;
        assetShare.Freeze_sign__c = false;
        assetShare.RecordTypeId = System.Label.Asset_RecordType;
        assetShare.SerialNumber = 'SB-ASSET-SERIAL-6';
        assetShare.Name = 'SB-ASSET-6';
        assetShare.AccountId = accountMap.get('备品(待收货)').Id;
        assetShare.Product2Id = proList[1].Id;
        assetShare.Quantity = 100;
        assetShare.Status = '不明';
        assetShare.Manage_type__c = '数量管理';
        assetShare.Salesdepartment__c = '1.华北营业本部';
        assetShare.Internal_asset_location__c = '北京 备品中心';
        assetShare.Product_category__c = 'GI';
        assetShare.Equipment_Type__c = '产品试用';
        assetShare.SalesProvince__c = '北京';
        assetShare.CompanyOfEquipment__c = '北京';
        assetShare.Internal_Asset_number__c = '0006';
        assetShare.Asset_loaner_category__c = '附属品';
        assetShare.Barcode__c = 'SB-0000-0000-0006';
        assetShare.CompanyOfEquipment__c = '北京';
        assetShare.Internal_Asset_number__c = 'SB-INTER-NUMBER-6';
        assetShare.Product_Serial_No__c = 'PRO:'+assetShare.SerialNumber;
        assetShare.Guaranteen_end__c = Date.Today();
        assetShare.Loaner_accsessary__c = true;
        assetMap.put('共有附属品', assetShare);
        upsert assetMap.values() Barcode__c ;

    }
    /**
    @param typeString 所要创建的保有设备类别
                    '固定资产,个体管理'
                    '附属品,个体管理'
                    '附属品,数量管理'
                    '耗材,数量管理'
                    '低值易耗品,数量管理'
    @param i 编号，用以区分类别相同的不同设备
    @return Asset 保有设备对象
    @description 创建一个保有设备
    */
    private Asset createAsset(String typeString, Integer i ){
        Datetime dt = Datetime.now();
        String dt_str = dt.format('yyyyMMdd');

        String assetCategory = typeString.split(',')[0];
        String manageType = typeString.split(',')[1];

        Asset asset1 = new Asset(Asset_Owner__c = 'Olympus');
        //asset1.AssetManageConfirm__c = true;
        asset1.Freeze_sign__c = false;
        asset1.RecordTypeId = System.Label.Asset_RecordType;
        asset1.SerialNumber = 'SB-ASSET-SERIAL-' + i + '(' + dt_str + ')';
        asset1.Name = 'SB-ASSET-'+i;
        asset1.AccountId = accountMap.get('备品(待收货)').Id;
        asset1.Product2Id = proList[0].Id;
        asset1.Quantity = 1;
        asset1.Status = '不明';
        asset1.Manage_type__c = manageType;
        if (manageType == '数量管理'){
            asset1.Loaner_accsessary__c = true;
        }
        asset1.Salesdepartment__c = '1.华北营业本部';
        asset1.Internal_asset_location__c = '北京 备品中心';
        asset1.Product_category__c = 'GI';
        asset1.Equipment_Type__c = '产品试用';
        asset1.SalesProvince__c = '北京';
        asset1.CompanyOfEquipment__c = '北京';
        asset1.Internal_Asset_number__c = '000'+i;
        asset1.Asset_loaner_category__c = assetCategory;
        asset1.Barcode__c = 'SB-0000-0000-000'+i;
        asset1.CompanyOfEquipment__c = '北京';
        asset1.Internal_Asset_number__c = 'SB-INTER-NUMBER-'+i;
        asset1.Product_Serial_No__c = 'PRO:'+asset1.SerialNumber;
        asset1.Guaranteen_end__c = Date.Today();
        asset1.Consumable_Guaranteen_end__c = System.Today();
        return asset1;
    }
    /**
    @param typeStringList 所要创建的数据类型列表
                        '固定资产,个体管理'
                        '附属品,个体管理'
                        '附属品,数量管理'
                        '耗材,数量管理'
                        '低值易耗品,数量管理'
    @description 新建清单 一览 明细 三个对象并插入数据库
    */
    public void setupReceivingNoteData(List<String> typeStringList){
        // 如果直接调用本方法，会先从数据库中取出master数据，如果无法取出，则执行上面的setupMasterData
        if (accountMap.isEmpty()){
            setupAccountMap();
        }
        if(proList.isEmpty()){
            setupProList();
        }
        if (fsList.isEmpty()) {
            setupFsList();
        }

        if (fsdList.isEmpty()) {
            setupFsdList();
        }

        if(assetMap.isEmpty()){
            List<Asset> assetList = [SELECT Id, Manage_type__c, Asset_loaner_category__c FROM Asset WHERE Barcode__c LIKE 'SB-0000-0000-000%'];

            for (Asset asset1 : assetList){
                assetMap.put(asset1.Asset_loaner_category__c + ',' + asset1.Manage_type__c,asset1);
            }
        }

        Integer i = 1;
        List<Asset> newAssetList = new List<Asset>();
        for(String typeString : typeStringList){
            if (!assetMap.containsKey(typeString)){
                Asset ass1 = createAsset(typeString,i);
                newAssetList.add(ass1);
                assetMap.put(typeString, ass1);
            }
            i+=1;
        }
        if(newAssetList.size()>0){
            upsert newAssetList Barcode__c ;
        }

        i = 1;
        for(String typeString : typeStringList){
            String assetCategory = typeString.split(',')[0];
            // 收货清单
            ReceivingNote__c rn = new ReceivingNote__c();
            rn.Managment_Code__c = 'SB-MCODE-'+i;
            rn.ManagementCenter__c = 'SB';
            rn.Name = 'SB-'+assetCategory+'-'+i;
            rn.Internal_asset_location__c = '北京 备品中心';
            rn.OrderCode__c = 'SB-ORDERCODE-'+i;
            rn.ApprovalNumber__c = 'SB-APPROVALNUMBER-'+i;
            rn.Asset_loaner_category__c = assetCategory;
            rn.DateOfDelivery__c = Date.Today();
            rn.Sales_order_number__c = 'SB-SALE-ORDER-NUMBER-'+i;
            rn.Model_Reminder_Email_Text__c = null;
            rnMap.put(typeString, rn);
            i += 1;
        }
        upsert rnMap.values() Managment_Code__c;

        i = 1;
        for(String typeString : typeStringList){
            // 收货清单一览
            ReceivingNoteSummary__c rns = new ReceivingNoteSummary__c();
            rns.ReceivingNote__c = rnMap.get(typeString).Id;
            rns.Fixture_Set__c = fsList[0].Id;
            rns.Fixture_Model_No__c = 'SB-RNS-MODEL-'+i;
            rns.Internal_Asset_number__c = 'SB-INTERNAL-ASSET-'+i;
            rns.passTxtNo3__c = '001';
            rns.DataMigration_Flag__c = true;
            rnsMap.put(typeString, rns);
            i+=1;
        }
        upsert rnsMap.values() Internal_Asset_number__c;

        i = 1;
        for(String typeString : typeStringList){
            String assetCategory = typeString.split(',')[0];
            Asset assetObj = assetMap.get(typeString);
            // 收货一览明细
            ReceivingNoteDetail__c rnd = new ReceivingNoteDetail__c();
            rnd.ReceivingNoteSummary__c = rnsMap.get(typeString).Id;
            rnd.FSD_Id__c = fsdList[0].Id;
            rnd.Fixture_Set_Detail__c = fsdList[0].Id;
            rnd.Product_Serial_No__c = 'SB-PRO-SERIAL-'+i;
            rnd.passNo2__c = '01';
            rnd.passNo3__c = '1';
            rnd.SerialNumber__c = 'SB-SERIALNUMBER-'+i;
            rnd.RNDAssert__c = assetObj.Id;
            rnd.DataMigration_Flag__c = true;
            rnd.Manage_type__c = assetObj.Manage_type__c;
            rnd.ImageAssetBase64__c = 'base64';

            if (assetCategory == '耗材'){
                rnd.unknow_serial_NO_product__c = 'FALSE';
                rnd.Loaner_accsessary__c = 'TRUE';
                rnd.FSD_Id__c = null;
                rnd.Fixture_Set_Detail__c = null;
            }
            rndMap.put(typeString,rnd);
            i+=1;
        }
        upsert rndMap.values() Product_Serial_No__c;
    }

}