package com.ffii.fpsms.modules.pickOrder.service

import org.apache.poi.ss.usermodel.BorderStyle
import org.apache.poi.ss.usermodel.FillPatternType
import org.apache.poi.ss.usermodel.HorizontalAlignment
import org.apache.poi.ss.usermodel.IndexedColors
import org.apache.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.VerticalAlignment
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.ss.util.CellRangeAddress
import org.apache.poi.ss.util.WorkbookUtil
import org.apache.poi.xssf.usermodel.XSSFCellStyle
import org.apache.poi.xssf.usermodel.XSSFFont
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import java.net.URLDecoder
import java.nio.charset.StandardCharsets

/**
 * MTMS 車線 Excel（PDF 圖1）：每個車線一個 worksheet，格式版本 MTMS_ROUTE_V1。
 * laneId 與前端 [encodeLaneId] 一致：`encodeURIComponent(code)|encodeURIComponent(remark)`。
 */
object RouteLaneExcelSupport {
    const val FORMAT_MARKER = "MTMS_ROUTE_V1"
    const val SEP = "|"

    /** 0-based row indices */
    const val ROW_MARKER = 0
    const val ROW_STORE = 1
    const val ROW_DEPARTURE_DEFAULT = 2
    const val ROW_HEADER = 3
    const val ROW_FIRST_DATA = 4

    const val COL_META_A = 0
    const val COL_META_B = 1
    const val COL_META_C = 2

    const val COL_AREA_PLATE = 0
    const val COL_SHOP_NAME = 1
    const val COL_BRAND = 2
    const val COL_SHOP_CODE = 3
    const val COL_SCHEDULE = 4
    const val COL_DEPARTURE_ROW = 5

    fun decodeLaneId(laneId: String): Pair<String, String?>? {
        val i = laneId.indexOf(SEP)
        if (i < 0) return null
        return try {
            val code = URLDecoder.decode(laneId.substring(0, i), StandardCharsets.UTF_8).trim()
            val rem = URLDecoder.decode(laneId.substring(i + SEP.length), StandardCharsets.UTF_8).trim()
            if (code.isEmpty()) return null
            code to if (rem.isEmpty()) null else rem
        } catch (_: Exception) {
            null
        }
    }

    fun plateLabel(groupIndexZeroBased: Int): String {
        val n = groupIndexZeroBased + 1
        val digits = arrayOf("一", "二", "三", "四", "五", "六", "七", "八", "九", "十")
        val cn = when {
            n in 1..10 -> digits[n - 1]
            n in 11..19 -> "十" + digits[n - 11]
            else -> "$n"
        }
        return "板$cn"
    }

    fun uniqueSheetName(workbook: Workbook, truckLanceCode: String, remark: String?): String {
        val remarkPart = remark?.trim()?.takeIf { it.isNotEmpty() }?.let { "_${it.take(8)}" } ?: ""
        val raw = (truckLanceCode.take(22) + remarkPart).take(31)
        var base = WorkbookUtil.createSafeSheetName(raw).take(31)
        if (base.isEmpty()) base = "Lane"
        var name = base
        var i = 0
        while (workbook.getSheet(name) != null) {
            val suffix = "_$i"
            val truncated = base.take((31 - suffix.length).coerceAtLeast(1))
            name = WorkbookUtil.createSafeSheetName(truncated + suffix).take(31)
            i++
        }
        return name
    }

    private data class RouteLaneExportStyles(
        val metaKey: XSSFCellStyle,
        val metaValue: XSSFCellStyle,
        val header: XSSFCellStyle,
        val data: XSSFCellStyle,
        val dataAlt: XSSFCellStyle,
    )

