import com.gridnine.xtrip.common.Environment
import com.gridnine.xtrip.common.l10n.model.LocaleHelper
import com.gridnine.xtrip.common.model.EntityContainer
import com.gridnine.xtrip.common.model.EntityReference
import com.gridnine.xtrip.common.model.booking.BlankType
import com.gridnine.xtrip.common.model.booking.ProductStatus
import com.gridnine.xtrip.common.model.booking.TransportationType
import com.gridnine.xtrip.common.model.booking.air.Tax
import com.gridnine.xtrip.common.model.dict.*
import com.gridnine.xtrip.common.model.entity.EntityStorage
import com.gridnine.xtrip.common.model.helpers.ProfileHelper
import com.gridnine.xtrip.common.model.profile.Communication
import com.gridnine.xtrip.common.model.profile.GdsReference
import com.gridnine.xtrip.common.model.profile.Organization
import com.gridnine.xtrip.common.model.profile.Person
import com.gridnine.xtrip.common.model.system.Metadata
import com.gridnine.xtrip.common.model.system.MetadataKey
import com.gridnine.xtrip.common.model.system.MetadataKeyDescriptor
import com.gridnine.xtrip.common.model.system.PaymentType
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportParameters
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportTicket
import com.gridnine.xtrip.common.util.MiscUtil

//CREATING STYLES
createStyle(name: 'title', h_alignment: 'CENTER', v_alignment: 'CENTER')
createStyle(name: 'titleH1',fontBold: true, fontHeight: 12, parent: 'title')
createStyle(name: 'titleH2',fontBold: false,h_alignment: 'LEFT', fontHeight: 9, parent: 'title')
createStyle(name: 'header', fontBold: true,  h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight:9, leftBorder:'MEDIUM', rightBorder:'MEDIUM', topBorder:'MEDIUM', bottomBorder:'MEDIUM', wrapText: true)
createStyle(name: 'columnHeader', fontHeight: 9, parent: 'header')
createStyle(name: 'rowHeader',fontHeight: 9, h_alignment: 'LEFT', wrapText: true, parent: 'titleH2')
createStyle(name: 'data', h_alignment: 'LEFT', v_alignment: 'CENTER', fontHeight: 7)
createStyle(name: 'textData', parent: 'data')
createStyle(name: 'textDataBold', parent: 'data',fontBold: true)
createStyle(name: 'dateData', format: 'm/d/yy', parent: 'data')
createStyle(name: 'dateDataBold', format: 'm/d/yy', parent: 'data',fontBold: true)
createStyle(name: 'numberData', h_alignment: 'RIGHT', format: '#,##0.00', parent: 'data')
createStyle(name: 'numberDataBold', h_alignment: 'RIGHT', format: '#,##0.00', parent: 'data',fontBold: true)
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: 'statusGroupTitle', parent: 'header', h_span: 4, fontBold: true)
createStyle(name: 'statusGroupNumber',parent: 'header', h_span: 2)
createStyle(name: 'subagencyGroupTitle', parent: 'statusGroupTitle')
createStyle(name: 'GroupNumber',parent: 'header', v_span: 3)
createStyle(name: 'totalTitle', parent: 'subagencyGroupTitle')
createStyle(name: 'totalNumber',parent: 'totalTitle', h_span: 1)

//ADDITIONAL FUNCTIONS
def notNullBigDec = {BigDecimal it ->
    return it == null ? BigDecimal.ZERO : it
}

def getOrganization = { EntityReference<Organization> organizationReference ->
    EntityContainer<Organization> ecO = EntityStorage.get().resolve(organizationReference)
    if (ecO != null) {
        return ecO.entity
    } else {
        return null
    }
}

