
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.air.Tax;
import com.gridnine.xtrip.common.model.dict.CommunicationType;
import com.gridnine.xtrip.common.model.dict.DictionaryCache;
import com.gridnine.xtrip.common.model.dict.GdsName;
import com.gridnine.xtrip.common.model.dict.ManagerType;
import com.gridnine.xtrip.common.model.dict.MCOCategory;
import com.gridnine.xtrip.common.model.dict.ProductCategory;
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)

createStyle(name: 'titleH0',fontBold: true, fontHeight: 12, parent: 'title', h_span :3,fontWidth: 20)
createStyle(name: 'smallTitle',fontBold: true, h_span: 1, h_alignment: 'RIGHT', v_alignment: 'CENTER', fontHeight:10)
createStyle(name: 'smallTitleSpan5',fontBold: true, h_span: 5, h_alignment: 'RIGHT', v_alignment: 'CENTER', fontHeight:10)
createStyle(name: 'wrap', wrapText: true)

class StringSpec {
    final static int BOLD_STRING = 0
    final static int HEAD_STRING = 1

    int type
    Object value

    StringSpec(int type,Object value){
        this.type = type
        this.value = value
    }
}

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 cellFill = { value ->
    if (value != null) {
        setStyle('data');rowHeight(13)

        if (value instanceof Number) {
            number(value,'numberData')
        } else if (value instanceof Date) {
            date(value,'dateData')
        } else if (value instanceof StringSpec) {
            if(value.type == StringSpec.BOLD_STRING){
                cellFillBold(value.value)
            } else if (value.type == StringSpec.HEAD_STRING) {
                setStyle('header');rowHeight(50);text(value.value);
            }
        } else {
            text(value, 'textData')
        }
    }
}

def getDocument         = { AirTicketsTemplateReportTicket ticket ->
    BlankType blankType = Environment.getPublished(DictionaryCache.class).resolveReference(ticket.blankType)
    return blankType.name + ' ' +ticket.ticketNumber;
}
def getTariff           = { AirTicketsTemplateReportTicket ticket -> return ticket.mcoCategory != MCOCategory.PENALTY ? ticket.equivalentFare : ticket.penalty }
def getVoz_nie          = { AirTicketsTemplateReportTicket ticket -> return ticket.vendorCommissionValue != null ? ticket.vendorCommissionValue : BigDecimal.ZERO }
def getFee              = { AirTicketsTemplateReportTicket ticket ->
    BigDecimal result = BigDecimal.ZERO
    ticket.taxes.each { Tax tax ->
        if(tax.equivalentAmount != null && !"ZZ".equals(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.routeLine }
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.substring(agentCode.length() - 2, agentCode.length())
            }
        }
    }
    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 tchAgencyCode = ''
    EntityContainer<Organization> ecO = EntityStorage.get().resolve(ticket.agency)
    if (ecO != null) {
        ecO.entity.metadata.any {Metadata md ->
            MetadataKeyDescriptor mdKd = Environment.getPublished(DictionaryCache.class).resolveReference(md.key)
            if (mdKd != null) {
                if (MetadataKey.KEY_TCH_AGENCY_CODE.name().equals(mdKd.code)) {
                    tchAgencyCode = md.value.toString()
                }
            }
        }
    }
    return tchAgencyCode
}

