//file:noinspection GrDeprecatedAPIUsage
package com.gridnine.xtrip.server.reports.prepare.statistics

import com.gridnine.xtrip.common.Environment
import com.gridnine.xtrip.common.model.Xeption
import com.gridnine.xtrip.common.model.support.reports.ProductStatisticsReportEntry
import com.gridnine.xtrip.common.model.support.reports.ProductStatisticsReportRequest
import com.gridnine.xtrip.common.model.support.reports.ProductStatisticsReportResponse
import com.gridnine.xtrip.common.model.system.Message
import com.gridnine.xtrip.common.model.system.MessageType
import com.gridnine.xtrip.common.util.MiscUtil
import com.gridnine.xtrip.common.util.TextUtil
import com.gridnine.xtrip.common.util.ValueHolder
import com.gridnine.xtrip.server.configuration.ServerConfiguration
import com.gridnine.xtrip.server.model.statistics.CollectStatisticsFlagPublisher
import com.gridnine.xtrip.server.model.synchronization.SynchronizationHelper
import com.gridnine.xtrip.server.model.synchronization.SynchronizationRequest
import com.gridnine.xtrip.server.model.synchronization.SynchronizationResponse

import java.text.DateFormat
import java.text.SimpleDateFormat

createStyle(name: 'title', fontBold: true, h_span: 6, h_alignment: 'CENTER', v_alignment: 'CENTER', fontHeight: 14, wrapText: 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: 'header', fontBold: false, 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: 'fakeText', fontHeight: 10)
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: 13, 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)

class ReportEntry {
    String period
    String carrierCode
    String productType
    String status
    String gds
    int count
}

class ReportPeriod {
    String caption
    Date startDate
    Date endDate
}

def periods = []
def splitByMonth = (Boolean.TRUE == parameters.splitByMonth)
def splitByCarrier = (Boolean.TRUE == parameters.splitByCarrier)

if (splitByMonth) {
    Calendar cal = Calendar.getInstance()
    cal.setTime(parameters.startDate)
    Date endDate = parameters.endDate ? MiscUtil.setDayEndTime(parameters.endDate) : MiscUtil.setDayEndTime(new Date())
    while (cal.getTime().before(endDate)) {
        Date periodStartDate = MiscUtil.clearTime(cal.getTime())
        cal.add(Calendar.MONTH, 1)
        cal.set(Calendar.DAY_OF_MONTH, 1)
        cal.add(Calendar.DAY_OF_MONTH, -1)
        Date periodEndDate = MiscUtil.setDayEndTime(cal.getTime())
        if (periodEndDate.after(endDate)) {
            periodEndDate = endDate
        }
        String caption = ""
        switch (cal.get(Calendar.MONTH)) {
            case Calendar.JANUARY:
                caption = "01_Jan"
                break
            case Calendar.FEBRUARY:
                caption = "02_Feb"
                break
            case Calendar.MARCH:
                caption = "03_Mar"
                break
            case Calendar.APRIL:
                caption = "04_Apr"
                break
            case Calendar.MAY:
                caption = "05_May"
                break
            case Calendar.JUNE:
                caption = "06_Jun"
                break
            case Calendar.JULY:
                caption = "07_Jul"
                break
            case Calendar.AUGUST:
                caption = "08_Aug"
                break
            case Calendar.SEPTEMBER:
                caption = "09_Sep"
                break
            case Calendar.OCTOBER:
                caption = "10_Oct"
                break
            case Calendar.NOVEMBER:
                caption = "11_Nov"
                break
            case Calendar.DECEMBER:
                caption = "12_Dec"
                break
        }
        caption = "${cal.get(Calendar.YEAR)}_${caption}"
        cal.add(Calendar.DAY_OF_MONTH, 1)
        periods.add(new ReportPeriod(startDate: periodStartDate, endDate: periodEndDate, caption: caption))
    }
} else {
    periods.add(new ReportPeriod(startDate: MiscUtil.clearTime(parameters.startDate),
            endDate: MiscUtil.setDayEndTime(parameters.endDate), caption: "all_period"))
}

def carrierSet = new HashSet<String>()
def entries = new ArrayList<ReportEntry>()

