package com.printer.demo.bean;

import java.util.ArrayList;
import java.util.List;
import java.text.BreakIterator;
import java.util.Locale;

public class LaoAlignedTable {

    public enum Align { LEFT, CENTER, RIGHT }

    private final List<Row> rows = new ArrayList<>();
    private final int[] colWidths;
    private final Align[] aligns;

    // 列间距
    private int colSpacing = 1;

    /* ==================== 内部行模型 ==================== */

    private static class Row {
        String[] cols;     // 普通表格行
        String divider;    // 分隔线（二选一）
    }

    /* ==================== 构造 ==================== */

    public LaoAlignedTable(int[] colWidths, Align[] aligns) {
        if (colWidths.length != aligns.length) {
            throw new IllegalArgumentException("列宽和对齐数组长度不一致");
        }
        this.colWidths = colWidths;
        this.aligns = aligns;
    }

    public void setColSpacing(int colSpacing) {
        this.colSpacing = Math.max(0, colSpacing);
    }

    /* ==================== 对外 API ==================== */

    public void addRow(String... cols) {
        if (cols.length != colWidths.length) {
            throw new IllegalArgumentException("列数不匹配");
        }
        Row r = new Row();
        r.cols = cols;
        rows.add(r);
    }

    /** ★ 你要的接口：画分隔线 */
    public void addDivider(char ch) {
        Row r = new Row();
        r.divider = buildDivider(ch);
        rows.add(r);
    }

    /* ==================== 渲染 ==================== */

    public String generate() {
        return render();
    }

    public String render() {
        StringBuilder out = new StringBuilder();

        for (Row row : rows) {

            /* ===== 分隔线行 ===== */
            if (row.divider != null) {
                out.append(row.divider).append('\n');
                continue;
            }

            /* ===== 普通表格行 ===== */
            String[] cols = row.cols;

            List<List<String>> wrappedCols = new ArrayList<>();
            int maxLines = 0;

            for (int i = 0; i < cols.length; i++) {
                List<String> lines = wrapByWidth(cols[i], colWidths[i]);
                wrappedCols.add(lines);
                maxLines = Math.max(maxLines, lines.size());
            }

            for (int line = 0; line < maxLines; line++) {
                for (int c = 0; c < wrappedCols.size(); c++) {
                    String cell = line < wrappedCols.get(c).size()
                            ? wrappedCols.get(c).get(line)
                            : "";

                    out.append(pad(cell, colWidths[c], aligns[c]));

                    if (c < wrappedCols.size() - 1) {
                        out.append(spaces(colSpacing));
                    }
                }
                out.append('\n');
            }
        }

        return out.toString();
    }

    /* ==================== Lao 友好换行 ==================== */

    private List<String> wrapByWidth(String text, int width) {
        List<String> lines = new ArrayList<>();
        if (text == null || text.isEmpty()) {
            lines.add("");
            return lines;
        }

        BreakIterator it = BreakIterator.getCharacterInstance(Locale.ROOT);
        it.setText(text);

        StringBuilder line = new StringBuilder();
        int lineWidth = 0;

        int start = it.first();
        for (int end = it.next(); end != BreakIterator.DONE; start = end, end = it.next()) {
            String grapheme = text.substring(start, end);
            int gw = displayWidth(grapheme);

            if (lineWidth + gw > width) {
                lines.add(line.toString());
                line.setLength(0);
                lineWidth = 0;
            }

            line.append(grapheme);
            lineWidth += gw;
        }

        if (line.length() > 0) {
            lines.add(line.toString());
        }

        return lines;
    }

    /* ==================== 分隔线 ==================== */

    private String buildDivider(char ch) {
        int width = totalWidth();
        StringBuilder sb = new StringBuilder(width);
        for (int i = 0; i < width; i++) {
            sb.append(ch);
        }
        return sb.toString();
    }

    private int totalWidth() {
        int sum = 0;
        for (int w : colWidths) sum += w;
        sum += colSpacing * (colWidths.length - 1);
        return sum;
    }

    /* ==================== 对齐 / 宽度 ==================== */

    private String pad(String text, int width, Align align) {
        int len = displayWidth(text);
        int pad = width - len;
        if (pad <= 0) return text;

        switch (align) {
            case LEFT:
                return text + spaces(pad);
            case RIGHT:
                return spaces(pad) + text;
            case CENTER:
                int left = pad / 2;
                int right = pad - left;
                return spaces(left) + text + spaces(right);
            default:
                return text;
        }
    }

    private int displayWidth(String s) {
        int w = 0;
        for (int i = 0; i < s.length(); ) {
            int cp = s.codePointAt(i);
            w += charWidth(cp);
            i += Character.charCount(cp);
        }
        return w;
    }

    private int charWidth(int codePoint) {
        int type = Character.getType(codePoint);
        if (type == Character.NON_SPACING_MARK ||
                type == Character.COMBINING_SPACING_MARK) {
            return 0;
        }
        return 1;
    }

    private String spaces(int n) {
        if (n <= 0) return "";
        StringBuilder sb = new StringBuilder(n);
        for (int i = 0; i < n; i++) {
            sb.append(' ');
        }
        return sb.toString();
    }
}
