import com.gridnine.xtrip.common.l10n.model.LocaleHelper
import com.gridnine.xtrip.common.model.booking.OperationBatch
import com.gridnine.xtrip.common.model.dict.DictionaryCache
import com.gridnine.xtrip.common.model.dict.DictionaryReference
import com.gridnine.xtrip.common.model.dict.GeoLocation
import com.gridnine.xtrip.common.model.dict.LocationType
import com.gridnine.xtrip.common.reports.model.AirTicketsTemplateReportTicket

import java.text.SimpleDateFormat

createStyle(name: "left", h_alignment: "LEFT")
createStyle(name: "right", h_alignment: "RIGHT")
createStyle(name: "center", h_alignment: "CENTER")
createStyle(name: "left-bold", h_alignment: "LEFT", fontBold : true)
createStyle(name: "right-bold", h_alignment: "RIGHT", fontBold : true)
createStyle(name: "left-bold-italic-underline", h_alignment: "LEFT", fontBold : true, fontUnderline : "SINGLE", fontItalic : true)
createStyle(name: "right-bold-italic-underline", h_alignment: "RIGHT", fontBold : true, fontUnderline : "SINGLE", fontItalic : true)
createStyle(name: "center-bold", h_alignment: "CENTER", fontBold : true)
createStyle(name: "center-center-bold", h_alignment: "CENTER", v_alignment: "CENTER", fontBold : true)
createStyle(name: "left-bold-border", h_alignment: "LEFT", fontBold : true, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "left-center-bold-border", h_alignment: "LEFT", v_alignment: "CENTER", fontBold : true, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "right-bold-border", h_alignment: "RIGHT", fontBold : true, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "center-bold-border", h_alignment: "CENTER", fontBold : true, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "left-border", h_alignment: "LEFT", leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true, fontUnderline : "NONE", fontItalic : false)
createStyle(name: "right-border", h_alignment: "RIGHT", leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "center-border", h_alignment: "CENTER", leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "center-center-border", h_alignment: "CENTER", v_alignment: "CENTER", leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "center-border-number", h_alignment: "CENTER", leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "left-border-number", h_alignment: "LEFT", leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "right-border-number", h_alignment: "RIGHT", leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "right-bold-border-number", fontBold : true, h_alignment: "RIGHT", leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "center-bold-border-number", h_alignment: "CENTER", fontBold : true, leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)
createStyle(name: "center-center-border-number", h_alignment: "CENTER", v_alignment: "CENTER", leftBorder:'THIN', rightBorder:'THIN', topBorder:'THIN', bottomBorder:'THIN', wrapText: true)

def printHead() {
    rowHeight(15)
    text("Реестр продажи перевозок по специальному тарифу " + parameters['tariffs'], "center-bold", 8, 1)

    nextRow()
    text("в агентстве " + parameters['AGENCY_NAME'], "center-bold", 8, 1)

    nextRow()
    nextRow()
    text("Авиаперевозчик: ОАО «Авиакомпания \"Сибирь\"»", "left", 5, 1)

    5.times {
        nextColumn()
    }

    SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy г.")
    def periodBeginParameter = parameters['key-report-params']?.periodBegin
    def periodEndParameter = parameters['key-report-params']?.periodEnd

    text("за " +
            (periodBeginParameter ? sdf.format(periodBeginParameter) : "") +
            " - " +
            (periodEndParameter ? sdf.format(periodEndParameter) : ""),
            "right", 3, 1)
}

def printHeader() {
    nextRow(); nextRow(); rowHeight(45)

    text("№" + "\n" + "п/п", "center-center-border")
    nextColumn();text("Серия, номер" + "\n" + "перевозочного" + "\n" + "документа", "center-center-border")
    nextColumn();text("Дата" + "\n" + "транзакции", "center-center-border")
    nextColumn();text("Аэропорт" + "\n" + "отправления", "center-center-border")
    nextColumn();text("Аэропорт" + "\n" + "назначения", "center-center-border")
    nextColumn();text("Фамилия, имя," + "\n" + "отчество" + "\n" + "пассажира", "center-center-border")
    nextColumn();text("Вид тарифа", "center-center-border")
    nextColumn();text("Величина" + "\n" + "тарифа," + "\n" + "руб", "center-center-border")
}

def printTickets() {
    Map<OperationBatch, List<AirTicketsTemplateReportTicket>> ticketsMap = collectTicketsByOpBatch()

    printBatch(OperationBatch.SELL, ticketsMap)
    printBatch(OperationBatch.REFUND, ticketsMap)
    printBatch(OperationBatch.EXCHANGE, ticketsMap)
}

def collectTicketsByOpBatch() {
    Map<OperationBatch, List<AirTicketsTemplateReportTicket>> result = new HashMap<>()
    result.put(OperationBatch.SELL, new ArrayList<>())
    result.put(OperationBatch.REFUND, new ArrayList<>())
    result.put(OperationBatch.EXCHANGE, new ArrayList<>())

    tickets { AirTicketsTemplateReportTicket ticket ->
        if (result.containsKey(ticket.operationBatch) && ticketFitByTariffs(ticket)) {
            result.get(ticket.operationBatch).add(ticket)
        }
    }

    return result
}

