package com.campus.activity.util;

import com.campus.activity.entity.Activity;
import com.campus.activity.entity.Registration;
import com.campus.activity.entity.User;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.draw.SolidLine;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.properties.HorizontalAlignment;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.properties.VerticalAlignment;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

public class PdfUtil {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm");

    public static byte[] generateTicketPdf(User user, Activity activity, Registration registration) {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            PdfWriter writer = new PdfWriter(outputStream);
            PdfDocument pdf = new PdfDocument(writer);
            Document document = new Document(pdf);

            PdfFont chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
            PdfFont boldChineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);

            createHeader(document, chineseFont, boldChineseFont);
            createDivider(document);
            createActivityInfo(document, activity, chineseFont, boldChineseFont);
            createParticipantAndQrCode(document, user, registration, chineseFont, boldChineseFont);
            createFooter(document, chineseFont);

            document.close();

            return outputStream.toByteArray();
        } catch (Exception e) {
            throw new RuntimeException("生成电子票失败", e);
        }
    }

    private static void createHeader(Document document, PdfFont font, PdfFont boldFont) {
        Paragraph title = new Paragraph("校园活动电子票")
                .setFont(boldFont)
                .setFontSize(20)
                .setBold()
                .setTextAlignment(TextAlignment.CENTER)
                .setMarginTop(15)
                .setMarginBottom(5);

        Paragraph subtitle = new Paragraph("Campus Activity E-Ticket")
                .setFont(font)
                .setFontSize(9)
                .setTextAlignment(TextAlignment.CENTER)
                .setFontColor(ColorConstants.GRAY)
                .setMarginBottom(10);

        document.add(title);
        document.add(subtitle);
    }

    private static void createDivider(Document document) {
        SolidLine line = new SolidLine(1f);
        line.setColor(ColorConstants.LIGHT_GRAY);
        LineSeparator separator = new LineSeparator(line)
                .setMarginBottom(15)
                .setWidth(UnitValue.createPercentValue(100));
        document.add(separator);
    }

    private static void createActivityInfo(Document document, Activity activity, PdfFont font, PdfFont boldFont) {
        Paragraph sectionTitle = new Paragraph("活动信息")
                .setFont(boldFont)
                .setFontSize(12)
                .setBold()
                .setMarginBottom(8);

        document.add(sectionTitle);

        Table infoTable = new Table(UnitValue.createPercentArray(new float[]{25, 75}))
                .setMarginBottom(15)
                .setWidth(UnitValue.createPercentValue(90))
                .setHorizontalAlignment(HorizontalAlignment.CENTER);

        addTableRow(infoTable, "活动名称", activity.getTitle(), font, boldFont, true);
        addTableRow(infoTable, "活动时间", formatDateTime(activity.getStartTime()) + " ~ " + formatDateTime(activity.getEndTime()), font, boldFont, false);
        addTableRow(infoTable, "活动地点", activity.getLocation(), font, boldFont, false);

        document.add(infoTable);
    }

    private static void createParticipantAndQrCode(Document document, User user, Registration registration, PdfFont font, PdfFont boldFont) {
        Table mainTable = new Table(UnitValue.createPercentArray(new float[]{60, 40}))
                .setWidth(UnitValue.createPercentValue(90))
                .setHorizontalAlignment(HorizontalAlignment.CENTER)
                .setMarginBottom(15);

        Cell leftCell = new Cell()
                .setBorder(com.itextpdf.layout.borders.Border.NO_BORDER)
                .setPadding(0);

        Cell rightCell = new Cell()
                .setBorder(com.itextpdf.layout.borders.Border.NO_BORDER)
                .setPadding(0)
                .setVerticalAlignment(VerticalAlignment.MIDDLE);

        Paragraph participantTitle = new Paragraph("参与者信息")
                .setFont(boldFont)
                .setFontSize(12)
                .setBold()
                .setMarginBottom(8);

        Table participantTable = new Table(UnitValue.createPercentArray(new float[]{25, 75}))
                .setMarginBottom(0);

        addTableRow(participantTable, "学生姓名", user.getName(), font, boldFont, true);
        addTableRow(participantTable, "学号", user.getStudentId(), font, boldFont, false);
        addTableRow(participantTable, "电子票号", registration.getTicketCode(), font, boldFont, false);
        addTableRow(participantTable, "报名时间", formatDateTime(registration.getCreatedAt()), font, boldFont, false);

        leftCell.add(participantTitle);
        leftCell.add(participantTable);

        try {
            byte[] qrCodeBytes = generateQrCode(registration.getTicketCode());
            Image qrCodeImage = new Image(ImageDataFactory.create(qrCodeBytes))
                    .setWidth(120)
                    .setHeight(120)
                    .setHorizontalAlignment(HorizontalAlignment.CENTER)
                    .setMarginBottom(5);

            Paragraph qrTitle = new Paragraph("签到二维码")
                    .setFont(font)
                    .setFontSize(12)
                    .setBold()
                    .setTextAlignment(TextAlignment.CENTER)
                    .setMarginBottom(8);

            Paragraph ticketCode = new Paragraph("票号：" + registration.getTicketCode())
                    .setFont(font)
                    .setFontSize(9)
                    .setTextAlignment(TextAlignment.CENTER)
                    .setFontColor(ColorConstants.GRAY)
                    .setMarginBottom(0);

            rightCell.add(qrTitle);
            rightCell.add(qrCodeImage);
            rightCell.add(ticketCode);
        } catch (Exception e) {
            throw new RuntimeException("生成二维码失败", e);
        }

        mainTable.addCell(leftCell);
        mainTable.addCell(rightCell);

        document.add(mainTable);
    }

    private static void createFooter(Document document, PdfFont font) {
        SolidLine line = new SolidLine(1f);
        line.setColor(ColorConstants.LIGHT_GRAY);
        LineSeparator separator = new LineSeparator(line)
                .setMarginTop(15)
                .setMarginBottom(10)
                .setWidth(UnitValue.createPercentValue(100));
        document.add(separator);

        Paragraph notice = new Paragraph("温馨提示：请妥善保管此电子票，活动当天凭此票签到入场。请提前15分钟到达活动现场，出示电子票二维码签到。")
                .setFont(font)
                .setFontSize(9)
                .setTextAlignment(TextAlignment.CENTER)
                .setMarginBottom(10);

        document.add(notice);

        Paragraph footer = new Paragraph("本电子票由校园活动系统自动生成 | 生成时间：" + LocalDateTime.now().format(DATE_TIME_FORMATTER))
                .setFont(font)
                .setFontSize(7)
                .setTextAlignment(TextAlignment.CENTER)
                .setFontColor(ColorConstants.GRAY)
                .setMarginBottom(15);

        document.add(footer);
    }

    private static void addTableRow(Table table, String label, String value, PdfFont font, PdfFont boldFont, boolean isFirstRow) {
        Cell labelCell = new Cell()
                .add(new Paragraph(label).setFont(boldFont).setFontSize(10))
                .setPadding(4)
                .setBorder(com.itextpdf.layout.borders.Border.NO_BORDER);

        Cell valueCell = new Cell()
                .add(new Paragraph(value != null ? value : "").setFont(font).setFontSize(10))
                .setPadding(4)
                .setBorder(com.itextpdf.layout.borders.Border.NO_BORDER);

        if (isFirstRow) {
            labelCell.setBackgroundColor(new com.itextpdf.kernel.colors.DeviceRgb(240, 240, 240));
            valueCell.setBackgroundColor(new com.itextpdf.kernel.colors.DeviceRgb(240, 240, 240));
        }

        table.addCell(labelCell);
        table.addCell(valueCell);
    }

    private static String formatDateTime(LocalDateTime dateTime) {
        if (dateTime == null) {
            return "待定";
        }
        return dateTime.format(DATE_TIME_FORMATTER);
    }

    private static String formatDescription(String description) {
        if (description == null || description.isEmpty()) {
            return "暂无描述";
        }
        if (description.length() > 100) {
            return description.substring(0, 100) + "...";
        }
        return description;
    }

    private static String formatRegistrationStatus(Integer status) {
        if (status == null) {
            return "未知";
        }
        switch (status) {
            case 0:
                return "已取消";
            case 1:
                return "已报名";
            case 2:
                return "已签到";
            default:
                return "未知";
        }
    }

    private static byte[] generateQrCode(String content) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 2);

            BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, 300, 300, hints);

            MatrixToImageWriter.writeToStream(bitMatrix, "PNG", outputStream);

            return outputStream.toByteArray();
        } catch (com.google.zxing.WriterException e) {
            throw new RuntimeException("生成二维码失败", e);
        }
    }
}