package de.assecutor.votianlt.pages.view;

import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.HasDynamicTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.theme.lumo.LumoUtility;
import de.assecutor.votianlt.model.Job;
import de.assecutor.votianlt.model.JobHistory;
import de.assecutor.votianlt.model.JobHistoryType;
import de.assecutor.votianlt.model.Barcode;
import de.assecutor.votianlt.model.Photo;
import de.assecutor.votianlt.model.Signature;
import de.assecutor.votianlt.pages.base.ui.component.DialogStylingHelper;
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
import de.assecutor.votianlt.repository.BarcodeRepository;
import de.assecutor.votianlt.repository.JobRepository;
import de.assecutor.votianlt.repository.PhotoRepository;
import de.assecutor.votianlt.repository.SignatureRepository;
import de.assecutor.votianlt.service.JobHistoryService;
import de.assecutor.votianlt.util.DateTimeFormatUtil;
import jakarta.annotation.security.RolesAllowed;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;

@Route(value = "job_history", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
@RolesAllowed("USER")
@Slf4j
public class JobHistoryView extends Main implements HasUrlParameter<String>, HasDynamicTitle {

    private final JobRepository jobRepository;
    private final JobHistoryService jobHistoryService;
    private final PhotoRepository photoRepository;
    private final BarcodeRepository barcodeRepository;
    private final SignatureRepository signatureRepository;
    private final VerticalLayout content;

    public JobHistoryView(JobRepository jobRepository, JobHistoryService jobHistoryService,
            PhotoRepository photoRepository, BarcodeRepository barcodeRepository,
            SignatureRepository signatureRepository) {
        this.jobRepository = jobRepository;
        this.jobHistoryService = jobHistoryService;
        this.photoRepository = photoRepository;
        this.barcodeRepository = barcodeRepository;
        this.signatureRepository = signatureRepository;

        setSizeFull();
        addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN,
                LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
        addClassName("data-view");

        add(new ViewToolbar(getTranslation("jobhistory.title")));

        content = new VerticalLayout();
        content.setSpacing(true);
        content.setPadding(true);
        content.setWidthFull();
        content.addClassNames("form-shell", "form-card");
        add(content);
    }

    @Override
    public void setParameter(BeforeEvent event, String parameter) {
        content.removeAll();

        if (parameter == null || parameter.isBlank()) {
            content.add(new Span(getTranslation("jobhistory.error.no.id")));
            return;
        }

        ObjectId jobId;
        try {
            jobId = new ObjectId(parameter);
        } catch (Exception e) {
            content.add(new Span(getTranslation("jobhistory.error.invalid.id", parameter)));
            return;
        }

        Job job = jobRepository.findById(jobId).orElse(null);
        if (job == null) {
            content.add(new Span(getTranslation("jobhistory.error.not.found", parameter)));
            return;
        }

        render(job);
    }

    private void render(Job job) {
        content.removeAll();

        // Header mit Job-Informationen
        H2 header = new H2(getTranslation("jobhistory.header",
                job.getJobNumber() != null ? job.getJobNumber() : getTranslation("jobhistory.unknown.jobnumber")));
        content.add(header);

        // Job basic info for context
        Div jobInfoBox = createJobInfoBox(job);
        content.add(jobInfoBox);

        // Load and display history entries
        try {
            var historyEntries = jobHistoryService.getJobHistory(job.getId());
            long historyCount = jobHistoryService.getJobHistoryCount(job.getId());

            if (historyEntries.isEmpty()) {
                Span noHistory = new Span(getTranslation("jobhistory.no.entries"));
                noHistory.getStyle().set("color", "var(--lumo-secondary-text-color)");
                content.add(noHistory);
            } else {
                // History section header
                H2 historyHeader = new H2(getTranslation("jobhistory.count", historyCount));
                historyHeader.getStyle().set("margin-top", "var(--lumo-space-l)");
                content.add(historyHeader);

                // History timeline
                VerticalLayout timeline = createHistoryTimeline(historyEntries);
                content.add(timeline);
            }
        } catch (Exception e) {
            Span errorMessage = new Span(getTranslation("jobhistory.error.load", e.getMessage()));
            errorMessage.getStyle().set("color", "var(--lumo-error-text-color)");
            content.add(errorMessage);
        }
    }

    private Div createJobInfoBox(Job job) {
        Div infoBox = new Div();
        infoBox.addClassName("summary-card");
        infoBox.getStyle().set("margin-bottom", "var(--lumo-space-m)");

        VerticalLayout infoContent = new VerticalLayout();
        infoContent.setPadding(false);
        infoContent.setSpacing(false);

        if (job.getDeliveryCompany() != null) {
            infoContent.add(new Span(getTranslation("jobhistory.info.customer", job.getDeliveryCompany())));
        }
        if (job.getCreatedAt() != null) {
            infoContent.add(new Span(getTranslation("jobhistory.info.createdat", formatDateTime(job.getCreatedAt()))));
        }
        if (job.getStatus() != null) {
            infoContent.add(new Span(getTranslation("jobhistory.info.status", formatStatus(job.getStatus()))));
        }

        infoBox.add(infoContent);
        return infoBox;
    }

    private VerticalLayout createHistoryTimeline(java.util.List<JobHistory> historyEntries) {
        VerticalLayout timeline = new VerticalLayout();
        timeline.setPadding(false);
        timeline.setSpacing(false);
        timeline.setWidthFull();

        for (JobHistory entry : historyEntries) {
            Div entryCard = createHistoryEntryCard(entry);
            timeline.add(entryCard);
        }

        return timeline;
    }

    private Div createHistoryEntryCard(JobHistory entry) {
        Div card = new Div();
        card.addClassName("timeline-entry-card");
        card.setWidthFull();
        card.getStyle().set("--timeline-accent", getTypeColor(entry.getChangeType()));

        // Header row with icon, reason and timestamp
        HorizontalLayout headerRow = new HorizontalLayout();
        headerRow.setAlignItems(HorizontalLayout.Alignment.CENTER);
        headerRow.setWidthFull();

        Icon typeIcon = getTypeIcon(entry.getChangeType());
        typeIcon.getStyle().set("color", getTypeColor(entry.getChangeType()));

        Span reason = new Span(getLocalizedReason(entry));
        reason.addClassName("timeline-reason");

        Span timestamp = new Span(formatDateTime(entry.getTimestamp()));
        timestamp.addClassName("timeline-timestamp");

        HorizontalLayout leftSide = new HorizontalLayout(typeIcon, reason);
        leftSide.setAlignItems(HorizontalLayout.Alignment.CENTER);
        leftSide.setSpacing(true);

        headerRow.add(leftSide, timestamp);
        headerRow.setJustifyContentMode(HorizontalLayout.JustifyContentMode.BETWEEN);

        VerticalLayout cardContent = new VerticalLayout();
        cardContent.setPadding(false);
        cardContent.setSpacing(false);
        cardContent.add(headerRow);

        // Description
        String localizedDescription = getLocalizedDescription(entry);
        if (localizedDescription != null && !localizedDescription.isBlank()) {
            Span description = new Span(localizedDescription);
            description.addClassName("timeline-description");
            cardContent.add(description);
        }

        // Photo preview for photo tasks
        if (entry.getChangeType() == JobHistoryType.TASK_COMPLETED && entry.getDetails() != null
                && entry.getDetails().contains("Task-Typ: PHOTO")) {

            HorizontalLayout photoPreview = createPhotoPreview(entry);
            if (photoPreview != null) {
                cardContent.add(photoPreview);
            }
        }

        // Barcode preview for barcode tasks
        if (entry.getChangeType() == JobHistoryType.TASK_COMPLETED && entry.getDetails() != null
                && entry.getDetails().contains("Task-Typ: BARCODE")) {

            VerticalLayout barcodePreview = createBarcodePreview(entry);
            if (barcodePreview != null) {
                cardContent.add(barcodePreview);
            }
        }

        // Signature preview for signature tasks
        if (entry.getChangeType() == JobHistoryType.TASK_COMPLETED && entry.getDetails() != null
                && entry.getDetails().contains("Task-Typ: SIGNATURE")) {

            Div signaturePreview = createSignaturePreview(entry);
            if (signaturePreview != null) {
                cardContent.add(signaturePreview);
            }
        }

        // Changed by (if available)
        if (entry.getChangedBy() != null && !entry.getChangedBy().isBlank()) {
            Span changedBy = new Span(getTranslation("jobhistory.changedby", entry.getChangedBy()));
            changedBy.getStyle().set("color", "var(--lumo-secondary-text-color)")
                    .set("font-size", "var(--lumo-font-size-xs)").set("margin-top", "var(--lumo-space-xs)")
                    .set("display", "block");
            cardContent.add(changedBy);
        }

        card.add(cardContent);

        return card;
    }

    private String getLocalizedReason(JobHistory entry) {
        if (entry == null) {
            return "";
        }
        if (entry.getChangeType() == JobHistoryType.CREATE) {
            return getTranslation("jobhistory.entry.create.reason");
        }
        return entry.getReason() != null ? entry.getReason() : "";
    }

    private String getLocalizedDescription(JobHistory entry) {
        if (entry == null || entry.getDescription() == null || entry.getDescription().isBlank()) {
            return entry != null ? entry.getDescription() : "";
        }
        if (entry.getChangeType() == JobHistoryType.CREATE) {
            return getTranslation("jobhistory.entry.create.description", extractDescriptionValue(entry.getDescription()));
        }
        return entry.getDescription();
    }

    private String extractDescriptionValue(String description) {
        if (description == null || description.isBlank()) {
            return "";
        }
        int separatorIndex = description.indexOf(':');
        if (separatorIndex < 0 || separatorIndex == description.length() - 1) {
            return description.trim();
        }
        return description.substring(separatorIndex + 1).trim();
    }

    private Icon getTypeIcon(JobHistoryType type) {
        if (type == null)
            return new Icon(VaadinIcon.INFO_CIRCLE);

        return switch (type) {
        case CREATE -> new Icon(VaadinIcon.PLUS_CIRCLE);
        case UPDATE -> new Icon(VaadinIcon.EDIT);
        case STATUS_CHANGE -> new Icon(VaadinIcon.ARROW_RIGHT);
        case TASK_COMPLETED -> new Icon(VaadinIcon.CHECK);
        case ASSIGNMENT -> new Icon(VaadinIcon.USER);
        case EXPORT -> new Icon(VaadinIcon.DOWNLOAD);
        case DELETE -> new Icon(VaadinIcon.TRASH);
        case SYSTEM -> new Icon(VaadinIcon.COG);
        case COMMENT -> new Icon(VaadinIcon.COMMENT);
        default -> new Icon(VaadinIcon.INFO_CIRCLE);
        };
    }

    private String getTypeColor(JobHistoryType type) {
        if (type == null)
            return "var(--lumo-contrast-60pct)";

        return switch (type) {
        case CREATE -> "var(--lumo-success-color)";
        case UPDATE -> "var(--lumo-primary-color)";
        case STATUS_CHANGE -> "var(--lumo-contrast-color)";
        case TASK_COMPLETED -> "var(--lumo-success-color)";
        case ASSIGNMENT -> "var(--lumo-primary-color)";
        case EXPORT -> "var(--lumo-contrast-color)";
        case DELETE -> "var(--lumo-error-color)";
        case SYSTEM -> "var(--lumo-contrast-60pct)";
        case COMMENT -> "var(--lumo-primary-color)";
        default -> "var(--lumo-contrast-60pct)";
        };
    }

    private String formatDateTime(java.time.LocalDateTime dateTime) {
        if (dateTime == null)
            return "";
        try {
            return DateTimeFormatUtil.formatDateTime(dateTime);
        } catch (Exception e) {
            return dateTime.toString();
        }
    }

    private String formatStatus(de.assecutor.votianlt.model.JobStatus status) {
        if (status == null)
            return "";

        return switch (status) {
        case CREATED -> getTranslation("jobstatus.CREATED");
        case IN_PROGRESS -> getTranslation("jobstatus.IN_PROGRESS");
        case PICKUP_SCHEDULED -> getTranslation("jobhistory.status.pickupscheduled");
        case PICKED_UP -> getTranslation("jobhistory.status.pickedup");
        case IN_TRANSIT -> getTranslation("jobhistory.status.intransit");
        case DELIVERED -> getTranslation("jobhistory.status.delivered");
        case COMPLETED -> getTranslation("jobstatus.COMPLETED");
        case CANCELLED -> getTranslation("jobstatus.CANCELLED");
        };
    }

    private HorizontalLayout createPhotoPreview(JobHistory entry) {
        try {
            // Extract task ID from details
            String details = entry.getDetails();
            if (details == null || !details.contains("Task-ID: ")) {
                return null;
            }

            String taskId = extractTaskIdFromDetails(details);
            if (taskId == null) {
                return null;
            }

            // Load photos for this task
            var photos = photoRepository.findByTaskId(taskId);
            if (photos.isEmpty()) {
                return null;
            }

            HorizontalLayout photoLayout = new HorizontalLayout();
            photoLayout.setSpacing(true);
            photoLayout.getStyle().set("margin-top", "var(--lumo-space-s)").set("flex-wrap", "wrap");

            for (Photo photo : photos) {
                if (photo.getPhoto() != null && !photo.getPhoto().isBlank()) {
                    com.vaadin.flow.component.html.Image thumbnail = createPhotoThumbnail(photo.getPhoto());
                    if (thumbnail != null) {
                        thumbnail.addClickListener(e -> showEnlargedPhoto(photo.getPhoto()));
                        photoLayout.add(thumbnail);
                    }
                }
            }

            return photoLayout.getComponentCount() > 0 ? photoLayout : null;

        } catch (Exception e) {
            log.error("Error creating photo preview for history entry: {}", e.getMessage());
            return null;
        }
    }

    private String extractTaskIdFromDetails(String details) {
        try {
            String prefix = "Task-ID: ";
            int startIndex = details.indexOf(prefix);
            if (startIndex == -1) {
                return null;
            }

            startIndex += prefix.length();
            int endIndex = details.indexOf(",", startIndex);
            if (endIndex == -1) {
                endIndex = details.length();
            }

            return details.substring(startIndex, endIndex).trim();
        } catch (Exception e) {
            return null;
        }
    }

    private com.vaadin.flow.component.html.Image createPhotoThumbnail(String base64Photo) {
        try {
            String imageData = base64Photo.startsWith("data:") ? base64Photo : "data:image/jpeg;base64," + base64Photo;

            com.vaadin.flow.component.html.Image thumbnail = new com.vaadin.flow.component.html.Image(imageData,
                    "Foto");
            thumbnail.getStyle().set("width", "100px").set("height", "100px").set("object-fit", "cover")
                    .set("border-radius", "var(--lumo-border-radius-s)")
                    .set("border", "1px solid var(--lumo-contrast-20pct)").set("cursor", "pointer");

            return thumbnail;
        } catch (Exception e) {
            log.error("Error creating photo thumbnail: {}", e.getMessage());
            return null;
        }
    }

    private void showEnlargedPhoto(String base64Photo) {
        Dialog photoDialog = DialogStylingHelper.createStyledDialog(getTranslation("jobhistory.image.alt"), "80vw");
        photoDialog.setHeight("80vh");
        photoDialog.setModal(true);
        photoDialog.setCloseOnOutsideClick(true);
        photoDialog.setCloseOnEsc(true);

        try {
            String imageData = base64Photo.startsWith("data:") ? base64Photo : "data:image/jpeg;base64," + base64Photo;

            com.vaadin.flow.component.html.Image enlargedImage = new com.vaadin.flow.component.html.Image(imageData,
                    "Vergrößertes Foto");
            enlargedImage.getStyle().set("max-width", "100%").set("max-height", "100%").set("object-fit", "contain");

            VerticalLayout dialogContent = new VerticalLayout(enlargedImage);
            dialogContent.setAlignItems(VerticalLayout.Alignment.CENTER);
            dialogContent.setJustifyContentMode(VerticalLayout.JustifyContentMode.CENTER);
            dialogContent.setSizeFull();

            photoDialog.add(DialogStylingHelper.wrapContent(dialogContent, true));
            photoDialog.open();

        } catch (Exception e) {
            log.error("Error showing enlarged photo: {}", e.getMessage());
        }
    }

    private VerticalLayout createBarcodePreview(JobHistory entry) {
        try {
            // Extract task ID from details
            String details = entry.getDetails();
            if (details == null || !details.contains("Task-ID: ")) {
                return null;
            }

            String taskId = extractTaskIdFromDetails(details);
            if (taskId == null) {
                return null;
            }

            // Load barcodes for this task
            ObjectId taskObjectId = new ObjectId(taskId);
            var barcodes = barcodeRepository.findByTaskId(taskObjectId);
            if (barcodes.isEmpty()) {
                return null;
            }

            VerticalLayout barcodeLayout = new VerticalLayout();
            barcodeLayout.setPadding(false);
            barcodeLayout.setSpacing(true);
            barcodeLayout.getStyle().set("margin-top", "var(--lumo-space-s)");

            for (Barcode barcode : barcodes) {
                if (barcode.getBarcode() != null && !barcode.getBarcode().isBlank()) {
                    Div barcodeBox = createBarcodeBox(barcode.getBarcode());
                    barcodeLayout.add(barcodeBox);
                }
            }

            return barcodeLayout.getComponentCount() > 0 ? barcodeLayout : null;

        } catch (Exception e) {
            log.error("Error creating barcode preview for history entry: {}", e.getMessage());
            return null;
        }
    }

    private Div createBarcodeBox(String barcodeValue) {
        Div barcodeBox = new Div();
        barcodeBox.addClassNames("detail-card", "detail-card--code");
        barcodeBox.getStyle().set("font-size", "var(--lumo-font-size-s)").set("margin-bottom", "var(--lumo-space-xs)");

        barcodeBox.add(new Span(barcodeValue));
        return barcodeBox;
    }

    private Div createSignaturePreview(JobHistory entry) {
        try {
            // Extract task ID from details
            String details = entry.getDetails();
            if (details == null || !details.contains("Task-ID: ")) {
                return null;
            }

            String taskId = extractTaskIdFromDetails(details);
            if (taskId == null) {
                return null;
            }

            // Load signature for this task
            ObjectId taskObjectId = new ObjectId(taskId);
            var signatures = signatureRepository.findByTaskId(taskObjectId);
            if (signatures.isEmpty()) {
                return null;
            }

            // Use the first signature
            Signature signature = signatures.getFirst();
            if (signature.getSignatureSvg() == null || signature.getSignatureSvg().isBlank()) {
                return null;
            }

            Div previewContainer = new Div();
            previewContainer.getStyle().set("margin-top", "var(--lumo-space-s)")
                    .set("border", "1px solid var(--lumo-contrast-20pct)")
                    .set("border-radius", "var(--lumo-border-radius-s)").set("padding", "var(--lumo-space-xs)")
                    .set("background-color", "var(--lumo-base-color)").set("cursor", "pointer").set("width", "200px")
                    .set("height", "100px").set("overflow", "hidden").set("display", "flex")
                    .set("align-items", "center").set("justify-content", "center");

            // Create responsive SVG for preview
            com.vaadin.flow.component.Html signatureSvg = createResponsiveSignatureSvg(signature.getSignatureSvg(),
                    "100%", "100%");
            previewContainer.add(signatureSvg);

            // Add click listener for enlarged view
            previewContainer.addClickListener(e -> showEnlargedSignature(signature.getSignatureSvg()));

            return previewContainer;

        } catch (Exception e) {
            log.error("Error creating signature preview for history entry: {}", e.getMessage());
            return null;
        }
    }

    private com.vaadin.flow.component.Html createResponsiveSignatureSvg(String svgContent, String width,
            String height) {
        // Make SVG responsive by ensuring proper viewBox and dimensions
        String responsiveSvg = svgContent;

        if (!responsiveSvg.contains("viewBox")) {
            // Try to extract width and height from SVG and create viewBox
            responsiveSvg = responsiveSvg.replaceFirst("<svg",
                    "<svg viewBox=\"0 0 300 150\" preserveAspectRatio=\"xMidYMid meet\"");
        }

        // Ensure the SVG has proper responsive attributes
        if (!responsiveSvg.contains("preserveAspectRatio")) {
            responsiveSvg = responsiveSvg.replaceFirst("<svg", "<svg preserveAspectRatio=\"xMidYMid meet\"");
        }

        // Set responsive dimensions
        responsiveSvg = responsiveSvg.replaceFirst("width=\"[^\"]*\"", "width=\"" + width + "\"");
        responsiveSvg = responsiveSvg.replaceFirst("height=\"[^\"]*\"", "height=\"" + height + "\"");

        return new com.vaadin.flow.component.Html(
                "<div style=\"width: " + width + "; height: " + height + ";\">" + responsiveSvg + "</div>");
    }

    @Override
    public String getPageTitle() {
        return getTranslation("page.title.job.history");
    }

    private void showEnlargedSignature(String svgContent) {
        Dialog signatureDialog = DialogStylingHelper.createStyledDialog(getTranslation("tasktype.SIGNATURE"), "60vw");
        signatureDialog.setHeight("40vh");
        signatureDialog.setModal(true);
        signatureDialog.setCloseOnOutsideClick(true);
        signatureDialog.setCloseOnEsc(true);

        try {
            // Create enlarged responsive SVG
            com.vaadin.flow.component.Html enlargedSignature = createResponsiveSignatureSvg(svgContent, "100%", "100%");

            VerticalLayout dialogContent = new VerticalLayout();
            dialogContent.setAlignItems(VerticalLayout.Alignment.CENTER);
            dialogContent.setJustifyContentMode(VerticalLayout.JustifyContentMode.CENTER);
            dialogContent.setSizeFull();
            dialogContent.setPadding(true);

            dialogContent.add(enlargedSignature);
            signatureDialog.add(DialogStylingHelper.wrapContent(dialogContent, true));
            signatureDialog.open();

        } catch (Exception e) {
            log.error("Error showing enlarged signature: {}", e.getMessage());
        }
    }
}
