public with sharing class AccountCaseTabController {
    private static integer SECTIONMAX = 14;
    private static integer FIELDMAX = 100;
    
    private Account dept;
    
    private OFSHospitalLayout__c layout;
    private Map<String, OFSHospitalLayout__c> layoutMap;
    private Map<String, Schema.SObjectField> layoutFieldMap;

    public HistoryBean history { get; set; }
    public String accId { get; private set; }
    
    public Boolean refreshAll { get; private set; }
    public Boolean dupliErr { get; private set; }
    
    public List<String> ocmOptions { get; private set; }
//    public List<String> ocmYearOptions { get; private set; }
    public List<SelectOption> ocmYearOptions { get; private set; }
    public Map<String,id> RecordTypeMap;
    public AccountCaseTabController() {
        refreshAll = false;
        dupliErr = false;
        ocmOptions = new List<String>();
//        ocmYearOptions = new List<String>();
        ocmYearOptions = new List<SelectOption>();
        history = null;
        
        layout = new OFSHospitalLayout__c();
        layoutMap = OFSHospitalLayout__c.getAll();
        if (layoutMap.values().size() <= 0) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR, '无法获取自定义设置'));
            return;
        }
        
        Schema.DescribeSobjectResult acl = OFSHospitalLayout__c.sObjectType.getDescribe();
        layoutFieldMap = acl.fields.getMap();
    }
    
    public void init() {
        RecordTypeMap = new Map<String,Id>();
        //deloitte-zhj 20231129 PIPL还原
        RecordTypeMap.put('Department_Class_GI',System.Label.DeparmentClassHardCode.split(',')[0]);//戦略科室分類 消化科
        RecordTypeMap.put('Department_Class_ET',System.Label.DeparmentClassHardCode.split(',')[0]);//戦略科室分類ET
        RecordTypeMap.put('Department_Class_BF',System.Label.DeparmentClassHardCode.split(',')[1]);//戦略科室分類 呼吸科
        RecordTypeMap.put('Department_Class_GS',System.Label.DeparmentClassHardCode.split(',')[2]);//戦略科室分類 普外科
        RecordTypeMap.put('Department_Class_URO',System.Label.DeparmentClassHardCode.split(',')[3]);//戦略科室分類 泌尿科
        RecordTypeMap.put('Department_Class_GYN',System.Label.DeparmentClassHardCode.split(',')[4]);//戦略科室分類 婦人科
        RecordTypeMap.put('Department_Class_ENT',System.Label.DeparmentClassHardCode.split(',')[5]);//戦略科室分類 耳鼻喉科
        RecordTypeMap.put('Department_Class_OTH',System.Label.DeparmentClassHardCode.split(',')[6]);//戦略科室分類 その他
        // RecordTypeMap.put('Department_Class_GI','01210000000QmhoAAC');//戦略科室分類 消化科
        // RecordTypeMap.put('Department_Class_ET','01210000000QmhoAAC');//戦略科室分類ET
        // RecordTypeMap.put('Department_Class_BF','01210000000QmhyAAC');//戦略科室分類 呼吸科
        // RecordTypeMap.put('Department_Class_GS','01210000000QmvDAAS');//戦略科室分類 普外科
        // RecordTypeMap.put('Department_Class_URO','01210000000QmutAAC');//戦略科室分類 泌尿科
        // RecordTypeMap.put('Department_Class_GYN','01210000000QmuyAAC');//戦略科室分類 婦人科
        // RecordTypeMap.put('Department_Class_ENT','01210000000Qmv3AAC');//戦略科室分類 耳鼻喉科
        // RecordTypeMap.put('Department_Class_OTH','01210000000Qmv8AAC');//戦略科室分類 その他
        String recordId = System.currentPageReference().getParameters().get('id');
        accId = System.currentPageReference().getParameters().get('accid');
        
        dept = [select Id, ParentId, RecordType.DeveloperName from Account where Id = :accId];
        for (OFSHospitalLayout__c setting : layoutMap.values()) {
            if ('AccountCase_' + dept.RecordType.DeveloperName == setting.recordType_devName__c) {
                layout = setting;
            }
        }
        if (layout.Id == null) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR, '无法获取自定义设置'));
            return;
        }
        
        // 今年±1期のみを出す
        Date dateToday = 
        Date.today();
        Integer year = dateToday.year();
        Integer month = dateToday.month();
        if (month < 4) {
            year -= 1;
        }
        // OCM期、画面からremoveするデータを設定
        Schema.DescribeFieldResult fieldResult = Account_Number_of_case__c.OCM_Period__c.getDescribe();
        List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
        for(Schema.PicklistEntry f : ple) {
            if (f.getValue() == String.valueOf(year - 1867 - 1 + 'P')
                || f.getValue() == String.valueOf(year - 1867 + 'P')
                || f.getValue() == String.valueOf(year - 1867 + 1 + 'P')) {
                continue;
            }
            ocmOptions.add(f.getValue());
        }
        // OCM年度、画面からremoveするデータを設定
        Schema.DescribeFieldResult fieldResultYear = Account_Number_of_case__c.OCM_Year__c.getDescribe();
        List<Schema.PicklistEntry> pley = fieldResultYear.getPicklistValues();
