package com.gridnine.xtrip.server.reports.templates
//import com.gridnine.xtrip.server.vip.rzd.UfsConnector;
import com.gridnine.xtrip.common.vip.rzd.RzdTransListResult;
import com.gridnine.xtrip.server.vip.ufs.model.TransListRequest;
import com.gridnine.xtrip.server.vip.ufs.model.TransListResponse;
import com.gridnine.xtrip.server.vip.ufs.util.UfsUtil;
import com.gridnine.xtrip.common.model.helpers.MessageHelper;
import com.gridnine.xtrip.server.vip.ufs.model.domain.TransInfo;
import com.gridnine.xtrip.common.vip.rzd.RzdTransInfo;
import com.gridnine.xtrip.common.vip.rzd.RzdTransactionType;
import com.gridnine.xtrip.common.Environment;
import com.gridnine.xtrip.common.vip.rzd.*
import com.gridnine.xtrip.common.model.entity.EntityStorage;
import com.gridnine.xtrip.common.util.TextUtil;
import com.gridnine.xtrip.common.model.booking.ProductStatus;
import com.gridnine.xtrip.common.util.XmlUtil;
import com.gridnine.xtrip.common.model.booking.railway.RailwayProduct;
import com.gridnine.xtrip.common.model.rzd.vip.VipRzdSettings;
import com.gridnine.xtrip.server.vip.helpers.VipRulesHelper
import com.gridnine.xtrip.server.vip.rzd.UfsGateEx

import java.util.Set

import com.gridnine.xtrip.server.vip.ufs.model.UfsSettings
import com.gridnine.xtrip.common.model.system.Message
import com.gridnine.xtrip.common.l10n.model.L10nStringHelper
import com.gridnine.xtrip.common.util.LocaleUtil