periods.forEach { ReportPeriod period ->
    SynchronizationRequest<ProductStatisticsReportRequest> request = new SynchronizationRequest<>()
    ProductStatisticsReportRequest data = new ProductStatisticsReportRequest()

    String licenseKey = Environment.getPublished(ServerConfiguration.class)
            .getConfiguration().getProperty("licenceKey")
    if (TextUtil.isBlank(licenseKey)) {
        throw Xeption.forEndUser("в настройках программы не задан лицензионный ключ")
    }
    data.setLicenceKey(licenseKey)
    if (period.startDate != null) {
        data.setStartDate(MiscUtil.toLocalDate(period.startDate))
    }
    if (period.endDate != null) {
        data.setEndDate(MiscUtil.toLocalDate(period.endDate))
    }

    request.setData(data)
    request.setOperationId(ProductStatisticsReportRequest.class.getSimpleName())
    request.setClientId(Environment.getApplicationId())
    request.setUser(CollectStatisticsFlagPublisher.STATISTICS_USER)
    ValueHolder<String> trace = new ValueHolder<>()

    SynchronizationResponse<ProductStatisticsReportResponse> response = SynchronizationHelper
            .execute(request, CollectStatisticsFlagPublisher.STATISTICS_SERVER_URL, trace)

    for (Message msg : response.getMessages()) {
        if (msg.type == MessageType.ERROR) {
            throw Xeption.forEndUser(msg.message.toString())
        }
    }

    Collections.sort(response.data.entries, { ProductStatisticsReportEntry e1, ProductStatisticsReportEntry e2 ->
        int res = MiscUtil.compare(e1.carrierCode, e2.carrierCode)
        if (res != 0) {
            return res
        }
        res = MiscUtil.compare(e1.productType, e2.productType)
        if (res != 0) {
            return res
        }
        res = MiscUtil.compare(e1.gds, e2.gds)
        if (res != 0) {
            return res
        }
        res = MiscUtil.compare(e1.status, e2.status)
        if (res != 0) {
            return res
        }
        return 0
    })

    response.data.entries.forEach { entry ->
        ReportEntry re = new ReportEntry()
        re.period = period.caption
        re.count = entry.count
        re.gds = entry.gds
        re.productType = entry.productType
        re.status = entry.status
        re.carrierCode = entry.carrierCode
        entries.add(re)

        carrierSet.add(re.carrierCode)
    }
}

page { "Данные" } {

    if (splitByMonth) {
        columnWidth(20); text('Период', 'header'); nextColumn()
    }
    if (splitByCarrier) {
        columnWidth(20); text('Авиакомпания', 'header'); nextColumn()
    }
    columnWidth(20); text('Канал продаж', 'header'); nextColumn()
    columnWidth(20); text('Тип продукта', 'header'); nextColumn()
    columnWidth(20); text('Статус', 'header'); nextColumn()
    columnWidth(20); text('Кол-во', 'header')

    entries.forEach { entry ->
        nextRow()
        if (splitByMonth) {
            text(entry.period, 'textData'); nextColumn()
        }
        if (splitByCarrier) {
            text(entry.carrierCode, 'textData'); nextColumn()
        }
        text(entry.gds, 'textData'); nextColumn()
        text(entry.productType, 'textData'); nextColumn()
        text(entry.status, 'textData'); nextColumn()
        number(entry.count, 'numberData')
    }

}

def findWidth = { caption, clb ->
    def width = caption.length()
    entries.forEach { et ->
        def content = clb.call(et)
        if (content != null) {
            if (width < content.length()) {
                width = content.length()
            }
        }
    }
    return (int) width * 0.9 + 2
}

def getReportPeriod = { Date periodBegin, Date periodEnd ->
    String reportPeriod = "" //$NON-NLS-1$
    DateFormat df = new SimpleDateFormat("dd", //$NON-NLS-1$
            new Locale("ru", "RU")) //$NON-NLS-1$ //$NON-NLS-2$
    DateFormat df2 = new SimpleDateFormat("dd.MM.yy", //$NON-NLS-1$
            new Locale("ru", "RU")) //$NON-NLS-1$ //$NON-NLS-2$
    if ((periodBegin != null) && (periodEnd != null)) {
        if ((periodBegin.getDate() == periodEnd.getDate())
                && (periodBegin.getMonth() == periodEnd.getMonth())
                && (periodBegin.getYear() == periodEnd.getYear())) {
            reportPeriod = df2.format(periodEnd)
        } else if ((periodBegin.getMonth() == periodEnd.getMonth())
                && (periodBegin.getYear() == periodEnd.getYear())) {
            reportPeriod = df.format(periodBegin) + "-" + df2.format(periodEnd)
        } else {
            reportPeriod = df2.format(periodBegin) + "-" + df2.format(periodEnd)

        }
    }
    return reportPeriod
}

page { "Отчет" } {

    def period = getReportPeriod(parameters.startDate, parameters.endDate)
    def title = "Статистика продаж за период ${period}"

    rowAutoHeight()
    text(title, 'title', 0, 0)

    nextRow()
    rowHeight(12)

    nextRow()
    pivotTable {
        source(sheet: "Данные", leftTop: [row: 0, column: 0],
                rightBottom: [row   : entries.size(),
                              column: 3 + (splitByCarrier ? 1 : 0) + (splitByMonth ? 1 : 0)])
        if (splitByMonth) {
            if (splitByCarrier) {
                row(0, 1, 2, 3, 4)
                sumColumn(5)
            } else {
                row(0, 1, 2, 3)
                sumColumn(4)
            }
        } else {
            if (splitByCarrier) {
                row(0, 1, 2, 3)
                sumColumn(4)
            } else {
                row(0, 1, 2)
                sumColumn(3)
            }
        }
    }

    nextRow()
    if (splitByMonth) {
        text("", "fakeText"); columnWidth(findWidth("Период", { return it.period })); nextColumn()
    }
    if (splitByCarrier) {
        text("", "fakeText"); columnWidth(findWidth("Авиакомпания", { return it.carrierCode })); nextColumn()
    }
    text("", "fakeText"); columnWidth(findWidth("Канал продаж", { return it.displayedGdsName })); nextColumn()
    text("", "fakeText"); columnWidth(findWidth("Тип продукта", { return it.productType })); nextColumn()
    text("", "fakeText"); columnWidth(findWidth("Статус", { return it.status }))
}

setDefaultSheet("Отчет")
