import com.gridnine.xtrip.common.l10n.model.LocaleHelper
import com.gridnine.xtrip.common.model.EntityReference
import com.gridnine.xtrip.common.model.booking.OperationBatch
import com.gridnine.xtrip.common.model.dict.CodeSystem
import com.gridnine.xtrip.common.model.dict.CurrencyInfo
import com.gridnine.xtrip.common.model.dict.DictionaryCache
import com.gridnine.xtrip.common.model.helpers.DictHelper
import com.gridnine.xtrip.common.model.profile.Organization
import com.gridnine.xtrip.common.model.system.PaymentType
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportParameters
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportSegmentTariff
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportTicket
import com.gridnine.xtrip.common.util.MiscUtil
import com.gridnine.xtrip.common.util.TextUtil

import java.text.SimpleDateFormat

//CREATING STYLES
createStyle(name: 'baseStyle', fontBold: false,  h_alignment: 'LEFT', v_alignment: 'CENTER', fontHeight:8, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN')
createStyle(name: 'baseStyleBold', parent: 'baseStyle', fontBold: true)
createStyle(name: 'baseStyleClearBold', fontBold: true, h_alignment: 'LEFT', v_alignment: 'CENTER', fontHeight:8)
createStyle(name: 'headStyle', fontBold: true,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:12)
createStyle(name: 'headStyle12', parent: 'headStyle', fontHeight:10)
createStyle(name: 'headerStyle', parent: 'baseStyle', h_alignment: 'CENTER')
createStyle(name: 'style', fontBold: false, fontHeight: 8, parent: 'baseStyle')
createStyle(name: 'dateData', format: 'm/d/yy', parent: 'style',  h_alignment: 'LEFT', v_alignment: 'CENTER')
createStyle(name: 'numberData', format: '#,##0.00', parent: 'style',  h_alignment: 'RIGHT', v_alignment: 'CENTER')
createStyle(name: 'numberDataClearBold', format: '#,##0.00',  h_alignment: 'RIGHT', v_alignment: 'CENTER', fontHeight: 8, fontBold: true)
createStyle(name: 'divide', topBorder:'THIN')

class Formula {
    String formula
    Formula(){}
    Formula(String formula) {
        this.formula = formula
    }

    static Formula getSumFormulaByRow (String start, String end) {
        return new Formula('SUM(' + start + ':' + end + ')')
    }
}

def cellFill(Object value) {
    if (value != null) {
        if (value instanceof Number) {
            number(value, 'numberDataClearBold')
        } else if (value instanceof Date) {
            date(value,'dateData')
        } else if (value instanceof Formula){
            formula(value.formula,'numberDataClearBold')
        } else {
            text(value, 'baseStyle')
        }
    } else {
        text('', 'baseStyle')
    }
}

def reportHeader () {

    def subagencyName = parameters['SUBAGENCY_NAME']
    subagencyName = subagencyName ? subagencyName : ''
    def agencyName = parameters['AGENCY_NAME']
    agencyName = agencyName ? agencyName : ''
    def contactNumber = parameters['contract_number']
    contactNumberToString = contactNumber ? contactNumber.toString() : '___'

    def scw = 12

    def contractDateFrom = parameters['contract_date_from']
    def contractDateFromToString =
            contractDateFrom ? new SimpleDateFormat('dd.MM.yyyy').format(contractDateFrom).toString()
                             : '__________'

    rowHeight(1.2*scw)
    columnWidth(scw)
    text('Реестр продаж и начисления', 'headStyle', 9, 1)
    nextRow()
    text('между ' + subagencyName + ' и ' + agencyName, 'headStyle12', 9, 1)
    nextRow()
    text('по начислению комиссионного вознаграждения', 'headStyle12', 9, 1)
    nextRow()
    text('согласно договору № ' + contactNumberToString + ' от ' + contractDateFromToString + ' года', 'headStyle12', 9, 1)
    nextRow()
    text('в период ' + parameters['REPORT_PERIOD'], 'headStyle12', 9, 1)
    2.times{nextRow()}
}

def printColumnHeader(String str, Number width) {
    if(width != 0) {
        columnWidth(width)
    }
    text(str, 'baseStyleBold')
    nextColumn()
}

def reportTitle() {
    rowHeight(30)
    CurrencyInfo currencyInfo = DictHelper.getCurrencyInfoByAnyCode(DictHelper.getLocalCurrencyCode())
    def currency = currencyInfo?.toString(LocaleHelper.RU_LOCALE)
    printColumnHeader('№\nп/п', 6)
    printColumnHeader('вал-р', 20)
    printColumnHeader('дата оп.', 10)
    printColumnHeader('№ документа', 15)
    printColumnHeader('АК', 5)
    printColumnHeader('ФО', 29)
    printColumnHeader('Базовая сумма\nдля расчета, ' + currency, 14)
    printColumnHeader('Вознаграждение\nсубагента, ' + currency, 14)
    printColumnHeader('Ком. агентства', 14)
}

def addTicketsToMapPaymentType (Map<PaymentType, Map<String, List<AirTicketsTemplateReportTicket>>> ticketsPaymantType,
                                AirTicketsTemplateReportTicket ticket){

    def airlineNumber = DictionaryCache.get().resolveReference(ticket.validatingCarrier)?.getAirlineNumber()
    airlineNumber = airlineNumber ? airlineNumber : ''

    PaymentType paymentType = ticket.subagentPaymentTypes.first()

    Map<String, List<AirTicketsTemplateReportTicket>> paymentTypeToTickets = ticketsPaymantType.get(paymentType)
    if(!paymentTypeToTickets){
        paymentTypeToTickets = new HashMap<String, List<AirTicketsTemplateReportTicket>>()
        ticketsPaymantType.put(paymentType, paymentTypeToTickets)
    }

    List<AirTicketsTemplateReportTicket> tickets = paymentTypeToTickets.get(airlineNumber)
    if(!tickets){
        tickets = new ArrayList<AirTicketsTemplateReportTicket>()
        tickets.add(ticket)
        paymentTypeToTickets.put(airlineNumber, tickets)
    } else {
        tickets.add(ticket)
    }
}

def reportBody() {
    int count = 0
    def ticketsMap = new HashMap<PaymentType, Map<String, List<AirTicketsTemplateReportTicket>>>()
    allTickets.each { AirTicketsTemplateReportTicket ticket ->

        if (!ticket.subagentPaymentTypes.contains(PaymentType.PTA)) {

            addTicketsToMapPaymentType(ticketsMap, ticket)
        }
    }

    if (!ticketsMap.isEmpty()){
        nextRow()
        count = fillTable(ticketsMap)
        if (count > 0) {
            text('Итого:', 'baseStyleClearBold', 2, 1)
            6.times { nextColumn() }
            3.times {
                cellFill(Formula.getSumFormulaByRow(cellIndex(-count, 0), cellIndex(-1, 0)))
                nextColumn()
            }
            nextRow()
        }
        9.times {
            text('', 'divide')
            nextColumn()
        }
    }
}

def sortTableByCodeVariant(List<AirTicketsTemplateReportTicket> listTicket){
    def validatingCarrierToTickets = new HashMap<String, Map<BigDecimal, List<AirTicketsTemplateReportTicket>>>()

    listTicket.each { AirTicketsTemplateReportTicket ticket ->
        def validatingCarrierCode = null
        def ticketCarrier = DictionaryCache.get().resolveReference(ticket.validatingCarrier)
        if (ticketCarrier) {
            validatingCarrierCode = DictHelper.getCodeVariant(ticketCarrier, CodeSystem.CRT, CodeSystem.IATA)
        }

        if (TextUtil.isBlank(validatingCarrierCode)){
            validatingCarrierCode = ''
        }

        def rate = ticket.subagentCommissionRate ? ticket.subagentCommissionRate : BigDecimal.ZERO

        Map<BigDecimal, List<AirTicketsTemplateReportTicket>> commissionToTickets = validatingCarrierToTickets.get(validatingCarrierCode)
        if (!commissionToTickets) {
            commissionToTickets = new HashMap<>()
            validatingCarrierToTickets.put(validatingCarrierCode, commissionToTickets)
        }

        List<AirTicketsTemplateReportTicket> tickets = null
        commissionToTickets.each { BigDecimal key, List<AirTicketsTemplateReportTicket> value ->
            if (MiscUtil.equals(key, rate)) {
                tickets = value
                return
            }
        }
        if (!tickets) {
            tickets = new ArrayList<>()
            commissionToTickets.put(rate, tickets)
        }

        tickets.add(ticket)

    }
    return validatingCarrierToTickets
}

def fillTable(Map<PaymentType, Map<String, List<AirTicketsTemplateReportTicket>>> mapTickets) {

    int count = 0
    int itemNumber = 0
    mapTickets.each { PaymentType fo, Map<String, List<AirTicketsTemplateReportTicket>> airlineNumberTickets ->//kp
        airlineNumberTickets.each { String airlineNumber, List<AirTicketsTemplateReportTicket> listTicket ->//421
            sortTableByCodeVariant(listTicket).each { String codeVariant, Map<BigDecimal, List<AirTicketsTemplateReportTicket>> cvTickets ->//c7
                cvTickets.each { BigDecimal rate, List<AirTicketsTemplateReportTicket> tickets ->
                    tickets.each { AirTicketsTemplateReportTicket ticket ->

                        BigDecimal amount = BigDecimal.ZERO
                        BigDecimal subagentTariff = BigDecimal.ZERO
                        BigDecimal vendorTariff = BigDecimal.ZERO

                        if(ticket.operationBatch == OperationBatch.REFUND){
                            amount = MiscUtil.sub(amount, ticket.equivalentFare)
                            ticket.segmentTariffs.each { AirTicketsTemplateReportSegmentTariff tariff ->
                                subagentTariff =  MiscUtil.sub(subagentTariff, MiscUtil.negate(tariff.subagentCommissionValue))
                                vendorTariff = MiscUtil.sub(vendorTariff, MiscUtil.negate(tariff.vendorCommissionValue))
                            }
                        } else {
                            amount = MiscUtil.sum(amount, ticket.equivalentFare)
                            ticket.segmentTariffs.each { AirTicketsTemplateReportSegmentTariff tariff ->
                                subagentTariff = MiscUtil.sum(subagentTariff, tariff.subagentCommissionValue)
                                vendorTariff = MiscUtil.sum(vendorTariff, tariff.vendorCommissionValue)
                            }
                        }

                        rowHeight(1.2 * 12)
                        number(++itemNumber, 'baseStyle')
                        nextColumn()
                        text(ticket.validator)
                        nextColumn()
                        date(ticket.issueDate, 'dateData')
                        nextColumn()
                        text(ticket.blankOwnerNumber + ' ' + ticket.ticketNumber)
                        nextColumn()
                        text(codeVariant, 'baseStyle')
                        nextColumn()
                        text(fo.toString(LocaleHelper.RU_LOCALE), 'baseStyle')
                        nextColumn()
                        number(amount, 'numberData')
                        nextColumn()
                        number(subagentTariff, 'numberData')
                        nextColumn()
                        number(vendorTariff, 'numberData')
                        nextRow()
                        count++
                    }
                }
            }
        }
    }
    return count
}

page{"Реестр продаж и начисления"} {
    warn 'report version = ' + '0.1.0'

    AirTicketsTemplateReportParameters airTicketParams = parameters.params
    EntityReference<Organization> orgRef = airTicketParams.agency

    reportHeader()
    reportTitle()
    reportBody()
}