def createTitle = { EntityReference<Organization> organizationReference ->
    columnWidth(28)
    setStyle('titleH1')
    3.times{nextColumn()}
    rowHeight(30)

    Organization org = getOrganization(organizationReference)
    def agencyKod = ''
    def agencyName = ''
    if (org != null) {
        agencyName = org.fullName
        def tchCode = ''
        def irCode = ''
        for(Metadata md : org.metadata) {
            MetadataKeyDescriptor mdKd = Environment.getPublished(DictionaryCache.class).resolveReference(md.key)
            if (mdKd != null) {
                if(MetadataKey.KEY_IR_AGENCY_CODE.name().equals(mdKd.code)) {
                    irCode = md.value.toString()
                }
            }
        }
        agencyKod = irCode
    }

    text('Реестр документов для а/к ЗАО АК ИрАэро в ' + agencyName + ' Код - ' + agencyKod, 'title')
    //metadata
    rowHeight(13);
    int scw = 10
    //header
    2.times{nextRow()}
    3.times{nextColumn()}
    rowHeight(13);
    setStyle('titleH1')

    text(parameters.REPORT_PERIOD + ' код РД', 'metadataValue');

    nextRow()
    3.times{nextColumn()}
    rowHeight(13);
}

def createEnd = { EntityReference<Organization> organizationReference ->
    def mainAccountant  = ''
    def performer       = ''
    def phone           = ''

    Organization org = getOrganization(organizationReference)
    org?.communications?.any { Communication comm ->
        if (comm.type == CommunicationType.WORK_PHONE || comm.type == CommunicationType.AGENCY) {
            phone = comm.sense
        }
    }
    EntityReference<Person> erP = ProfileHelper.getManager(organizationReference, ManagerType.CHIEF_ACCOUNTANT, new Date())
    if(erP != null){
        EntityContainer<Person> ecP = EntityStorage.get().resolve(erP)
        mainAccountant = ProfileHelper.getFullName(ecP.entity,LocaleHelper.getCurrentLocale(), false)
    }

    2.times{nextRow()}
    text('Главный бухгалтер','textDataBold')
    nextColumn();text(mainAccountant,'textDataBold')

    nextRow()
    text('Исполнитель','textDataBold')
    nextColumn();text(performer,'textDataBold')

    nextRow()
    text('Телефон','textDataBold')
    nextColumn();text(phone,'textDataBold')
}

def createHeader = {
    int scw = 10
    rowHeight(40)
    columnWidth(1.7*scw)
    text('')
    setStyle('header')
    rowHeight(50)
    nextColumn();columnWidth(1.5*scw);text('Документ')
    nextColumn();columnWidth(1.5*scw);text('Тариф')
    nextColumn();columnWidth(scw);text('Воз-ние')
    nextColumn();columnWidth(scw);text('Такса')
    nextColumn();columnWidth(1.5*scw);text('Пассажир')
    nextColumn();columnWidth(scw);text('Маршрут')
    nextColumn();columnWidth(scw);text('Дата продажи')
    nextColumn();columnWidth(scw);text('Дата вылета')
    nextColumn();columnWidth(0.5*scw);text('Кассир')
    nextColumn();columnWidth(0.7*scw);text('Тип тарифа')
    nextColumn();columnWidth(0.5*scw);text('Форма оплаты')
    nextColumn();columnWidth(0.7*scw);text('АВС')
}

def cellFill = { value ->
    if (value != null) {
        if (value instanceof Number) {
            number(value,'numberData')
        } else if (value instanceof Date) {
            date(value,'dateData')
        } else {
            text(value, 'textData')
        }
    }
}

def cellFillBold = { value ->
    if (value != null) {
        if (value instanceof Number) {
            number(value,'numberDataBold')
        } else if (value instanceof Date) {
            date(value,'dateDataBold')
        } else {
            text(value, 'textDataBold')
        }
    }
}

def totalRevenue = { BigDecimal tariffe, BigDecimal vos_nie, BigDecimal fee ->
    nextRow()
    cellFillBold('Итог выручка - ')
    nextColumn();
    nextColumn(); cellFillBold(tariffe)
    nextColumn(); cellFillBold(vos_nie)
    nextColumn(); cellFillBold(fee)
}