    private fun buildExportStyles(wb: XSSFWorkbook): RouteLaneExportStyles {
        fun XSSFCellStyle.borders() {
            borderTop = BorderStyle.THIN
            borderBottom = BorderStyle.THIN
            borderLeft = BorderStyle.THIN
            borderRight = BorderStyle.THIN
        }

        val metaKey = (wb.createCellStyle() as XSSFCellStyle).apply {
            alignment = HorizontalAlignment.LEFT
            verticalAlignment = VerticalAlignment.CENTER
            fillForegroundColor = IndexedColors.GREY_40_PERCENT.index
            fillPattern = FillPatternType.SOLID_FOREGROUND
            borders()
            val f = wb.createFont() as XSSFFont
            f.bold = true
            f.fontHeightInPoints = 11
            setFont(f)
        }
        val metaValue = (wb.createCellStyle() as XSSFCellStyle).apply {
            alignment = HorizontalAlignment.LEFT
            verticalAlignment = VerticalAlignment.CENTER
            fillForegroundColor = IndexedColors.WHITE.index
            fillPattern = FillPatternType.SOLID_FOREGROUND
            borders()
            val f = wb.createFont()
            f.fontHeightInPoints = 11
            setFont(f)
        }
        val headerFont = (wb.createFont() as XSSFFont).apply {
            bold = true
            fontHeightInPoints = 11
            color = IndexedColors.WHITE.index
        }
        val header = (wb.createCellStyle() as XSSFCellStyle).apply {
            alignment = HorizontalAlignment.CENTER
            verticalAlignment = VerticalAlignment.CENTER
            fillForegroundColor = IndexedColors.ROYAL_BLUE.index
            fillPattern = FillPatternType.SOLID_FOREGROUND
            borders()
            setFont(headerFont)
        }
        val data = (wb.createCellStyle() as XSSFCellStyle).apply {
            alignment = HorizontalAlignment.LEFT
            verticalAlignment = VerticalAlignment.CENTER
            wrapText = true
            borders()
            val f = wb.createFont()
            f.fontHeightInPoints = 11
            setFont(f)
        }
        val dataAlt = (wb.createCellStyle() as XSSFCellStyle).apply {
            cloneStyleFrom(data)
            fillPattern = FillPatternType.SOLID_FOREGROUND
            fillForegroundColor = IndexedColors.GREY_25_PERCENT.index
        }
        return RouteLaneExportStyles(metaKey, metaValue, header, data, dataAlt)
    }

    /**
     * 表頭／邊框／隔行底色／欄寬／凍結首列資料之上／AutoFilter。不改儲存格值（import 仍讀 raw）。
     */
    fun applyRouteLaneExportFinishing(
        sheet: Sheet,
        wb: XSSFWorkbook,
        firstDataRow: Int,
        lastDataRow: Int,
    ) {
        val st = buildExportStyles(wb)

        for (r in intArrayOf(ROW_MARKER, ROW_STORE, ROW_DEPARTURE_DEFAULT)) {
            val row = sheet.getRow(r) ?: continue
            for (c in 0..COL_META_C) {
                val cell = row.getCell(c) ?: continue
                cell.cellStyle = if (c == COL_META_A) st.metaKey else st.metaValue
            }
        }

        val headerRow = sheet.getRow(ROW_HEADER)
        if (headerRow != null) {
            for (c in COL_AREA_PLATE..COL_DEPARTURE_ROW) {
                headerRow.getCell(c)?.cellStyle = st.header
            }
        }

        if (lastDataRow >= firstDataRow) {
            for (r in firstDataRow..lastDataRow) {
                val alt = (r - firstDataRow) % 2 == 1
                val style = if (alt) st.dataAlt else st.data
                val row = sheet.getRow(r) ?: continue
                for (c in COL_AREA_PLATE..COL_DEPARTURE_ROW) {
                    row.getCell(c)?.cellStyle = style
                }
            }
        }

        sheet.setColumnWidth(COL_AREA_PLATE, 14 * 256)
        sheet.setColumnWidth(COL_SHOP_NAME, 28 * 256)
        sheet.setColumnWidth(COL_BRAND, 14 * 256)
        sheet.setColumnWidth(COL_SHOP_CODE, 12 * 256)
        sheet.setColumnWidth(COL_SCHEDULE, 12 * 256)
        sheet.setColumnWidth(COL_DEPARTURE_ROW, 12 * 256)

        sheet.createFreezePane(0, ROW_FIRST_DATA)

        val filterLast = if (lastDataRow >= firstDataRow) lastDataRow else ROW_HEADER
        sheet.setAutoFilter(
            CellRangeAddress(ROW_HEADER, filterLast, COL_AREA_PLATE, COL_DEPARTURE_ROW),
        )
    }
}