def getOrgReference = { String type ->
    AirTicketsTemplateReportParameters airTicketParams = parameters.params

    if(type.equals('agency')){
        return airTicketParams?.agency
    } else if(type.equals('supplier')){
        return airTicketParams?.supplier
    } else {
        return null
    }
}

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.AIR) return 1
    if(prodCategory == ProductCategory.MCO) return 2
    return 3
}

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 bodyHead = {
    return [
        '',
        new StringSpec(StringSpec.HEAD_STRING,'Документ'),
        new StringSpec(StringSpec.HEAD_STRING,'Тариф'),
        new StringSpec(StringSpec.HEAD_STRING,'Воз-ние'),
        new StringSpec(StringSpec.HEAD_STRING,'Такса'),
        new StringSpec(StringSpec.HEAD_STRING,'Пассажир'),
        new StringSpec(StringSpec.HEAD_STRING,'Маршрут'),
        new StringSpec(StringSpec.HEAD_STRING,'Дата продажи'),
        new StringSpec(StringSpec.HEAD_STRING,'Дата вылета'),
        new StringSpec(StringSpec.HEAD_STRING,'Кассир'),
        new StringSpec(StringSpec.HEAD_STRING,'Тип тарифа'),
        new StringSpec(StringSpec.HEAD_STRING,'Форма оплаты'),
        new StringSpec(StringSpec.HEAD_STRING,'ABC')
    ]
}

def reportHead = { EntityReference<Organization> orgRef ->
    def orgName     = ''
    def datePeriod  = parameters.REPORT_PERIOD

    Organization org = EntityStorage.get().resolve(orgRef)?.entity
    if(org != null){
        orgName = org.fullName.toString()
    }

    rowHeight(13)
    text('Реестр документов для АК Ангара', 'titleH0')
    nextRow();
    text('Дата создания', 'metadataTitle')
    nextColumn();text(datePeriod,'smallTitle');
    nextRow();
    text('Наименование агентства', 'metadataTitle');
    nextColumn();text(orgName,'smallTitleSpan5');
    setStyle('data')
    int scw = 10
    nextRow();
    columnWidth(1.6*scw);
    nextColumn();   columnWidth(1.6*scw)
    nextColumn();   columnWidth(1.8*scw)
    nextColumn();   columnWidth(0.8*scw)
    nextColumn();   columnWidth(0.8*scw)
    nextColumn();   columnWidth(2*scw)
    nextColumn();   columnWidth(1.2*scw)
    nextColumn();   columnWidth(0.9*scw)
    nextColumn();   columnWidth(0.8*scw)
    nextColumn();   columnWidth(scw)
    nextColumn();   columnWidth(scw)
    nextColumn();   columnWidth(0.5*scw)
}