def totalStatus = { String status, BigDecimal tariffe, BigDecimal vos_nie, BigDecimal fee ->
    nextRow()
    cellFillBold('Итог ')
    nextColumn(); cellFillBold(status)
    nextColumn(); cellFillBold(tariffe)
    nextColumn(); cellFillBold(vos_nie)
    nextColumn(); cellFillBold(fee)
}

def totalTransportationType = { String transportationType, BigDecimal tariffe, BigDecimal vos_nie, BigDecimal fee ->
    nextRow()
    cellFillBold('Итог ')
    nextColumn(); cellFillBold(transportationType)
    nextColumn(); cellFillBold(tariffe)
    nextColumn(); cellFillBold(vos_nie)
    nextColumn(); cellFillBold(fee)
}

def totalPaymentsType = { String paymentsType, BigDecimal tariffe, BigDecimal vos_nie, BigDecimal fee ->
    nextRow()
    cellFillBold('Итог ')
    nextColumn(); cellFillBold(paymentsType)
    nextColumn(); cellFillBold(tariffe)
    nextColumn(); cellFillBold(vos_nie)
    nextColumn(); cellFillBold(fee)
}

//FOR FILL TABLE
def getDocument         = { AirTicketsTemplateReportTicket ticket ->
    BlankType blankType = Environment.getPublished(DictionaryCache.class).resolveReference(ticket.blankType)
    return blankType.name + ' ' +ticket.ticketNumber;
}
def getTariff           = { AirTicketsTemplateReportTicket ticket ->
    res = ticket.equivalentFare != null ? ticket.equivalentFare : BigDecimal.ZERO
    if (ticket.mcoCategory == MCOCategory.PENALTY && res == BigDecimal.ZERO){
        res = ticket.penalty != null ? ticket.penalty : BigDecimal.ZERO
    } else if (MCOCategory.PENALTY != ticket.mcoCategory && MCOCategory.REBOOKING != ticket.mcoCategory) {
        res = MiscUtil.sum(res,ticket.penalty)
    }
    return res
}
def getVoz_nie          = { AirTicketsTemplateReportTicket ticket -> return ticket.vendorCommissionValue != null ? ticket.vendorCommissionValue : BigDecimal.ZERO }
def getFee              = { AirTicketsTemplateReportTicket ticket ->
    BigDecimal result = BigDecimal.ZERO
    boolean includeZZTax = parameters['includeZZTax']

    if (ticket.taxesSum && ticket.ruTaxAmount) {
        result = includeZZTax
                ? ticket.taxesSum : ticket.taxesSum.subtract(ticket.ruTaxAmount)
    } else if (ticket.taxesSum) {
        result = ticket.taxesSum
    } else {
        ticket.taxes.each { Tax tax ->
            if (tax.equivalentAmount && (includeZZTax || "ZZ" != tax.code)) {
                result = result.add(tax.equivalentAmount)
            }
        }
    }
    return result
}