boolean ticketFitByTariffs(AirTicketsTemplateReportTicket ticket) {
    String[] allPossibleTariffs = ["AFLOW", "AFLRT", "AFLOW1", "AFLRT1"]
    String tariffs = parameters['tariffs']

    boolean res = false

    if (tariffs != null) {
        tariffs.split("/").each { String requiredTariff ->
            ticket.segmentTariffs.each {
                it.segments.each {
                    if (it.fareBasis) {
                        String fareBasis = it.fareBasis

                        boolean isAnotherTariff = false

                        allPossibleTariffs.each { String anotherTariff ->
                            if (!requiredTariff.startsWith(anotherTariff) && fareBasis.startsWith(anotherTariff)) {
                                isAnotherTariff = true
                            }
                        }

                        if (!isAnotherTariff && fareBasis.startsWith(requiredTariff)) {
                            res = true
                        }
                    }
                }
            }
        }
    }

    return res
}

def printBatch(OperationBatch batch, Map<OperationBatch, List<AirTicketsTemplateReportTicket>> ticketsMap) {
    List<AirTicketsTemplateReportTicket> ticketsList = ticketsMap.get(batch)
    String batchName = batchName(batch)
    boolean negate = batch == OperationBatch.REFUND

    nextRow(); rowHeight(15)
    text(batchName, "left-bold-italic-underline", 8, 1)

    SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy")

    ticketsList.eachWithIndex { AirTicketsTemplateReportTicket ticket, int i ->
        nextRow()

        number(i + 1, "center-border")

        nextColumn()
        text((ticket.validatingCarrierNumber ? ticket.validatingCarrierNumber + " " : "") +
                (ticket.ticketNumber ? ticket.ticketNumber : ""))

        nextColumn()
        text(ticket.issueDate ? sdf.format(ticket.issueDate) : "")

        nextColumn()
        text(airportName(ticket.getDepartureGeoLocation()))

        nextColumn()
        text(airportName(ticket.getArriveGeoLocation()))

        nextColumn()
        text(ticket.travellerName ? ticket.travellerName.toUpperCase() : "")

        nextColumn()
        text(ticket.fareBasisLine ? ticket.fareBasisLine : "")

        nextColumn()
        number(ticket.equivalentFare ? (negate ? ticket.equivalentFare.negate() : ticket.equivalentFare) : BigDecimal.ZERO, "center-border-number")
    }

    nextRow()
    text("Итого " + batchName, "left-bold-border", 7, 1)

    7.times {
        nextColumn()
    }

    if (ticketsList.size() > 0) {
        formula("SUM(${cellIndex(-ticketsList.size(), 0)}:${cellIndex(-1, 0)})", "center-bold-border-number")
    } else {
        number(BigDecimal.ZERO, "center-bold-border-number")
    }
}

def batchName(OperationBatch batch) {
    switch (batch) {
        case OperationBatch.SELL:
            return "Продажа"
        case OperationBatch.REFUND:
            return "Возврат"
        case OperationBatch.EXCHANGE:
            return "Переоформление"
        default:
            throw new IllegalArgumentException("Unsupported batch: " + batch)
    }
}

def airportName(DictionaryReference<GeoLocation> airportRef) {
    if (airportRef == null) {
        return ""
    }

    GeoLocation airport = DictionaryCache.get().resolveReference(airportRef)
    if (airport == null || airport.type != LocationType.AIRPORT || airport.parent == null) {
        return airportRef.toString(LocaleHelper.RU_LOCALE)
    }

    GeoLocation city = DictionaryCache.get().resolveReference(airport.parent)
    if (city == null) {
        return airport.toString(LocaleHelper.RU_LOCALE)
    }

    String cityName = city.toString(LocaleHelper.RU_LOCALE)
    String airportName = airport.toString(LocaleHelper.RU_LOCALE)

    return airportName.contains(cityName) ? airportName : String.format("%s (%s)", cityName, airportName)
}

def printBottom() {
    nextRow()
    nextRow()
    printBottomRow("Исполнитель", "_____________", "__________________________", "____________________")
    printBottomRow("должность", "подпись", "ф.и.о.", "дата")
    nextRow()
    nextRow()
    printBottomRow("Главный бухгалтер", "_____________", "__________________________", "____________________")
    printBottomRow("М.П.", "подпись", "ф.и.о.", "дата")
}

def printBottomRow(String... values) {
    nextRow()
    text(values[0], "left", 3, 1)
    3.times {
        nextColumn()
    }

    text(values[1], "center", 1, 1)
    1.times {
        nextColumn()
    }

    text(values[2], "center", 2, 1)
    2.times {
        nextColumn()
    }

    text(values[3], "center", 2, 1)
    2.times {
        nextColumn()
    }
}

def setAutoWidth() {
    nextRow()
    rowHeight(15)

    8.times {
        columnAutoWidth()
        nextColumn()
    }
}

page{"Тарифы " + ((String) parameters['tariffs']).replaceAll("/", ", ")} {
    printHead()
    printHeader()
    printTickets()
    printBottom()
    setAutoWidth()
}