public with sharing class SetPersonalTargetEngController {
    // 当前期
    public String currentPeriod { get; private set; }
    // 上年度按钮制御
    public Boolean previousRendered { get; private set; }
    // 下年度按钮制御
    public Boolean nextRendered { get; private set; }
    // 数据集
    public List<DataBean> dataBeans { get; set; }
    // 金额分类
    public List<String> opportunity_category { get; private set; }
    // 是否是过去年度
    public Boolean isPast { get; private set; }
    // 年度変化時セーブかどうか
    public Boolean saveFlg { get; set; }
    // 本部の選択値
    public String salesDpt { get; set; }
    // 職位のチェックボックス
    public List<Position> plist { get; set; }
    // 登陆用户
    public User loginUser { get; set; }
    // checkAll値保持用
    public Boolean checkAll { get; set; }
    // 製品担当の選択値
    public String productUser { get; set; }
    // 医院担当 プルダウン
    public static List<SelectOption> productUserOptions { get; private set; }
    static {
        productUserOptions = new List<SelectOption>();
        productUserOptions.add(new SelectOption('医院担当','医院担当'));
        productUserOptions.add(new SelectOption('医院担当以外','医院担当以外'));
    }
    
    public SetPersonalTargetEngController() {
        //Apexpages.currentPage().getHeaders().put('X-UA-Compatible', 'IE=8');    
    }
    
    // ユーザ数
    public Integer getUserSize() {
        return users.size();
    }
    // 職位数
    public Integer getPSize() {
        return plist.size();
    }
    // 本部プルダウン
    public static List<SelectOption> salesDptOpts { get; private set; }
    static {
        salesDptOpts = new List<SelectOption>();
        salesDptOpts.add(new SelectOption('','--无--'));
        salesDptOpts.add(new SelectOption('1.华北','1.华北'));
        salesDptOpts.add(new SelectOption('2.东北','2.东北'));
        salesDptOpts.add(new SelectOption('3.西北','3.西北'));
        salesDptOpts.add(new SelectOption('4.西南','4.西南'));
        salesDptOpts.add(new SelectOption('5.华东','5.华东'));
        salesDptOpts.add(new SelectOption('6.华南','6.华南'));
    }
    
    //  现在年度
    private Integer currentYear;
    //  当前年度
    private Integer iYear;
    //  当前月份
    private Integer iMonth;
    //  当前日期
    private Integer iDay;
    //  4月可编辑期限
    private Integer iBuffer;
    
    private RecordType rt;           // 目标的数据类型
    private User[] users;            // 担当人员
    private Map<String, List<Double>> proportion;     // 比重
    private String adminDpt = null;
    
    // 既存目标数据
    private Map<String, Opportunity> oppMap;
    // 金额分类
    //private static String[] amountCategory = new String[] {'GI','ET','BF','GS','URO','GYN','ENT','OTH'};
    private static String[] amountCategory = new String[] {'ENG'};
    
    // 画面初始化
    public Pagereference init() {
        // 现在时间
        Date dateNow = Date.today();
        Integer year = dateNow.year();
        Integer month = dateNow.month();
        if (month < 4) {
            year -= 1;
        }
        // 初始化
        currentYear = year;
        iYear = year;
        iMonth = month;
        iDay = dateNow.day();
        iBuffer = Integer.valueOf(System.Label.SetPersonalTarget_buffer_day);
        isPast = false;
//        if (month == 3) isPast = true;
        currentPeriod = String.valueOf(iYear - 1867 + 'P');
        previousRendered = true;
        nextRendered = true;
        saveFlg = false;
        // 金额分类
        opportunity_category = amountCategory;
        // 每月比重
        if (proportion == null) {
            proportion = new Map<String, List<Double>>();
            String strObjectiveProportionGI = System.Label.ObjectiveProportionGI;
            List<String> objectiveProportionGI = strObjectiveProportionGI.split(',');
            List<Double> doubleGI = new List<Double>();
            for (String strGI : objectiveProportionGI) {
                doubleGI.add(Double.valueOf(strGI));
            }
            proportion.put('GI', doubleGI);

            String strObjectiveProportionET = System.Label.ObjectiveProportionET;
            List<String> objectiveProportionET = strObjectiveProportionET.split(',');
            List<Double> doubleET = new List<Double>();
            for (String strET : objectiveProportionET) {
                doubleET.add(Double.valueOf(strET));
            }
            proportion.put('ET', doubleET);

            String strObjectiveProportionBF = System.Label.ObjectiveProportionBF;
            List<String> objectiveProportionBF = strObjectiveProportionBF.split(',');
            List<Double> doubleBF = new List<Double>();
            for (String strBF : objectiveProportionBF) {
                doubleBF.add(Double.valueOf(strBF));
            }
            proportion.put('BF', doubleBF);

            String strObjectiveProportionGS = System.Label.ObjectiveProportionGS;
            List<String> objectiveProportionGS = strObjectiveProportionGS.split(',');
            List<Double> doubleGS = new List<Double>();
            for (String strGS : objectiveProportionGS) {
                doubleGS.add(Double.valueOf(strGS));
            }
            proportion.put('GS', doubleGS);

            String strObjectiveProportionURO = System.Label.ObjectiveProportionURO;
            List<String> objectiveProportionURO = strObjectiveProportionURO.split(',');
            List<Double> doubleURO = new List<Double>();
            for (String strURO : objectiveProportionURO) {
                doubleURO.add(Double.valueOf(strURO));
            }
            proportion.put('URO', doubleURO);

            String strObjectiveProportionGYN = System.Label.ObjectiveProportionGYN;
            List<String> objectiveProportionGYN = strObjectiveProportionGYN.split(',');
            List<Double> doubleGYN = new List<Double>();
            for (String strGYN : objectiveProportionGYN) {
                doubleGYN.add(Double.valueOf(strGYN));
            }
            proportion.put('GYN', doubleGYN);

            String strObjectiveProportionENT = System.Label.ObjectiveProportionENT;
            List<String> objectiveProportionENT = strObjectiveProportionENT.split(',');
            List<Double> doubleENT = new List<Double>();
            for (String strENT : objectiveProportionENT) {
                doubleENT.add(Double.valueOf(strENT));
            }
            proportion.put('ENT', doubleENT);

            String strObjectiveProportionOTH = System.Label.ObjectiveProportionOTH;
            List<String> objectiveProportionOTH = strObjectiveProportionOTH.split(',');
            List<Double> doubleOTH = new List<Double>();
            for (String strOTH : objectiveProportionOTH) {
                doubleOTH.add(Double.valueOf(strOTH));
            }
            proportion.put('OTH', doubleOTH);

            // CHAN-BBLCYP 2019048 LHJ Start
            //String strObjectiveProportionENG = System.Label.ObjectiveProportionENG;
            String strObjectiveProportionENG = System.Label.ObjectiveProportionENGENG;
            // CHAN-BBLCYP 2019048 LHJ End
            List<String> objectiveProportionENG = strObjectiveProportionENG.split(',');
            List<Double> doubleENG = new List<Double>();
            for (String strENG : objectiveProportionENG) {
                doubleENG.add(Double.valueOf(strENG));
            }
            proportion.put('ENG', doubleENG);
        }
        // 職位
        if (plist == null) {
            plist = new List<Position>();
            plist.add(new Position('一般', true));
            plist.add(new Position('高级', true));
            plist.add(new Position('主管', true));
            plist.add(new Position('副经理', false));
            plist.add(new Position('经理', false));
            plist.add(new Position('副部长', false));
            plist.add(new Position('部长', false));
        }
        
        // 当前用户信息
        if (loginUser == null) {
            loginUser = [Select Id, Salesdepartment__c, Province__c, ProfileId From User where Id = :Userinfo.getUserId()];
            //loginUser.Province__c = '';
        }
        adminDpt = loginUser.Salesdepartment__c;
        if (String.isBlank(adminDpt)
                && (loginUser.ProfileId == System.Label.ProfileId_SystemAdmin
                        || loginUser.ProfileId == System.Label.ProfileId_103
                )
        ) {
            adminDpt = '4.华东';
        }
        
        users = this.getUserList(false, false);
        // 目标的数据类型
        if (rt == null) {
            rt = [select Id from RecordType where SobjectType = 'Opportunity' and IsActive = true and DeveloperName = 'Target'];
        }
        // 数据赋值
        setBean(iYear);
        // 保存成功のメッセージ
        String s = System.currentPageReference().getParameters().get('s');
        if (s == '1') {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, '保存成功。'));
        }
        return null;
    }
    
    // 点击上年度
    public void previous() {
        if (saveFlg) {
            this.saveLogic();
        }
        
        iYear -= 1;
        currentPeriod = String.valueOf(iYear - 1867 + 'P');
        // 是否是过去数据
        isPast = false;
        if (iYear < currentYear && !(currentYear - iYear == 1 && iMonth == 4 && iDay <= iBuffer)) {
            isPast = true;
        }// else if (iYear == currentYear) {
//            if (Date.today().month() == 3) {
//                isPast = true;
//            }
//        }
        previousRendered = true;
        nextRendered = true;
        // 数据赋值
        setBean(iYear);
    }
    
    // 点击下年度
    public void next() {
        if (saveFlg) {
            this.saveLogic();
        }
        
        iYear += 1;
        currentPeriod = String.valueOf(iYear - 1867 + 'P');
        // 是否是过去数据
        isPast = false;
        if (iYear < currentYear && !(currentYear - iYear == 1 && iMonth == 4 && iDay <= iBuffer)) {
            isPast = true;
        }// else if (iYear == currentYear) {
//            if (Date.today().month() == 3) {
//                isPast = true;
//            }
//        }
        previousRendered = true;
        nextRendered = true;
        // 只显示到现在时间的下一年数据
        if (iYear > currentYear) {
            nextRendered = false;
        }
        // 数据赋值
        setBean(iYear);
    }
    
    // 本部プルダウン変更時の処理、システム管理者専用
    public void searchByDpt() {
        if (saveFlg) {
            this.saveLogic();
        }
        users = this.getUserList(true, false);
        // 数据赋值
        setBean(iYear);
    }
    
    // 省プルダウン変更時の処理
    public void searchByProvince() {
        if (saveFlg) {
            this.saveLogic();
        }
        users = this.getUserList(false, true);
        // 数据赋值
        setBean(iYear);
    }
    
    // 職位変更時の処理
    public void searchByFilter() {
        if (saveFlg) {
            this.saveLogic();
        }
        users = this.getUserList(false, false);
        // 数据赋值
        setBean(iYear);
    }
    
    // 点击保存按钮
    public Pagereference saveBtn() {
        this.saveLogic();
        
        PageReference ref = new Pagereference('/apex/SetPersonalTargetEng?s=1');
        ref.setRedirect(true);
        return ref;
    }
    
    // 点击返回按钮
    public Pagereference backBtn() {
        // HOMEに戻る
        PageReference ref = new Pagereference('/home/home.jsp');
        ref.setRedirect(true);
        return ref;
    }
    
    // ユーザの検索
    private List<User> getUserList(Boolean searchByDpt, Boolean searchByProvince) {
        String soql = 'select Id, Salesdepartment__c, Province__c, Alias, Product_specialist_incharge_product__c, Use_Start_Date__c,'
                    + ' ProfileId, Profile.Name, UserRoleId, UserRole.Name, Sales_Speciality__c, Post__c'
                    + ' from User where IsActive = true and Test_staff__c = false';
/*        if (String.isBlank(productUser) || productUser == '医院担当') {
            soql += ' and Sales_Speciality__c = \'医院担当\'';
        } else {
            soql += ' and Sales_Speciality__c <> \'医院担当\'';
        }*/
        // 本部にて検索の場合、省を無視
        if (searchByDpt) {
            loginUser.Province__c = null;
        // 省にて検索の場合、本部を無視
        } else if (searchByProvince) {
            salesDpt = null;
        // 職位にて検索の場合
        } else {}
        
        if (!String.isBlank(salesDpt)) {
            soql += ' and Salesdepartment__c = \'' + salesDpt + '\'';
        }
        if (!String.isBlank(loginUser.Province__c)) {
            soql += ' and Province__c = \'' + loginUser.Province__c + '\'';
        }
/*        if (String.isBlank(salesDpt) && String.isBlank(loginUser.Province__c)) {
            soql += ' and Salesdepartment__c = \'' + adminDpt + '\'';
        }
        if (searchByProvince) {
            salesDpt = adminDpt;
        }*/
        soql += ' and Dept__c = \'能量事业本部\'';
        
        // 職位条件
        List<String> positionNames = new List<String>();
        for (Position p : plist) {
            if (p.check) {
                positionNames.add(p.positionName);
            }
        }
        if (positionNames.size() > 0) {
            soql += ' and (';
            for (Integer i = 0; i < positionNames.size(); i++) {
                if (i == positionNames.size() - 1) {
                    soql += ' Post__c = \'' + positionNames[i] + '\'';
                } else {
                    soql += ' Post__c = \'' + positionNames[i] + '\' or';
                }
            }
            soql += ')';
        }
        soql += ' order by Salesdepartment__c, Province__c, UserRole.Name';
        
        return Database.query(soql);
    }
    
    // 数据赋值
    private void setBean(Integer year) {
        // 取得当前年度目标数据
        //Opportunity[] opportunitys = ControllerUtil.oppSelectForPersonTaget(rt.Id, users, currentPeriod);
        // OLY_OCM-202
        Opportunity[] opportunitys = [select
                        Id, OwnerId, Opportunity_Category__c, Proportion__c, CloseDate,
                        Amount, Objective__c, Target_category__c,
                        SAP_Province__c, RecordTypeId, OCM_Target_period__c
                 from Opportunity
                where Target_category__c = '担当目标'
                  and RecordTypeId = :rt.Id
                  and OwnerId in :users
                  and OCM_Target_period__c = :currentPeriod];
        // 当前年度没有数据时，显示信息
        if (opportunitys.size() <= 0 && isPast && iYear < currentYear) {
            ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.INFO, '没有上年度的数据。');
            ApexPages.addMessage(msg);
            previousRendered = false;
            iYear += 1;
            currentPeriod = String.valueOf(iYear - 1867 + 'P');
            isPast = false;
            if (iYear < currentYear && !(currentYear - iYear == 1 && iMonth == 4 && iDay <= iBuffer)) {
                isPast = true;
            }// else if (iYear == currentYear) {
//                if (Date.today().month() == 3) {
//                    isPast = true;
//                }
//            }
            // 今表示しているデータを再取得
            setBean(iYear);
            return;
        }
        // 保存当前年度所有既存目标数据
        oppMap = new Map<String, Opportunity>();
        for (Opportunity opp : opportunitys) {
            if (opp.OwnerId != null && opp.Opportunity_Category__c != null && opp.CloseDate !=null){
                //  目标 key : OwnerId + _ + Opportunity_Category__c + _ + CloseDate(yyyy-mm-dd)
                String key = opp.OwnerId + '_' + opp.Opportunity_Category__c + '_' + String.valueOf(opp.CloseDate);
                oppMap.put(key, opp);
            }
        }
        // 建立数据集
        dataBeans = new List<DataBean>();
        for (Integer u = 0; u < users.size(); u++) {
            DataBean dataBean = new DataBean(users[u], oppMap, iYear);
            dataBeans.add(dataBean);
        }
    }
    
    // 実際の保存ロジック
    private void saveLogic() {
        List<Opportunity> saveList = new List<Opportunity>();
        List<Opportunity> deleteList = new List<Opportunity>();
        // 只处理当前本部数据
        for (Integer d = 0; d < dataBeans.size(); d++) {
            DataBean db = dataBeans[d];
            
            // 寄存数据比例值是否变化
            Boolean proportionChanged = false;
            for (Integer i = 0; i < 12; i++) {
                Integer y = iYear;
                Integer m = 4 + i;
                if (m > 12) {
                    y += 1;
                    m -= 12;
                }
                String syear = String.valueOf(y);
                String smonth = String.valueOf(m);
                if (m < 10) {
                    smonth = '0' + smonth;
                }
                String sTargetDay = syear + '-' + smonth + '-01';
                // 按金额分类顺序处理
                for (Integer j = 0; j < amountCategory.size(); j++) {
                    String amountC = amountCategory[j];
                    // 数据检索Key
                    String key = db.user.Id + '_' + amountC + '_' + sTargetDay;
                    // 每月数据赋值
                    Opportunity opp = new Opportunity();
                    if (oppMap.containskey(key)) {
                        opp = oppMap.get(key);
                        if (opp.Proportion__c != proportion.get(amountC)[i]) {
                            proportionChanged = true;
                            break;
                        }
                    }
                }
                if (proportionChanged) {
                    break;
                }
            }
            if (db.isChanged == '0' && !proportionChanged) {
                continue;
            }
            // 使用开始后目标金额补正系数计算
            Map<String, Decimal> proportionSumMap = new Map<String, Decimal>();
            for (Integer j = 0; j < amountCategory.size(); j++) {
                String amountC = amountCategory[j];
                proportionSumMap.put(amountC, 0.0);
            }
            for (Integer i = 0; i < 12; i++) {
                Integer y = iYear;
                Integer m = 4 + i;
                if (m > 12) {
                    y += 1;
                    m -= 12;
                }
                String syear = String.valueOf(y);
                String smonth = String.valueOf(m);
                if (m < 10) {
                    smonth = '0' + smonth;
                }
                String sTagetDay = syear + '-' + smonth + '-01';
                Date tagetDay = Date.valueOf(sTagetDay);
                if (db.user.Use_Start_Date__c < tagetDay) {
                    //proportionSum += proportion[i];
                    for (Integer j = 0; j < amountCategory.size(); j++) {
                        String amountC = amountCategory[j];
                        proportionSumMap.put(amountC, proportionSumMap.get(amountC) + proportion.get(amountC)[i]);
                    }
                }
            }
            //proportionSum = proportionSum / 100;
            for (Integer j = 0; j < amountCategory.size(); j++) {
                String amountC = amountCategory[j];
                proportionSumMap.put(amountC, proportionSumMap.get(amountC) / 100);
            }
            // 一年分成12条数据
            for (Integer i = 0; i < 12; i++) {
                Integer y = iYear;
                Integer m = 4 + i;
                if (m > 12) {
                    y += 1;
                    m -= 12;
                }
                String syear = String.valueOf(y);
                String smonth = String.valueOf(m);
                if (m < 10) {
                    smonth = '0' + smonth;
                }
                String sTagetDay = syear + '-' + smonth + '-01';
                Date tagetDay = Date.valueOf(sTagetDay);
                if (db.user.Use_Start_Date__c >= tagetDay) {
                    // 使用開始当月 及び 開始前 は目標を登録しない，无视。
                    continue;
                }
                // 按金额分类顺序处理
                for (Integer j = 0; j < amountCategory.size(); j++) {
                    String amountC = amountCategory[j];
                    // 数据检索Key
                    String key = db.user.Id + '_' + amountC + '_' + sTagetDay;
                    // 每月数据赋值
                    Opportunity opp = new Opportunity();
                    if (oppMap.containskey(key)) {
                        opp = oppMap.get(key);
                        if (db.amount[j].Amount == null || db.amount[j].Amount == 0) {
                            deleteList.add(opp);
                            continue;
                        }
                        opp.Proportion__c = proportion.get(amountC)[i];
                        opp.Amount = db.amount[j].Amount / proportionSumMap.get(amountC);
                    } else {
                        if (db.amount[j].Amount == null || db.amount[j].Amount == 0) {
                            continue;
                        }
                        opp.Name = db.user.Alias + ' 担当目标';
                        opp.StageName = '目標';
                        opp.OwnerId = db.user.Id;
                        // トリガをスルーのため、ここでやります
                        opp.Owner_System__c = db.user.Id;
                        opp.Opportunity_Category__c = amountC;
                        opp.Proportion__c = proportion.get(amountC)[i];
                        opp.CloseDate = tagetDay;
                        opp.Amount = db.amount[j].Amount / proportionSumMap.get(amountC);
                        opp.Target_category__c = '担当目标';
                        opp.SAP_Province__c = db.user.Province__c;
                        opp.RecordTypeId = rt.Id;
                        opp.OCM_Target_period__c = currentPeriod;
                    }
                    // 加入保存列表
                    saveList.add(opp);
                }
            }
            // 数据库限制小于10000条
            if (saveList.size() + deleteList.size() >= 4000) {
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, '操作数据量过大，截止至' + db.user.Alias + '的数据操作完成，之后的数据请再次输入并保存。'));
                break;
            }
        }
        // トリガをスルー
        StaticParameter.EscapeOpportunityBefUpdTrigger = true;
        StaticParameter.EscapeOpportunityHpDeptUpdTrigger = true;
        StaticParameter.EscapeNFM007Trigger = true;

        // 更新数据库
        if (saveList.size() > 0) upsert saveList;
        if (deleteList.size() > 0) delete deleteList;
    }
    
    // 数据类
    class DataBean {
        // 担当者信息
        public User user { get; private set; }
        // 总金额，画面用
        public Opportunity[] amount { get; set; }
        // 是否变化 0：无 1：有
        public String isChanged { get; set; }
        
        // 构造方法
        DataBean(User user, Map<String, Opportunity> oppMap, Integer iYear) {
            this.user = user;
            this.amount = new List<Opportunity>();
            this.isChanged = '0';
            // 按金额分类，查找数据，并设值
            for (Integer i = 0; i < amountCategory.size(); i++) {
                String amountC = amountCategory[i];
                Opportunity a = new Opportunity();
                a.Opportunity_Category__c = amountC;
                Decimal amountSum = 0.0;
                for (Integer j = 0; j < 12; j++) {
                    Integer y = iYear;
                    Integer m = 4 + j;
                    if (m > 12) {
                        y += 1;
                        m -= 12;
                    }
                    String strY = String.valueOf(y);
                    String strM = String.valueOf(m);
                    if (strM.length() < 2) {
                        strM = '0' + strM;
                    }
                    String key = user.Id + '_' + amountC + '_' + strY + '-' + strM + '-01';
                    if (oppMap.containskey(key)) {
                        //a.Amount = oppMap.get(key).Amount;
                        amountSum += oppMap.get(key).Objective__c == null ? 0 : oppMap.get(key).Objective__c;
                    }
                }
                if (amountSum > 0) {
                    amountSum = amountSum.setScale(2);
                    a.Amount = amountSum;
                }
                this.amount.add(a);
            }
        }
    }
    
    // 職位チェックボックスリスト作成
    class Position {
        public String positionName { get; private set; }
        public Boolean check { get; set; }
        
        public Position(String positionName, Boolean flg) {
            this.positionName = positionName;
            this.check = flg;
        }
    }
}