def getPassander        = { AirTicketsTemplateReportTicket ticket ->
    if(ticket.travellerPassportType != null && ticket.travellerPassportNumber != null){
        return ticket.travellerPassportType.toString() + ticket.travellerPassportNumber + ' ' + ticket.travellerName
    } else {
        return ticket.travellerName
    }
}
def getRoute            = { AirTicketsTemplateReportTicket ticket -> return ticket.routeLineWithFlightNum }
def getDateOfSale       = { AirTicketsTemplateReportTicket ticket -> return ticket.issueDate }
def getDepartureDate    = { AirTicketsTemplateReportTicket ticket -> return ticket.departureDate }
def getAgentCode        = { AirTicketsTemplateReportTicket ticket ->
    def agentCode = ticket.agentCode
    EntityContainer<Person> ecP = EntityStorage.get().resolve(ticket.agent)
    if(ecP != null){
        ecP.entity.gdsReferences.each {GdsReference gdsRef ->
            if (gdsRef.gdsName == GdsName.SIRENA) {
                agentCode = gdsRef.reference
                agentCode = agentCode ? agentCode.substring(agentCode.length() - 2, agentCode.length()) : agentCode
            }
        }
    }
    return agentCode
}
def getTypeOfTariff     = { AirTicketsTemplateReportTicket ticket ->  return ticket.fareBasisLine }
def getFormOfPayment    = { AirTicketsTemplateReportTicket ticket ->
    return ticket.paymentTypes.contains(PaymentType.CASH) ? 'НА' : ticket.paymentTypes.contains(PaymentType.INVOICE) ? 'ПП' : ticket.paymentTypes.contains(PaymentType.CREDIT_CARD) || ticket.paymentTypes.contains(PaymentType.CREDIT_CARD_AGENCY) ? 'ПК' : 'ДР'
}
def getAbc              = {  AirTicketsTemplateReportTicket ticket ->
    //        EntityContainer<Organization> ecO = EntityStorage.get().resolve(ticket.supplier)
    //        println 'fName = ' + ecO.entity.fullName
    def irAgencyCode = ''
    def tchAgencyCode = ''
    EntityContainer<Organization> ecO = EntityStorage.get().resolve(ticket.agency)
    if (ecO != null) {
        for(Metadata md : ecO.entity.metadata) {
            MetadataKeyDescriptor mdKd = Environment.getPublished(DictionaryCache.class).resolveReference(md.key)
            if (mdKd != null) {
                if(MetadataKey.KEY_IR_AGENCY_CODE.name().equals(mdKd.code)) {
                    irAgencyCode = md.value.toString()
                }
            }
        }
        return irAgencyCode
    }
}

//SORT TICKETS
def getTransportatioTypeInt = {
    if(it == TransportationType.DOMESTIC) return 1
    else if(it == TransportationType.INTERNATIONAL || it == TransportationType.COMBINED) return 2
    return 3
}

def getPaymentTypeInt = { List<PaymentType> list ->
    if(list.any { return (it == PaymentType.CASH) || (it == PaymentType.INVOICE) }) return 1
    else if(list.any { return (it == PaymentType.CREDIT_CARD) || (it == PaymentType.CREDIT_CARD_AGENCY) }) return 2
    return 3
}

def getStatusInt = { ProductStatus status ->
    if (status == ProductStatus.SELL)           return 1
    else if (status == ProductStatus.REFUND)    return 2
    else if (status == ProductStatus.EXCHANGE)  return 3
    return 4
}

def getProdCatTypeInt = { ProductCategory prodCategory ->
    if(prodCategory == ProductCategory.MCO) return 1
    return 2
}

def getMCOCatTypeInt = { MCOCategory mcoCategory ->
    if (mcoCategory == null){
        return -1
    }
    return mcoCategory.ordinal()
}

allTickets.sort{AirTicketsTemplateReportTicket a, AirTicketsTemplateReportTicket b ->
    int res = getPaymentTypeInt(a.paymentTypes) <=> getPaymentTypeInt(b.paymentTypes)
    if (res == 0) {
        res = getTransportatioTypeInt(a.transportationType) <=> getTransportatioTypeInt(b.transportationType)
        //if (res == 0) {
        //    res = a.vendorCommissionRate <=> b.vendorCommissionRate
            if (res == 0) {
                if (a.status == b.status) {
                    if(a.productCategory == b.productCategory){
                        res = getMCOCatTypeInt(a.mcoCategory) <=> getMCOCatTypeInt(b.mcoCategory)
                        if (res == 0){
                            if (a.ticketNumber != null && b.ticketNumber != null){
                                return a.ticketNumber <=> b.ticketNumber
                            } else {
                                return 0
                            }
                        } else {
                            return res
                        }
                    } else {
                        return getProdCatTypeInt(a.productCategory) <=> getProdCatTypeInt(b.productCategory)
                    }
                } else {
                    return getStatusInt(a.status) <=> getStatusInt(b.status)
                }
            } else {
                return res
            }
        //} else {
        //    return res
        //}
    } else {
        return res
    }

    return res
}

