package com.gridnine.xtrip.server.reports.templates

import com.gridnine.xtrip.common.Environment
import com.gridnine.xtrip.common.model.booking.ProductIndex
import com.gridnine.xtrip.common.model.booking.ProductStatus
import com.gridnine.xtrip.common.model.dict.Airline
import com.gridnine.xtrip.common.model.dict.DictionaryCache
import com.gridnine.xtrip.common.model.dict.GdsName
import java.math.RoundingMode

//CREATING STYLES
createStyle(name: 'title', fontBold: true, h_span: 6, 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', foreground: 'GREEN', fontBold: true, 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')
createStyle(name: 'dateData', parent: 'data', h_alignment: 'RIGHT', format: 'm/d/yy')
createStyle(name: 'statusGroupTitle', parent: 'header', h_span: 2, 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)

//ADDITIONAL FUNCTIONS
def monthIndex = { ProductIndex it ->
    Date date = it.issueDate
    if (date == null)
    {
        return -1
    }
    Calendar cal = Calendar.getInstance()
    cal.setTime(date)
    return cal.get(Calendar.MONTH)
}

def monthName = {
    if (it == null) {
        return "все"
    }
    int month = monthIndex(it)
    switch (month)
    {
        case 0:
            return 'Январь'
        case 1:
            return 'Февраль'
        case 2:
            return 'Март'
        case 3:
            return 'Апрель'
        case 4:
            return 'Май'
        case 5:
            return 'Июнь'
        case 6:
            return 'Июль'
        case 7:
            return 'Август'
        case 8:
            return 'Сентябрь'
        case 9:
            return 'Октябрь'
        case 10:
            return 'Ноябрь'
        case 11:
            return 'Декабрь'
        default:
            return 'Другой'
    }

}

def airline = { ProductIndex it ->
    if (!it.carrier)
    {
        return "Не задан"
    }
    Airline airline = Environment.getPublished(DictionaryCache.class).resolveReference(it.carrier)
    if (airline)
    {
        return airline.toString()
    }
    Set<Airline> airlines = Environment.getPublished(DictionaryCache.class).lookup(Airline.class, it.carrier.code)
    return airlines.isEmpty() ? "Не задан" : airlines.iterator().next().toString()
}

def incrementValue = { ProductIndex it ->
    if (!it.status)
    {
        return 0
    }
    switch (it.status)
    {
        case ProductStatus.SELL:
            return 1
        case ProductStatus.REFUND:
            return 1
        default:
            return 0
    }
}

def intNumber = {
    return BigDecimal.valueOf(it)
}

def notNull = { it ? it : BigDecimal.ZERO }

def income = { ProductIndex it -> return notNull(it.totalSum).add(notNull(it.clientFeeValue))
}

allTickets.sort { a, b -> monthIndex(a) <=> monthIndex(b) }