def reportEnd = { EntityReference<Organization> orgRef ->
    def mainAccountant  = ''
    def performer       = ''
    def phone           = ''

    Organization org = EntityStorage.get().resolve(orgRef)?.entity
    org.communications.any { Communication comm ->
        if (comm.type == CommunicationType.WORK_PHONE || comm.type == CommunicationType.AGENCY) {
            phone = comm.sense
        }
    }
    EntityReference<Person> erP = ProfileHelper.getManager(orgRef, 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()}
    rowHeight(13)
    text('Главный бухгалтер','textDataBold')
    nextColumn();text(mainAccountant,'textDataBold')

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

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

EntityReference<Organization> orgRefAgency  = getOrgReference('agency')
def tableAk  = []
def tableTch = []

def reportBody = { EntityReference<Organization> orgRef, int report ->
    def table = null

    if(report == 0){
        table = tableAk
    }else if(report == 1){
        table = tableTch
    }

    table.each { row ->
        nextRow();rowHeight(12)

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

def createTables = {
    def compareBlankOwner = {AirTicketsTemplateReportTicket a, AirTicketsTemplateReportTicket b ->
        def ak = "ИК"
        def tch = "Ш1"

        if(ProfileHelper.isOrganizationCode(a.blankOwner, ak)){
            if (ProfileHelper.isOrganizationCode(b.blankOwner, ak)) {
                return 0
            } else {
                return -1
            }
        } else if (ProfileHelper.isOrganizationCode(a.blankOwner, tch)) {
            if (ProfileHelper.isOrganizationCode(b.blankOwner, tch)) {
                return 0
            } else {
                return 1
            }
        } else {
            return 3
        }
    }

    def comparePaymentType = {AirTicketsTemplateReportTicket a, AirTicketsTemplateReportTicket b ->
        return getPaymentTypeInt(a.paymentTypes) <=> getPaymentTypeInt(b.paymentTypes)
    }

    allTickets.sort{AirTicketsTemplateReportTicket a, AirTicketsTemplateReportTicket b ->

        int res = compareBlankOwner(a,b)

        if(res == 0) {
            res = comparePaymentType(a,b)
        }

        if(res == 0) {
            res = a.vendorCommissionRate <=> b.vendorCommissionRate
        }

        if(res == 0) {
            res = getStatusInt(a.status) <=> getStatusInt(b.status)
        }

        if(res == 0) {
            res = getProdCatTypeInt(a.productCategory) <=> getProdCatTypeInt(b.productCategory)
        }

        if(res == 0) {
            res = MiscUtil.compare(a.ticketNumber, b.ticketNumber)
        }

        return res

//        int res = 0
//        return (res = compareBlankOwner(a,b)) != 0 ? res :
//        (res = comparePaymentType(a,b)) !=0 ? res :
//        (res = a.vendorCommissionRate <=> b.vendorCommissionRate) != 0 ? res :
//        (res = (a.status == b.status ? 0 : getStatusInt(a.status) <=> getStatusInt(b.status))) !=0 ? res :
//        (res = (a.productCategory == b.productCategory ? 0 : getProdCatTypeInt(a.productCategory) <=> getProdCatTypeInt(b.productCategory)))
//        (res = MiscUtil.compare(a.ticketNumber, b.ticketNumber))
    }

    def getBlankOwner = {AirTicketsTemplateReportTicket a ->
        def ak = "ИК"
        def tch = "Ш1"

        if(ProfileHelper.isOrganizationCode(a.blankOwner, ak)) return 'ak'
        else if (ProfileHelper.isOrganizationCode(a.blankOwner, tch)) return 'tch'
        return 'other'
    }
    warn 'size='+allTickets.size()
    def table = null
    groups{AirTicketsTemplateReportTicket superTickets1 -> getBlankOwner(superTickets1)}{

        if(it.equals('ak')) {
            table = tableAk
        }
        else if (it.equals('tch')) {
            table = tableTch
        }
        else {
            table = []
        }

        groups{AirTicketsTemplateReportTicket superTickets1 -> getPaymentTypeGroupString(superTickets1.paymentTypes)}{

            //if(!it.equals('ДР')){

                table.add([''])
                table.add(['Продажа ' + it])
                table.add(['', '', '', new StringSpec(StringSpec.BOLD_STRING,'ВВЛ')])
                table.add(bodyHead())

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

                groups{AirTicketsTemplateReportTicket superTickets2 -> superTickets2.vendorCommissionRate.doubleValue().toString()}{

                    def vendCommRate = it
                    boolean nextRowData = true

                    groups{AirTicketsTemplateReportTicket superTickets3 -> superTickets3.status.toString()}{

                        table.add([''])
                        table.add(['', '', '', new StringSpec(StringSpec.BOLD_STRING, it)])

                        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()}{
                                    def mcoProdCat = vendCommRate.toDouble().toString() + ' ' + 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)

                                        def firstRow = nextRowData ? mcoProdCat : ''
                                        nextRowData = false

                                        table.add([
                                            firstRow,
                                            getDocument(ticket),
                                            tariffe,
                                            voz_nie,
                                            fee,
                                            getPassander(ticket),
                                            getRoute(ticket),
                                            getDateOfSale(ticket),
                                            getDepartureDate(ticket),
                                            getAgentCode(ticket),
                                            getTypeOfTariff(ticket),
                                            getFormOfPayment(ticket),
                                            getAbc(ticket)
                                        ])
                                    }
                                    nextRowData = true

                                    tariffeTicketsStatus = MiscUtil.sum(tariffeTicketsStatus,tariffeTickets)
                                    voz_nieTicketsStatus = MiscUtil.sum(voz_nieTicketsStatus,voz_nieTickets)
                                    feeTicketsStatus     = MiscUtil.sum(feeTicketsStatus,feeTickets)

                                    table.add([new StringSpec(StringSpec.BOLD_STRING,'Итог'), new StringSpec(StringSpec.BOLD_STRING,vendCommRate), new StringSpec(StringSpec.BOLD_STRING,tariffeTickets), new StringSpec(StringSpec.BOLD_STRING,voz_nieTickets), new StringSpec(StringSpec.BOLD_STRING,feeTickets)])
                                }
                            } else {

                                def prod = vendCommRate.toDouble().toString() + ' ' + 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)

                                    def firstRow = nextRowData ? prod : ''
                                    nextRowData = false

                                    table.add([
                                        firstRow,
                                        getDocument(ticket),
                                        tariffe,
                                        voz_nie,
                                        fee,
                                        getPassander(ticket),
                                        getRoute(ticket),
                                        getDateOfSale(ticket),
                                        getDepartureDate(ticket),
                                        getAgentCode(ticket),
                                        getTypeOfTariff(ticket),
                                        getFormOfPayment(ticket),
                                        getAbc(ticket)
                                    ])
                                }

                                nextRowData = true

                                tariffeTicketsStatus = MiscUtil.sum(tariffeTicketsStatus,tariffeTickets)
                                voz_nieTicketsStatus = MiscUtil.sum(voz_nieTicketsStatus,voz_nieTickets)
                                feeTicketsStatus     = MiscUtil.sum(feeTicketsStatus,feeTickets)

                                table.add([new StringSpec(StringSpec.BOLD_STRING,'Итог'), new StringSpec(StringSpec.BOLD_STRING,vendCommRate), new StringSpec(StringSpec.BOLD_STRING,tariffeTickets), new StringSpec(StringSpec.BOLD_STRING,voz_nieTickets), new StringSpec(StringSpec.BOLD_STRING,feeTickets)])


                            }
                        }

                        tariffePT = MiscUtil.sum(tariffePT, ProductStatus.REFUND.toString().equals(it) ? tariffeTicketsStatus.negate() : tariffeTicketsStatus)
                        voz_niePT = MiscUtil.sum(voz_niePT, ProductStatus.REFUND.toString().equals(it) ? voz_nieTicketsStatus.negate() : voz_nieTicketsStatus)
                        feePT = MiscUtil.sum(feePT, ProductStatus.REFUND.toString().equals(it) ? feeTicketsStatus.negate() : feeTicketsStatus)

                        table.add([new StringSpec(StringSpec.BOLD_STRING,'Итог'), new StringSpec(StringSpec.BOLD_STRING, it), new StringSpec(StringSpec.BOLD_STRING,tariffeTicketsStatus), new StringSpec(StringSpec.BOLD_STRING,voz_nieTicketsStatus), new StringSpec(StringSpec.BOLD_STRING,feeTicketsStatus)])
                    }

                }

                table.add([''])
                table.add([new StringSpec(StringSpec.BOLD_STRING,'Итог'), new StringSpec(StringSpec.BOLD_STRING,'ВВЛ'), new StringSpec(StringSpec.BOLD_STRING,tariffePT), new StringSpec(StringSpec.BOLD_STRING,voz_niePT), new StringSpec(StringSpec.BOLD_STRING,feePT)])
                table.add([new StringSpec(StringSpec.BOLD_STRING,'Итог'), new StringSpec(StringSpec.BOLD_STRING,it), new StringSpec(StringSpec.BOLD_STRING,tariffePT), new StringSpec(StringSpec.BOLD_STRING,voz_niePT), new StringSpec(StringSpec.BOLD_STRING,feePT)])
            //}
        }

    }

}
createTables()

page{'Реестр'}{
    reportHead(orgRefAgency)
    reportBody(orgRefAgency,0)
    reportEnd(orgRefAgency)
}
page{'Реестр ТКП'}{
    reportHead(orgRefAgency)
    reportBody(orgRefAgency,1)
    reportEnd(orgRefAgency)
}