//REPORT
def getPaymentTypeGroupString = {List<PaymentType> list ->
    String res = ''
    switch(getPaymentTypeInt(list)){
        case 1:
            res = 'НАЛ и КР'
            break
        case 2:
            res = 'ВЗ'
            break
        case 3:
            res = 'ДР'
            break
        default:
            break
    }

    return res
}
def getTransportatioTypeString = {
    if(it == TransportationType.DOMESTIC)           return 'ВВЛ'
    else if(it == TransportationType.INTERNATIONAL) return 'МВЛ'
    return 'ДР'
}

page{'Реестр'}{
    //title
    warn 'report version=' + '0.1.0'
    AirTicketsTemplateReportParameters airTicketParams = parameters.params
    EntityReference<Organization> org = airTicketParams.agency

    createTitle(org)

    BigDecimal sellInfo     = null

    int amountTickets = 0

    groups{AirTicketsTemplateReportTicket superTickets1 -> getPaymentTypeGroupString(superTickets1.paymentTypes)}{
        //if(!it.equals('ДР')){

            nextRow()
            nextRow()
            cellFill('Продажа ' + it)

            BigDecimal tariffePT    = BigDecimal.ZERO
            BigDecimal voz_niePT    = BigDecimal.ZERO
            BigDecimal feePT        = BigDecimal.ZERO

            groups{AirTicketsTemplateReportTicket superTickets2 -> getTransportatioTypeString(superTickets2.transportationType)}{
                //if(!it.equals('ДР')){

                    nextRow()
                    3.times{nextColumn()}
                    cellFillBold(it)
                    nextRow()
                    createHeader()

                    BigDecimal tariffeTT    = BigDecimal.ZERO
                    BigDecimal voz_nieTT    = BigDecimal.ZERO
                    BigDecimal feeTT        = BigDecimal.ZERO

                    Boolean nextRowData = false

                    groups{AirTicketsTemplateReportTicket superTickets4 -> superTickets4.status.toString()}{
                        nextRow()
                        rowHeight(12)
                        3.times{nextColumn()}
                        cellFillBold(it)

                        nextRow()
                        def table = []

                        def tariffeTicketsStatus = BigDecimal.ZERO
                        def voz_nieTicketsStatus = BigDecimal.ZERO
                        def feeTicketsStatus = BigDecimal.ZERO

                        groups{AirTicketsTemplateReportTicket superTickets5 -> superTickets5.productCategory.toString()}{
                            def prodCat = it

                            if(it.equals(ProductCategory.MCO.toString())){
                                groups{AirTicketsTemplateReportTicket superTickets5 -> superTickets5.mcoCategory.toString()}{
                                    cellFill(prodCat + ' ' + it)
                                    def tariffeTickets = BigDecimal.ZERO
                                    def voz_nieTickets = BigDecimal.ZERO
                                    def feeTickets = BigDecimal.ZERO

                                    tickets { AirTicketsTemplateReportTicket ticket ->

                                        BigDecimal tariffe = getTariff(ticket)
                                        BigDecimal voz_nie = getVoz_nie(ticket)
                                        BigDecimal fee     = getFee(ticket)

                                        tariffeTickets = tariffeTickets.add(tariffe)
                                        voz_nieTickets = voz_nieTickets.add(voz_nie)
                                        feeTickets     = feeTickets.add(fee)
                                        amountTickets++
                                        table.add([
                                            getDocument(ticket),
                                            tariffe,
                                            voz_nie,
                                            fee,
                                            getPassander(ticket),
                                            getRoute(ticket),
                                            getDateOfSale(ticket),
                                            getDepartureDate(ticket),
                                            getAgentCode(ticket),
                                            getTypeOfTariff(ticket),
                                            getFormOfPayment(ticket),
                                            getAbc(ticket)
                                        ])
                                    }

                                    table.each { row ->
                                        if(nextRowData.value){
                                            nextRow()
                                        } else {
                                            nextRowData = true
                                        }
                                        rowHeight(12)
                                        nextColumn()

                                        row.each {
                                            cellFill(it)
                                            nextColumn()
                                        }
                                    }
                                    nextRowData = false
                                    table = []
                                    totalRevenue(tariffeTickets,voz_nieTickets,feeTickets)
                                    nextRow()

                                    tariffeTicketsStatus = tariffeTicketsStatus.add(tariffeTickets)
                                    voz_nieTicketsStatus = voz_nieTicketsStatus.add(voz_nieTickets)
                                    feeTicketsStatus     = feeTicketsStatus.add(feeTickets)
                                }

                                totalStatus(it,tariffeTicketsStatus,voz_nieTicketsStatus,feeTicketsStatus)
                                nextRow()
                                nextRow()
                            } else {
                                cellFill(prodCat)
                                def tariffeTickets = BigDecimal.ZERO
                                def voz_nieTickets = BigDecimal.ZERO
                                def feeTickets = BigDecimal.ZERO

                                tickets { AirTicketsTemplateReportTicket ticket ->

                                    BigDecimal tariffe = getTariff(ticket)
                                    BigDecimal voz_nie = getVoz_nie(ticket)
                                    BigDecimal fee     = getFee(ticket)

                                    tariffeTickets = tariffeTickets.add(tariffe)
                                    voz_nieTickets = voz_nieTickets.add(voz_nie)
                                    feeTickets     = feeTickets.add(fee)
                                    amountTickets++
                                    table.add([
                                        getDocument(ticket),
                                        tariffe,
                                        voz_nie,
                                        fee,
                                        getPassander(ticket),
                                        getRoute(ticket),
                                        getDateOfSale(ticket),
                                        getDepartureDate(ticket),
                                        getAgentCode(ticket),
                                        getTypeOfTariff(ticket),
                                        getFormOfPayment(ticket),
                                        getAbc(ticket)
                                    ])
                                }

                                table.each { row ->
                                    if(nextRowData.value){
                                        nextRow()
                                    } else {
                                        nextRowData = true
                                    }
                                    rowHeight(12)
                                    nextColumn()

                                    row.each {
                                        cellFill(it)
                                        nextColumn()
                                    }
                                }

                                nextRowData = false
                                table = []
                                totalRevenue(tariffeTickets,voz_nieTickets,feeTickets)
                                nextRow()

                                tariffeTicketsStatus = tariffeTicketsStatus.add(tariffeTickets)
                                voz_nieTicketsStatus = voz_nieTicketsStatus.add(voz_nieTickets)
                                feeTicketsStatus     = feeTicketsStatus.add(feeTickets)
                            }
                        }
                        totalStatus(it,tariffeTicketsStatus,voz_nieTicketsStatus,feeTicketsStatus)
                        nextRow()
                        tariffeTT = it.equals(ProductStatus.REFUND.toString()) ? tariffeTT.subtract(tariffeTicketsStatus) : tariffeTT.add(tariffeTicketsStatus)
                        voz_nieTT = it.equals(ProductStatus.REFUND.toString()) ? voz_nieTT.subtract(voz_nieTicketsStatus) : voz_nieTT.add(voz_nieTicketsStatus)
                        feeTT     = it.equals(ProductStatus.REFUND.toString()) ? feeTT.subtract(feeTicketsStatus) : feeTT.add(feeTicketsStatus)
                    }

                    tariffePT   = tariffePT.add(tariffeTT)
                    voz_niePT   = voz_niePT.add(voz_nieTT)
                    feePT       = feePT.add(feeTT)
                    totalTransportationType(it,tariffeTT,voz_nieTT,feeTT)
                //}
            }
            totalPaymentsType(it,tariffePT,voz_niePT,feePT)
        //}
    }

    createEnd(org)
}