/*
        for(Schema.PicklistEntry f : pley) {
            if (f.getValue() == String.valueOf(year - 1 + '年度')
                || f.getValue() == String.valueOf(year + '年度')
                || f.getValue() == String.valueOf(year + 1 + '年度')) {
                continue;
            }
            ocmYearOptions.add(f.getValue());
        }
*/
        ocmYearOptions.add(new SelectOption(String.valueOf(year - 1 + '年度'),String.valueOf(year - 1 + '年度')));
        ocmYearOptions.add(new SelectOption(String.valueOf(year + '年度'),String.valueOf(year + '年度')));
        ocmYearOptions.add(new SelectOption(String.valueOf(year + 1 + '年度'),String.valueOf(year + 1 + '年度')));

        if (String.isBlank(recordId) == true) {
            List<Account_Number_of_case__c> tmpList = Database.query(this.makeSoql2());
            if (tmpList.size() > 0) {
                //history = new HistoryBean(tmpList[0].clone(false, true), layout, layoutFieldMap);
                history = new HistoryBean(new Account_Number_of_case__c(), layout, layoutFieldMap);
                //history.rec.OCM_Period__c = null;
                //history.rec.OCM_Year__c = null;
            } else {
                history = new HistoryBean(new Account_Number_of_case__c(), layout, layoutFieldMap);
            }
            history.rec.unique_key__c = null;
        } else {
            selectData(recordId);
        }
    }
    
    // 重複エラーが発生する時、js alertを出し、＋タブを消すため、画面リフレッシュ必要
    // 正常で終了する時、新規追加されたタブを出すため、画面リフレッシュ必要
    // 合わせて、refreshAllフラグを設定
    public void save() {
        Savepoint sp = Database.setSavepoint();
        try {
            // 新規
            if (history.rec.Id == null) {
                history.rec.OCM_Period__c = changeY2P(history.rec.OCM_Year__c);
/*
                // 重複チェック
                List<Account_Number_of_case__c> tmp = [select Id from Account_Number_of_case__c where Account__c = :accId and OCM_Period__c = :history.rec.OCM_Period__c];
                if (tmp.size() > 0) {
//                    recordId = tmp[0].Id;
                    dupliErr = true;
                    refreshAll = true;
                    return;
                }
*/
                history.rec.RecordTypeid = RecordTypeMap.get(dept.RecordType.DeveloperName);
                history.rec.Account__c = dept.Id;
                history.rec.Account_HP__c = dept.ParentId;
                
                //20211210 lt start
                //ESD
                Decimal esdup = 0;
                Decimal esddown = 0;
                Decimal esd = 0;
                if(history.rec.ESD_UpNumber__c != null){
                    esdup = history.rec.ESD_UpNumber__c;
                }
                if(history.rec.ESD_DownNumber__c != null){
                    esddown = history.rec.ESD_DownNumber__c;
                }
                if(history.rec.ESD_Number__c != null){
                    esd = history.rec.ESD_Number__c;
                }
                history.rec.ESD_AddNumber__c = esdup + esddown + esd;

                //EUS
                Decimal eusup = 0;
                Decimal eusdown = 0;
                Decimal eus = 0;
                if(history.rec.EUS_UpNumber__c != null){
                    eusup = history.rec.EUS_UpNumber__c;
                }
                if(history.rec.EUS_DownNumber__c != null){
                    eusdown = history.rec.EUS_DownNumber__c;
                }
                if(history.rec.EUS_Number__c != null){
                    eus = history.rec.EUS_Number__c;
                }
                history.rec.EUS_AddNumber__c = eusup + eusdown + eus;

                //ERCP
                Decimal ercpup = 0;
                Decimal ercpdown = 0;
                Decimal ercp = 0;
                if(history.rec.ERCP_UpNumber__c != null){
                    ercpup = history.rec.ERCP_UpNumber__c;
                }
                if(history.rec.ERCP_DownNumber__c != null){
                    ercpdown = history.rec.ERCP_DownNumber__c;
                }
                if(history.rec.ERCP_Number__c != null){
                    ercp = history.rec.ERCP_Number__c;
                }
                history.rec.ERCP_AddNumber__c = ercpup + ercpdown + ercp;
                //20211210 lt end

                insert history.rec;
                refreshAll = true;

            }
            // 更新
            else {
                history.rec.OCM_Period__c = changeY2P(history.rec.OCM_Year__c);

                                //20211210 lt start
                //ESD
                Decimal esdup = 0;
                Decimal esddown = 0;
                Decimal esd = 0;
                if(history.rec.ESD_UpNumber__c != null){
                    esdup = history.rec.ESD_UpNumber__c;
                }
                if(history.rec.ESD_DownNumber__c != null){
                    esddown = history.rec.ESD_DownNumber__c;
                }
                if(history.rec.ESD_Number__c != null){
                    esd = history.rec.ESD_Number__c;
                }
                history.rec.ESD_AddNumber__c = esdup + esddown + esd;

                //EUS
                Decimal eusup = 0;
                Decimal eusdown = 0;
                Decimal eus = 0;
                if(history.rec.EUS_UpNumber__c != null){
                    eusup = history.rec.EUS_UpNumber__c;
                }
                if(history.rec.EUS_DownNumber__c != null){
                    eusdown = history.rec.EUS_DownNumber__c;
                }
                if(history.rec.EUS_Number__c != null){
                    eus = history.rec.EUS_Number__c;
                }
                history.rec.EUS_AddNumber__c = eusup + eusdown + eus;

                //ERCP
                Decimal ercpup = 0;
                Decimal ercpdown = 0;
                Decimal ercp = 0;
                if(history.rec.ERCP_UpNumber__c != null){
                    ercpup = history.rec.ERCP_UpNumber__c;
                }
                if(history.rec.ERCP_DownNumber__c != null){
                    ercpdown = history.rec.ERCP_DownNumber__c;
                }
                if(history.rec.ERCP_Number__c != null){
                    ercp = history.rec.ERCP_Number__c;
                }
                history.rec.ERCP_AddNumber__c = ercpup + ercpdown + ercp;
                //20211210 lt end

                update history.rec;
                selectData(history.rec.Id);
            }
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO, '保存完了。'));
        } catch (Exception ex) {
            Database.rollback(sp);
            ApexPages.addMessages(ex);
        }
    }
    
    private String changeY2P(String ocmYear) {
        Integer y = Integer.valueOf(ocmYear.substring(0, 4));
        return y - 1867 + 'P';
    }
    
    private void selectData(String recordId) {
        List<Account_Number_of_case__c> tmpList = Database.query(this.makeSoql(recordId));
        if (tmpList.size() > 0) {
            history = new HistoryBean(tmpList[0], layout, layoutFieldMap);
        }
        else {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR, '没有数据。'));
        }
    }

    private String makeSoql(String recordId) {
        Schema.DescribeSobjectResult d = Account_Number_of_case__c.sObjectType.getDescribe();
        Map<String, Schema.SObjectField> fieldMap = d.fields.getMap();
        
        String soql = 'select ';
        String fields = '';
        for (String field : fieldMap.keySet()) {
            if (fields.length() > 0) {
                fields += ', ';
            }
            fields += field;
        }
        soql += fields;
        soql += ' from Account_Number_of_case__c where Id = :recordId';

        return soql;
    }
    
    private String makeSoql2() {
        Schema.DescribeSobjectResult d = Account_Number_of_case__c.sObjectType.getDescribe();
        Map<String, Schema.SObjectField> fieldMap = d.fields.getMap();
        
        String soql = 'select ';
        String fields = '';
        for (String field : fieldMap.keySet()) {
            if (fields.length() > 0) {
                fields += ', ';
            }
            fields += field;
        }
        soql += fields;
        soql += ' from Account_Number_of_case__c where Account__c = \'' + this.accId + '\''
             + ' order by OCM_Period__c desc limit 1';

        return soql;
    }
    
    public class HistoryBean {
        public Account_Number_of_case__c rec { get; set; }
        public List<OutputData> dataList { get; set; }
        
        public HistoryBean(Account_Number_of_case__c record, OFSHospitalLayout__c layout, Map<String, Schema.SObjectField> layoutFieldMap) {
            rec = record;
            dataList = new List<OutputData>();
            
            Map<String, SectionBean> sectionMap = new Map<String, SectionBean>();
            for (Integer i = 1; i <= SECTIONMAX; i++) {
                String strI = 'section' + i + '__c';
                
                if (layoutFieldMap.containsKey(strI) == false) continue;
                String sectionStr = String.valueOf(layout.get(strI));
                
                if (String.isBlank(sectionStr) == false) {
                    SectionBean sb = new SectionBean(sectionStr);
                    sectionMap.put(sb.id, sb);
                }
            }
            
            for (Integer i = 1; i <= FIELDMAX; i++) {
                String strI = 'field' + i + '__c';
                
                if (layoutFieldMap.containsKey(strI) == false) continue;
                String fieldStr = String.valueOf(layout.get(strI));
                
                if (String.isBlank(fieldStr) == false) {
                    FieldBean fb = new FieldBean(fieldStr);
                    if (sectionMap.containsKey(fb.sectionId)) {
                        dataList.add(new OutputData(record, sectionMap.get(fb.sectionId), fb));
                    }
                }
            }
            
            // 整形、rowspan設定
            String tmplvl1 = '';
            String tmplvl2 = '';
            Integer rowspan1 = 0;
            Integer rowspan2 = 0;
            Integer lvl1Cnt = 1;
            Integer lvl2Cnt = 1;
            for (Integer i = 0; i < dataList.size(); i++) {
                if (i == 0) {
                    tmplvl1 = dataList[i].sb.title;
                    tmplvl2 = dataList[i].fb.parentLabel;
                }
                // section変わった時、全リセット
                if (i != 0 && tmplvl1 != dataList[i].sb.title) {
                    tmplvl1 = dataList[i].sb.title;
                    tmplvl2 = dataList[i].fb.parentLabel;
                    dataList[i - rowspan1].lvl1Rowspan = rowspan1;
                    dataList[i - rowspan2].lvl2Rowspan = rowspan2;

                    rowspan1 = 0;
                    rowspan2 = 0;
                    lvl1Cnt++;
                    lvl2Cnt++;
                }
                // 中分類変わった時、中分類のみリセット
                if (i != 0 && tmplvl2 != dataList[i].fb.parentLabel) {
                    tmplvl2 = dataList[i].fb.parentLabel;
                    dataList[i - rowspan2].lvl2Rowspan = rowspan2;
                    
                    rowspan2 = 0;
                    lvl2Cnt++;
                }
                
                dataList[i].lvl1Idx = lvl1Cnt + '';
                dataList[i].lvl2Idx = lvl1Cnt + '_' + lvl2Cnt;
                rowspan1++;
                rowspan2++;
            }
            
            if (rowspan1 > 0) {
                dataList[dataList.size() - rowspan1].lvl1Rowspan = rowspan1;
            }
            if (rowspan2 > 0) {
                dataList[dataList.size() - rowspan2].lvl2Rowspan = rowspan2;
            }
        }
    }
    
    class OutputData {
        public Account_Number_of_case__c rec { get; set; }
        public SectionBean sb { get; private set; }
        public FieldBean fb { get; private set; }
        public Integer lvl1Rowspan { get; private set; }
        public Integer lvl2Rowspan { get; private set; }
        public String lvl1Idx { get; set; }
        public String lvl2Idx { get; set; }
        
        public OutputData(Account_Number_of_case__c record, SectionBean sb, FieldBean fb) {
            this.rec = record;
            this.sb = sb;
            this.fb = fb;
            lvl1Rowspan = 0;
            lvl2Rowspan = 0;
            lvl1Idx = '';
            lvl2Idx = '';
        }
    }
    
    class SectionBean {
        public String title { get; private set; }
        public String id { get; private set; }
        
        public SectionBean(String jsonSection){
            Map<String, Object> m = (Map<String, Object>) JSON.deserializeUntyped(jsonSection);
            id =  String.valueOf(m.get('id'));
            title =  String.valueOf(m.get('title'));
        }
    }
    
    class FieldBean {
        public String label { get; private set; }
        public String parentLabel { get; private set; }
        public String sectionId { get; private set; }
        public String apiNum { get; private set; }
        public String apiPrice { get; private set; }
        
        public FieldBean(String jsonField) {
            Map<String, Object> m = (Map<String, Object>) JSON.deserializeUntyped(jsonField);
            label = String.valueOf(m.get('label'));
            parentLabel = String.valueOf(m.get('parentLabel'));
            sectionId = String.valueOf(m.get('sectionId'));
            apiNum = String.valueOf(m.get('apiNum'));
            apiPrice = String.valueOf(m.get('apiPrice'));
            if (String.isBlank(apiPrice)) {
                apiPrice = 'false';
            }
        }
    }
}