createStyle(name: 'title',fontBold: true, h_span: 14, h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:20)
createStyle(name: 'metadataTitle',fontBold: true, h_span: 2, h_alignment: 'RIGHT', v_alignment: 'CENTER', fontHeight:10)
createStyle(name: 'metadataValue', parent: 'metadataTitle', h_span: 10, fontBold: false, h_alignment: 'LEFT')
createStyle(name: 'metadataDateValue', parent: 'metadataValue', format: 'm/d/yy')
createStyle(name: 'header',fontBold: false,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10, leftBorder:'MEDIUM', rightBorder:'MEDIUM', topBorder:'MEDIUM', bottomBorder:'MEDIUM', wrapText: true)
createStyle(name: 'data',fontBold: false,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:10, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN')
createStyle(name: 'textData',parent: 'data')
createStyle(name: 'numberData',parent: 'data',h_alignment: 'RIGHT', format: '#,##0.00')
createStyle(name: 'dateData',parent: 'data',h_alignment: 'RIGHT',format: 'm/d/yy')
createStyle(name: 'statusGroupTitle', parent: 'header', h_span: 12, h_alignment: 'RIGHT', fontBold: true)
createStyle(name: 'statusGroupNumber',parent: 'statusGroupTitle',  h_span: 1)
createStyle(name: 'subagencyGroupTitle', parent: 'statusGroupTitle')
createStyle(name: 'subagencyGroupNumber',parent: 'subagencyGroupTitle',  h_span: 1)
createStyle(name: 'totalTitle', parent: 'subagencyGroupTitle')
createStyle(name: 'totalNumber',parent: 'totalTitle', h_span: 1)
createStyle(name: 'error', foreground: 'RED', h_alignment : 'CENTER')
createStyle(name: 'success', foreground: 'LIGHT_GREEN', h_alignment : 'CENTER')

// METADATA
nextRow(); rowHeight(13);
text('Отчет по продажам ЖД за:', 'metadataTitle'); 
nextColumn();
date(parameters['REPORT-PERIOD'], 'metadataDateValue');

nextRow(); 
text('Дата составления отчета:', 'metadataTitle');
nextColumn();
date(new Date(), 'metadataDateValue')


//HEADER
nextRow();
rowHeight(15);

text('№ Билета', 'header')
columnWidth(22)

nextColumn()
text('Дата операции', 'header')
columnWidth(16)

nextColumn()
text('Маршрут','header')
columnWidth(14)

nextColumn()
text('Пассажиры', 'header')
columnWidth(16)

nextColumn()
text('Статус', 'header')
columnWidth(10)

nextColumn()
text('Статус УФС', 'header')
columnWidth(16)

nextColumn()
text('Стоимость', 'header')
columnWidth(12)

nextColumn()
text('Стоимость УФС',  'header')
columnWidth(18)

nextColumn()
text('Сбор',  'header')
columnWidth(10)


nextColumn()
text('Сбор УФС',  'header')
columnWidth(14)

nextColumn()
text('Результат сверки',  'header')
columnWidth(28)

Set<UfsSettings> getUfsSettingsSet() {
    Set<UfsSettings> result = VipRulesHelper.getRzdReportUfsSettings(parameters['SALES_POINT']).keySet()
    info("ufsSettings: ${result}")
    return result
}

TransListResponse getTransList(UfsSettings ufsSettings, TransListRequest request) {
    UfsGateEx ufsGate = new UfsGateEx()
    ufsGate.configure(new Properties())
    ufsGate.updateConfiguration(ufsSettings.url, ufsSettings.url, ufsSettings.login, ufsSettings.password, ufsSettings.terminal)
    return ufsGate.getTransList(request)
}

Set<UfsSettings> ufsSettingsSet
ufsSettingsSet = getUfsSettingsSet()

def negateCl =  {
    return it.getValue() == 14;
}

def toRzdModel = { type->
    for (RzdTransactionType rzdType : RzdTransactionType.values()) {
        if (rzdType.getValue() == type.getValue()) {
            return rzdType;
        }
    }

    return null;
}

def getTransList = { dt->
          
    long timing = System.currentTimeMillis();
    RzdTransListResult result = new RzdTransListResult();

    try {
        TransListRequest request = new TransListRequest();
        request.setDate(dt);
        
        for (UfsSettings ufsSettings : ufsSettingsSet) {
            TransListResponse response = getTransList(ufsSettings, request)
            
            if (!UfsUtil.SUCCESS_STATUS.equals(response.getStatus())) {
                warn("error: ${response.message}")
                result.getMessages().add(
                    MessageHelper.createErrorMessage("UFS error", "status="
                        + response.getStatus(), "code=" + response.getCode(),
                        "message=" + response.getMessage()));
            } else {
                for (TransInfo info : response.getTrans()) {
                    RzdTransInfo rzdInfo = new RzdTransInfo();
                    rzdInfo.setConfirmDate(info.getConfirmDate());
                    rzdInfo.setCreateDate(info.getCreateDate());
                    rzdInfo.setIdTrans(info.getIdTrans());
                    rzdInfo.setOrderNum(info.getOrderNum());
                    rzdInfo.setPlaceCount(info.getPlaceCount());
                    rzdInfo.setPrevTrans(info.getPrevTrans());
                    rzdInfo.setrStatus(info.getrStatus());
                    rzdInfo.setStan(info.getStan());
                    rzdInfo.setTerminal(info.getTerminal());
                    rzdInfo.setTest(info.isTest());
                    rzdInfo.setTransactionType(toRzdModel(info
                        .getTransactionType()));
                    rzdInfo.settStatus(info.gettStatus());
    
                    boolean negate = negateCl(info.getTransactionType());
                    BigDecimal fee = info.getFee();
                    BigDecimal amount = info.getAmount();
                    if (negate) {
                        fee = fee.negate();
                        amount = amount.negate();
                    }
    
                    rzdInfo.setFee(fee);
                    rzdInfo.setAmount(amount);
    
                    result.getTrans().add(rzdInfo);
                }
            }
        }
        return result;
    } finally {
      //  result.getTiming().add(createTimingRecord("getTransList", timing)); //$NON-NLS-1$
    }
}

def getData = {
    def data = []
    def document = com.gridnine.xtrip.common.xml.XUtil.getDocumentBuilder().parse(new File(it))
    def nd = document.getElementsByTagName("Trans")
    for(def i = 0; i<nd.getLength(); i++){
        def el = nd.item(i)
        
        def transType = ['value' : XmlUtil.getValue(el, 'Type').toInteger()]
        def trans = ['amount' : XmlUtil.getValue(el, 'Amount').toBigDecimal(), 'fee': XmlUtil.getValue(el, 'Fee').toBigDecimal(), 'tStatus' : XmlUtil.getValue(el, 'TStatus').toBigDecimal(),  'transactionType' : transType, 'orderNum' : XmlUtil.getValue(el, 'OrderNum')]
        if(trans.transactionType.value ==14)
            trans.amount = trans.amount.negate()
        data.add trans
    }

    return data
}



def statusMap = [1 : ProductStatus.SELL, 14 : ProductStatus.REFUND]
def compare = { first, second ->
    
    if(first.status!=second.status){
        return 'Ошибка статуса билета'
    }

    if(first.amount!= second.amount){
        return 'Ошибка в стоимости'
    }

}

def map = [:]
def productMap = [:]
def refundMap = [:]
def entityStorage = EntityStorage.get()
for(def index in allTickets){
    def bookingCtr = entityStorage.resolve(index.getSource())
    def booking = bookingCtr?.entity
    if(!booking)continue;
    
    def product = com.gridnine.xtrip.common.model.helpers.BookingHelper.findProduct(booking, index.navigationKey)
    for(def ticket in product.reservation.products){
        if(!(ticket instanceof RailwayProduct)){
            continue;
        }
        RailwayProduct railwayTicket = (RailwayProduct)ticket
        map[railwayTicket.systemNumber] = index.bookingNumber           
    }


    
    def pmap = null
    if(index.status==ProductStatus.SELL){
        pmap = productMap
    }
    else if(index.status==ProductStatus.REFUND){
        pmap = refundMap
    }

    def mm = pmap[index.bookingNumber];
    if(mm==null){
        mm = []
        pmap[index.bookingNumber] = mm  
    }
    mm.add index    
    if(pmap==refundMap){
        mm = productMap[index.bookingNumber]
        if(mm!=null && mm.contains(index)){
            mm.remove(index)
        }
    }
}

def createWrapper = {

    def wrapper = [:]
    if(!it)return wrapper
    def firstProduct = it[0]
    wrapper['ticketNumber'] = firstProduct.systemNumber
    wrapper['issueDate'] =  firstProduct.issueDate
    wrapper['status'] = firstProduct.status
    wrapper['routeLine'] = firstProduct.routeLine

    def amount = 0;
    def travellers = []
    def fee = 0;
    for(def product in it){
        amount += (product.equivalentTotalFare ? product.equivalentTotalFare : 0) 
        travellers.addAll product.travellers
        fee += product.vendorFeeValue ? product.vendorFeeValue : 0
    }   
    wrapper['amount'] = amount
    wrapper['travellers'] = TextUtil.join(',', travellers);
    wrapper['fee'] = fee;

    return wrapper;
}

def createTransWrapper = {
    def wrapper = [:]
    def firstTrans = it[0]
    
    wrapper['ticketNumber'] = firstTrans.orderNum
    def amount = 0
    def fee = 0
    for(def t in it){
        amount += t.amount
        fee += t.fee        
    }
    wrapper['amount'] = amount
    wrapper['status'] = statusMap[firstTrans.transactionType.value]
    wrapper['fee'] = fee
    wrapper['travellers'] = ''
    wrapper['routeLine'] = ''
    wrapper['issueDate'] = firstTrans.confirmDate
    
    
    return wrapper
}


//def connector = Environment.getPublished(UfsConnector.class);
//def params = new RzdTransListParameters();
//params.setDate parameters['key-report-params']['periodBegin']
RzdTransListResult response = getTransList(parameters['key-report-params']['periodBegin'])

for (Message message : response.messages) {
    String messageStr = message.message?.toString()
    String details = message.details
    warn("res_mes: ${messageStr} - ${details}")
}

Collection transactions = response.getTrans()//getData('/usr/local/midoffice/temp/server/rzd-trace/ufs/2013/12/26/1388045971947-TransList.xml')//

def ufsTranses = [:]
def ufsRefunds = [:]
for(def trans in transactions){
    if(trans.tStatus!=0)
        continue
    def ufsMap = (statusMap[trans.transactionType.value]==ProductStatus.REFUND) ? ufsRefunds : ufsTranses;

    def mm =ufsMap[trans.orderNum]
    if(!mm){
        mm = []
        ufsMap[trans.orderNum] = mm
    }
    mm.add trans
}

def maps = [ufsRefunds, ufsTranses]
def notFoundInMom = []
for(def ufsMap in maps)
for(def tEntry in ufsMap){
    def orderNum = tEntry.key
    def transes = tEntry.value
    def transWrapper = createTransWrapper(transes)

    def bookingNumber = map[orderNum]
    if(!bookingNumber){
        notFoundInMom.add transes
        continue
    }
        
    def pmap = transWrapper.status==ProductStatus.REFUND ? refundMap : productMap
    def productList = pmap[bookingNumber]
    if(productList==null){
        pmap = transWrapper.status==ProductStatus.REFUND ? productMap : refundMap
        productList = pmap[bookingNumber];
    }
    def wrapper = createWrapper(productList)
    def message = compare(wrapper, transWrapper);

    nextRow()
    text(wrapper.ticketNumber, 'textData')
    nextColumn();
    date(wrapper.issueDate, 'dateData')
    nextColumn()
    text(wrapper.routeLine, 'textData')
    nextColumn()
    text(wrapper.travellers, 'textData')    
    nextColumn()
    text(wrapper.status.toString(), 'textData')     
    nextColumn();
    text(transWrapper.status.toString(), 'textData')
    nextColumn()
    number(wrapper.amount, 'numberData')
    nextColumn()
    number(transWrapper.amount, 'numberData')
    nextColumn()
    number(wrapper.fee, 'numberData')
    nextColumn()
    number(transWrapper.fee, 'numberData')
    nextColumn()
    text(message!=null ? message : 'OK' , message!=null ? 'error' : 'success')

    pmap.remove bookingNumber
}


productMap.putAll refundMap
productMap.each {

    if(it==null)
        return;

    nextRow()
    def wrapper = createWrapper(it.value)   
    text(wrapper.ticketNumber, 'textData')
    nextColumn();
    date(wrapper.issueDate, 'dateData')
    nextColumn()
    text(wrapper.routeLine, 'textData')
    nextColumn()
    text(wrapper.travellers, 'textData')    
    nextColumn()
    text(wrapper.status?.toString(), 'textData')        
    nextColumn();
    text('', 'textData')
    nextColumn()
    number(wrapper.amount, 'numberData')
    nextColumn()
    text('', 'textData')
    nextColumn()
    number(wrapper.fee, 'numberData')
    nextColumn()
    text('', 'textData')
    nextColumn()
    text('Билет не найден в УФС', 'error' )

}

notFoundInMom.each{
    if(it==null)
        return;

    def wrapper = createTransWrapper(it)

    nextRow()   
    text(wrapper.ticketNumber, 'textData')
    nextColumn();
    text('', 'textData')
    nextColumn()
    text('', 'textData')
    nextColumn()
    text('', 'textData')
    nextColumn()
    text('', 'textData')
    nextColumn()
    text(wrapper.status.toString(), 'textData')
    nextColumn();
    text('', 'textData')
    nextColumn()
    number(wrapper.amount, 'numberData')
    nextColumn()
    text('', 'textData')
    nextColumn()
    text('', 'textData')
    nextColumn()
    text('Билет не найден в мидофисе', 'error' )
}