//REPORT
page { monthName(it) } {
    Map ticketsMap = [:]
    int sellTotalTicketsCount = 0
    BigDecimal sellTotalIncome = BigDecimal.ZERO
    int refundTotalTicketsCount = 0
    BigDecimal refundTotalIncome = BigDecimal.ZERO
    tickets { ProductIndex ticket ->
        int sellIncrement = incrementValue(ticket)
        int refundIncrement = incrementValue(ticket)
        if (sellIncrement == 0 || refundIncrement == 0)
        {
            return
        }
        String carrier = airline(ticket)
        if (!ticketsMap[carrier])
        {
            AirCompanyItem item = new AirCompanyItem()
            item.airline = carrier
            ticketsMap[carrier] = item
        }
        AirCompanyItem item = ticketsMap[carrier]
        if (ticket.status == ProductStatus.SELL)
        {
            item.sellTicketsCount = item.sellTicketsCount + sellIncrement
            item.sellIncome = item.sellIncome.add(income(ticket))
            sellTotalTicketsCount = sellTotalTicketsCount + sellIncrement
            sellTotalIncome = sellTotalIncome.add(income(ticket))
            if (ticket.gdsNames.contains(GdsName.SABRE) || GdsName.SABRE == ticket.gdsName)
            {
                item.sabreSegmentsCount = item.sabreSegmentsCount + ticket.segmentsCount
            }
            if (ticket.gdsNames.contains(GdsName.SIRENA) || GdsName.SIRENA == ticket.gdsName)
            {
                item.sirenaSegmentsCount = item.sirenaSegmentsCount + ticket.segmentsCount
            }
            if (ticket.gdsNames.contains(GdsName.SIG) || GdsName.SIG == ticket.gdsName)
            {
                item.sigSegmentsCount = item.sigSegmentsCount + ticket.segmentsCount
            }
        }
        if (ticket.status == ProductStatus.REFUND)
        {
            item.refundTicketsCount = item.refundTicketsCount + refundIncrement
            item.refundIncome = item.refundIncome.add(income(ticket))
            refundTotalTicketsCount = refundTotalTicketsCount + refundIncrement
            refundTotalIncome = refundTotalIncome.add(income(ticket))
        }
    }
    List items = []
    items.addAll(ticketsMap.values())
    items.sort { AirCompanyItem item -> -item.sellTicketsCount }
    nextRow();
    rowHeight(20);
    nextColumn(); text(it, 'title');
    nextRow();
    nextRow();
    int scw = 10

    //header
    setStyle('header')
    rowHeight(40)
    nextColumn(); columnWidth(scw); text('№ пп');
    nextColumn(); columnWidth(4 * scw); text('Авиакомпания');
    nextColumn(); columnWidth(scw); text('Билетов продано');
    nextColumn(); columnWidth(2 * scw); text('Сумма выручки');
    nextColumn(); columnWidth(scw); text('% билетов');
    nextColumn(); columnWidth(1.5 * scw); text('% от общей выручки');
    nextColumn(); columnWidth(scw); text('Билетов возвращено');
    nextColumn(); columnWidth(2 * scw); text('Сумма возвратов');
    nextColumn(); columnWidth(scw); text('% от возвращенных билетов');
    nextColumn(); columnWidth(1.5 * scw); text('% от общих возвратов');
    nextColumn(); columnWidth(1.5 * scw); text('Сегмент Sabre');
    nextColumn(); columnWidth(1.5 * scw); text('Сегмент Sirena');
    nextColumn(); columnWidth(1.5 * scw); text('Сегмент Sig');
    nextColumn();

    //group by subagent
    int idx = 0
    String sellTicketCell = cellIndex(1, -11)
    String sellTicketIncome = cellIndex(1, -10)
    String refundTicketCell = cellIndex(1, -7)
    String refundTicketIncome = cellIndex(1, -6)
    String sabreSegmentsCount = cellIndex(1, -3)
    String sirenaSegmentsCount = cellIndex(1, -2)
    String sigSegmentsCount = cellIndex(1, -1)
    items.each { AirCompanyItem item ->
        //group by status
        idx++;
        nextRow();
        rowHeight(12);
        nextColumn(); number(BigDecimal.valueOf(idx), 'numberData');
        nextColumn(); text(item.airline, 'textData');
        nextColumn(); number(BigDecimal.valueOf(item.sellTicketsCount), 'numberData');
        nextColumn(); number(BigDecimal.valueOf(item.sellIncome), 'numberData');
        nextColumn(); number(sellTotalTicketsCount == 0 ? BigDecimal.ZERO :
                                     BigDecimal.valueOf(item.sellTicketsCount).multiply(BigDecimal.valueOf(100)).
                                             divide(BigDecimal.valueOf(sellTotalTicketsCount), 2, RoundingMode.HALF_UP),
                             'numberData');
        nextColumn(); number(sellTotalIncome.compareTo(BigDecimal.ZERO) == 0 ?:
                                     BigDecimal.valueOf(item.sellIncome).multiply(BigDecimal.valueOf(100)).
                                             divide(sellTotalIncome, 2, RoundingMode.HALF_UP), 'numberData');
        nextColumn(); number(BigDecimal.valueOf(item.refundTicketsCount), 'numberData');
        nextColumn(); number(BigDecimal.valueOf(item.refundIncome), 'numberData');
        nextColumn(); number(refundTotalTicketsCount == 0 ? BigDecimal.ZERO :
                                     BigDecimal.valueOf(item.refundTicketsCount).multiply(BigDecimal.valueOf(100)).
                                             divide(BigDecimal.valueOf(refundTotalTicketsCount), 2,
                                                    RoundingMode.HALF_UP), 'numberData');
        BigDecimal refundIncome
        if (refundTotalIncome.compareTo(BigDecimal.ZERO) == 0) {
            refundIncome = null
        } else {
            refundIncome = BigDecimal.valueOf(item.refundIncome).multiply(BigDecimal.valueOf(100)).divide(refundTotalIncome, 2, RoundingMode.HALF_UP)
        }
        nextColumn(); number(refundIncome, 'numberData');
        nextColumn(); number(intNumber(item.sabreSegmentsCount), 'numberData');
        nextColumn(); number(intNumber(item.sirenaSegmentsCount), 'numberData');
        nextColumn(); number(intNumber(item.sigSegmentsCount), 'numberData');
        nextColumn();
    }

    //status group total
    nextRow();
    nextColumn(); text('Итого', 'totalTitle');
    nextColumn(); formula(idx == 0 ? "0" : "SUM(${sellTicketCell}:${cellIndex(-1, 0)})", 'totalNumber');
    nextColumn(); formula(idx == 0 ? "0" : "SUM(${sellTicketIncome}:${cellIndex(-1, 0)})", 'totalNumber');
    nextColumn(); number(BigDecimal.valueOf(100), 'totalNumber');
    nextColumn(); number(BigDecimal.valueOf(100), 'totalNumber');
    nextColumn(); formula(idx == 0 ? "0" : "SUM(${refundTicketCell}:${cellIndex(-1, 0)})", 'totalNumber');
    nextColumn(); formula(idx == 0 ? "0" : "SUM(${refundTicketIncome}:${cellIndex(-1, 0)})", 'totalNumber');
    nextColumn(); number(BigDecimal.valueOf(100), 'totalNumber');
    nextColumn(); number(BigDecimal.valueOf(100), 'totalNumber');
    nextColumn(); formula(idx == 0 ? "0" : "SUM(${sabreSegmentsCount}:${cellIndex(-1, 0)})", 'totalNumber');
    nextColumn(); formula(idx == 0 ? "0" : "SUM(${sirenaSegmentsCount}:${cellIndex(-1, 0)})", 'totalNumber');
    nextColumn(); formula(idx == 0 ? "0" : "SUM(${sigSegmentsCount}:${cellIndex(-1, 0)})", 'totalNumber');
}

class AirCompanyItem
{
    String airline

    int sellTicketsCount
    BigDecimal sellIncome = BigDecimal.ZERO
    int refundTicketsCount
    BigDecimal refundIncome = BigDecimal.ZERO

    int sabreSegmentsCount
    int sirenaSegmentsCount
    int sigSegmentsCount
}
