package org.example.petshopdesktop.controllers;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import org.example.petshopdesktop.api.endpoints.ChatApi;
import org.example.petshopdesktop.api.ChatRealtimeClient;
import org.example.petshopdesktop.api.dto.auth.AvatarUploadResponse;
import org.example.petshopdesktop.api.dto.auth.UserInfoResponse;
import org.example.petshopdesktop.api.endpoints.AuthApi;
import org.example.petshopdesktop.auth.UserSession;
import org.example.petshopdesktop.util.FilePickerSupport;
import org.example.petshopdesktop.ui.SvgWebViewFactory;
import org.example.petshopdesktop.util.ActivityLogger;

import java.io.ByteArrayInputStream;

public class MainLayoutController {

    private int avatarExifOrientation = 1;

    private static final String NAV_BASE_STYLE = "-fx-background-color: transparent; " +
            "-fx-text-fill: #cbd5e1; " +
            "-fx-background-radius: 10; " +
            "-fx-cursor: hand; " +
            "-fx-focus-color: transparent; " +
            "-fx-faint-focus-color: transparent;";

    private static final String NAV_ACTIVE_STYLE = "-fx-background-color: #FF6B6B; " +
            "-fx-text-fill: white; " +
            "-fx-background-radius: 10; " +
            "-fx-cursor: hand; " +
            "-fx-focus-color: transparent; " +
            "-fx-faint-focus-color: transparent; " +
            "-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.22), 10, 0.15, 0, 2);";

    @FXML
    private Button btnAdoptions;

    @FXML
    private Button btnAppointments;

    @FXML
    private Button btnInventory;

    @FXML
    private Button btnChat;

    @FXML
    private Circle chatBadge;

    @FXML
    private Button btnPets;

    @FXML
    private Button btnProductSuppliers;

    @FXML
    private Button btnProducts;

    @FXML
    private Button btnActivityLogs;

    @FXML
    private Button btnSalesHistory;

    @FXML
    private Button btnPurchaseOrders;

    @FXML
    private Button btnServices;

    @FXML
    private Button btnSuppliers;

    @FXML
    private Button btnStaffAccounts;

    @FXML
    private Button btnCustomers;

    @FXML
    private Button btnAnalytics;

    @FXML
    private Button btnCoupons;

    @FXML
    private Button btnLogout;

    @FXML
    private StackPane logoContainer;

    @FXML
    private StackPane avatarPreview;

    @FXML
    private Button btnChangeAvatar;

    @FXML
    private Button btnRemoveAvatar;

    @FXML
    private Button btnRefreshAvatar;

    @FXML
    private Label lblUsername;

    @FXML
    private Label lblRole;

    @FXML
    private Label lblAdminSection;

    @FXML
    private Separator separatorAdmin;

    @FXML
    private StackPane spContentArea;

    @FXML
    void btnAdoptionsClicked(ActionEvent event) {
        loadView("adoption-view.fxml");
        updateButtons(btnAdoptions);
    }

    @FXML
    void btnAppointmentsClicked(ActionEvent event) {
        loadView("appointment-view.fxml");
        updateButtons(btnAppointments);
    }

    @FXML
    void btnInventoryClicked(ActionEvent event) {
        loadView("inventory-view.fxml");
        updateButtons(btnInventory);
    }

    @FXML
    void btnPetsClicked(ActionEvent event) {
        loadView("pet-view.fxml");
        updateButtons(btnPets);
    }

    @FXML
    void btnProductSuppliersClicked(ActionEvent event) {
        loadView("product-supplier-view.fxml");
        updateButtons(btnProductSuppliers);
    }

    @FXML
    void btnProductsClicked(ActionEvent event) {
        loadView("product-view.fxml");
        updateButtons(btnProducts);
    }

    @FXML
    void btnSalesHistoryClicked(ActionEvent event) {
        loadView("sale-view.fxml");
        updateButtons(btnSalesHistory);
    }

    @FXML
    void btnPurchaseOrdersClicked(ActionEvent event) {
        loadView("purchase-order-view.fxml");
        updateButtons(btnPurchaseOrders);
    }

    @FXML
    void btnStaffAccountsClicked(ActionEvent event) {
        loadView("staff-accounts-view.fxml");
        updateButtons(btnStaffAccounts);
    }

    @FXML
    void btnCustomersClicked(ActionEvent event) {
        loadView("customer-accounts-view.fxml");
        updateButtons(btnCustomers);
    }

    @FXML
    void btnAnalyticsClicked(ActionEvent event) {
        loadView("analytics-view.fxml");
        updateButtons(btnAnalytics);
    }

    @FXML
    void btnActivityLogsClicked(ActionEvent event) {
        loadView("activity-log-view.fxml");
        updateButtons(btnActivityLogs);
    }

    @FXML
    void btnCouponsClicked(ActionEvent event) {
        loadView("coupon-view.fxml");
        updateButtons(btnCoupons);
    }

    @FXML
    void btnServicesClicked(ActionEvent event) {
        loadView("service-view.fxml");
        updateButtons(btnServices);
    }

    @FXML
    void btnSuppliersClicked(ActionEvent event) {
        loadView("supplier-view.fxml");
        updateButtons(btnSuppliers);
    }

    @FXML
    void btnChatClicked(ActionEvent event) {
        loadView("chat-view.fxml");
        updateButtons(btnChat);
    }

    @FXML
    void logoClicked(MouseEvent event) {
        UserSession session = UserSession.getInstance();
        if (session.isAdmin()) {
            loadView("analytics-view.fxml");
            updateButtons(btnAnalytics);
        } else {
            loadView("sale-view.fxml");
            updateButtons(btnSalesHistory);
        }
    }

    @FXML
    void btnChangeAvatarClicked(ActionEvent event) {
        java.io.File file = FilePickerSupport.pickImageFile(btnChangeAvatar.getScene().getWindow());
        if (file == null) {
            return;
        }

        try {
            AvatarUploadResponse response = AuthApi.getInstance().uploadAvatar(file.toPath());
            UserSession.getInstance().setAvatarUrl(response.getAvatarUrl());
            refreshProfileHeader();
        } catch (Exception e) {
            ActivityLogger.getInstance().logException("MainLayoutController.btnChangeAvatarClicked", e, "Uploading avatar");
            showAvatarError(e.getMessage() != null ? e.getMessage() : "Could not upload profile picture.");
        }
    }

    @FXML
    void btnRefreshAvatarClicked(ActionEvent event) {
        btnRefreshAvatar.setDisable(true);
        new Thread(() -> {
            try {
                UserInfoResponse userInfo = AuthApi.getInstance().getCurrentUser();
                String displayName = userInfo.getFullName() == null || userInfo.getFullName().isBlank()
                    ? UserSession.getInstance().getUsername()
                    : userInfo.getFullName();
                Image avatarImage = loadAvatarImage(userInfo.getAvatarUrl());
                Platform.runLater(() -> {
                    UserSession.getInstance().setAvatarUrl(userInfo.getAvatarUrl());
                    renderAvatar(displayName, avatarImage);
                    btnRemoveAvatar.setDisable(userInfo.getAvatarUrl() == null || userInfo.getAvatarUrl().isBlank());
                    btnRefreshAvatar.setDisable(false);
                });
            } catch (Exception e) {
                Platform.runLater(() -> btnRefreshAvatar.setDisable(false));
                ActivityLogger.getInstance().logException("MainLayoutController.btnRefreshAvatarClicked", e, "Refreshing avatar");
            }
        }).start();
    }

    @FXML
    void btnRemoveAvatarClicked(ActionEvent event) {
        try {
            AuthApi.getInstance().deleteAvatar();
            UserSession.getInstance().setAvatarUrl(null);
            renderAvatar(UserSession.getInstance().getEmployeeName(), null);
            btnRemoveAvatar.setDisable(true);
        } catch (Exception e) {
            ActivityLogger.getInstance().logException("MainLayoutController.btnRemoveAvatarClicked", e, "Deleting avatar");
            showAvatarError(e.getMessage() != null ? e.getMessage() : "Could not remove profile picture.");
        }
    }

    @FXML
    void btnLogoutClicked(ActionEvent event) {
        ChatRealtimeClient.getInstance().disconnect();
        UserSession.getInstance().logout();
        try {
            FXMLLoader loader = new FXMLLoader(
                    getClass().getResource("/org/example/petshopdesktop/login-view.fxml"));
            Scene scene = new Scene(loader.load());
            Stage stage = (Stage) btnLogout.getScene().getWindow();
            stage.setScene(scene);
            stage.setTitle("Pet Shop Manager - Login");
        } catch (Exception e) {
            ActivityLogger.getInstance().logException(
                "MainLayoutController.btnLogoutClicked",
                e,
                "Loading login view after logout");
            System.err.println("Error loading login view: " + e.getMessage());
            e.printStackTrace();
        }
    }

    @FXML
    public void initialize() {
        logoContainer.getChildren().setAll(SvgWebViewFactory.build("/org/example/petshopdesktop/images/leons-pet-store-badge-light.svg", 94));
        renderAvatar(UserSession.getInstance().getEmployeeName(), null);
        btnRemoveAvatar.setDisable(UserSession.getInstance().getAvatarUrl() == null || UserSession.getInstance().getAvatarUrl().isBlank());
        refreshProfileHeader();
        applyRBAC();

        ChatRealtimeClient.getInstance().addNotificationListener(hasActionable -> {
            Platform.runLater(() -> {
                if (chatBadge != null) {
                    chatBadge.setVisible(hasActionable);
                }
            });
        });

        UserSession session = UserSession.getInstance();
        if (session.isAdmin()) {
            loadView("analytics-view.fxml");
            updateButtons(btnAnalytics);
        } else {
            loadView("sale-view.fxml");
            updateButtons(btnSalesHistory);
        }
    }

    private void refreshProfileHeader() {
        new Thread(() -> {
            try {
                UserInfoResponse userInfo = AuthApi.getInstance().getCurrentUser();
                String displayName = userInfo.getFullName() == null || userInfo.getFullName().isBlank()
                    ? UserSession.getInstance().getUsername()
                    : userInfo.getFullName();
                Image avatarImage = loadAvatarImage(userInfo.getAvatarUrl());
                Platform.runLater(() -> {
                    UserSession.getInstance().setEmployeeName(displayName);
                    UserSession.getInstance().setAvatarUrl(userInfo.getAvatarUrl());
                    lblUsername.setText(displayName);
                    renderAvatar(displayName, avatarImage);
                    btnRemoveAvatar.setDisable(userInfo.getAvatarUrl() == null || userInfo.getAvatarUrl().isBlank());
                });
            } catch (Exception e) {
                Platform.runLater(() -> renderAvatar(UserSession.getInstance().getEmployeeName(), null));
            }
        }).start();
    }

    private Image loadAvatarImage(String avatarUrl) {
        if (avatarUrl == null || avatarUrl.isBlank()) {
            return null;
        }

        try {
            byte[] imageBytes = AuthApi.getInstance().getMyAvatarFile();
            avatarExifOrientation = readExifOrientation(imageBytes);
            Image image = new Image(new ByteArrayInputStream(imageBytes), 200, 200, true, true);
            return image.isError() ? null : image;
        } catch (Exception e) {
            avatarExifOrientation = 1;
            return null;
        }
    }

    private void renderAvatar(String displayName, Image avatarImage) {
        Circle border = new Circle(29);
        border.setFill(Color.web("#dbe4ee"));

        if (avatarImage != null) {
            double imgW = avatarImage.getWidth();
            double imgH = avatarImage.getHeight();
            double cropSize = Math.min(imgW, imgH);
            double cropX = (imgW - cropSize) / 2;
            double cropY = (imgH - cropSize) / 2;

            javafx.scene.image.ImageView imageView = new javafx.scene.image.ImageView(avatarImage);
            imageView.setViewport(new javafx.geometry.Rectangle2D(cropX, cropY, cropSize, cropSize));
            imageView.setFitWidth(52);
            imageView.setFitHeight(52);
            imageView.setPreserveRatio(false);
            imageView.setRotate(exifOrientationToAngle(avatarExifOrientation));

            Circle clip = new Circle(26, 26, 26);
            imageView.setClip(clip);

            avatarPreview.getChildren().setAll(border, imageView);
        } else {
            Circle circle = new Circle(26);
            circle.setFill(Color.web("#4ECDC4"));
            Label initials = new Label(initials(displayName));
            initials.setStyle("-fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 16px;");
            avatarPreview.getChildren().setAll(border, circle, initials);
        }
    }

    private String initials(String displayName) {
        if (displayName == null || displayName.isBlank()) {
            return "?";
        }

        String[] parts = displayName.trim().split("\\s+");
        if (parts.length == 1) {
            return parts[0].substring(0, 1).toUpperCase();
        }
        return (parts[0].substring(0, 1) + parts[parts.length - 1].substring(0, 1)).toUpperCase();
    }

    private void showAvatarError(String message) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setTitle("Profile Picture");
        alert.setHeaderText(null);
        alert.setContentText(message);
        alert.showAndWait();
    }

    private void applyRBAC() {
        UserSession session = UserSession.getInstance();

        String displayName = session.getEmployeeName();
        if (displayName == null || displayName.isBlank()) {
            displayName = session.getUsername();
        }
        lblUsername.setText(displayName == null ? "" : displayName);
        lblRole.setText("Leon's Petstore");

        boolean isAdmin = session.isAdmin();
        boolean canViewAnalytics = isAdmin || session.isStaff();
        btnInventory.setVisible(isAdmin);
        btnInventory.setManaged(isAdmin);
        btnSuppliers.setVisible(isAdmin);
        btnSuppliers.setManaged(isAdmin);
        btnProductSuppliers.setVisible(isAdmin);
        btnProductSuppliers.setManaged(isAdmin);

        btnPurchaseOrders.setVisible(isAdmin);
        btnPurchaseOrders.setManaged(isAdmin);

        if (btnStaffAccounts != null) {
            btnStaffAccounts.setVisible(isAdmin);
            btnStaffAccounts.setManaged(isAdmin);
        }

        if (btnCustomers != null) {
            btnCustomers.setVisible(true);
            btnCustomers.setManaged(true);
        }

        if (lblAdminSection != null) {
            lblAdminSection.setVisible(isAdmin);
            lblAdminSection.setManaged(isAdmin);
        }

        if (separatorAdmin != null) {
            separatorAdmin.setVisible(isAdmin);
            separatorAdmin.setManaged(isAdmin);
        }

        if (btnAnalytics != null) {
            btnAnalytics.setVisible(canViewAnalytics);
            btnAnalytics.setManaged(canViewAnalytics);
        }

        if (btnActivityLogs != null) {
            btnActivityLogs.setVisible(isAdmin);
            btnActivityLogs.setManaged(isAdmin);
        }

        if (btnCoupons != null) {
            btnCoupons.setVisible(isAdmin);
            btnCoupons.setManaged(isAdmin);
        }

        btnSalesHistory.setText(isAdmin ? "Sales History" : "Sales");

        // Initial chat state and subscription
        new Thread(() -> {
            try {
                var conversations = ChatApi.getInstance().listConversations();
                ChatRealtimeClient.getInstance().initializeState(conversations);
                ChatRealtimeClient.getInstance().subscribeToConversations();
            } catch (Exception e) {
                ActivityLogger.getInstance().logException("MainLayoutController.applyRBAC", e, "Initializing chat notifications");
            }
        }).start();
    }

    private void loadView(String fxmlFile) {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/modelviews/" + fxmlFile));
            Parent view = loader.load();
            spContentArea.getChildren().clear();
            spContentArea.getChildren().add(view);
        } catch (Exception e) {
            ActivityLogger.getInstance().logException(
                "MainLayoutController.loadView",
                e,
                "Loading view: " + fxmlFile);
            System.err.println("Error loading view: " + fxmlFile);
            e.printStackTrace();

            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("View Load Error");
            alert.setHeaderText("Failed to load: " + fxmlFile);
            alert.setContentText("Error: " + e.getMessage() + "\n\nCheck console for details.");
            alert.showAndWait();
        }
    }

    private void updateButtons(Button activeButton) {
        Button[] buttons = {
            btnAdoptions,
            btnPets,
            btnAppointments,
            btnInventory,
            btnSalesHistory,
            btnServices,
            btnSuppliers,
            btnProductSuppliers,
            btnProducts,
            btnPurchaseOrders,
            btnStaffAccounts,
            btnCustomers,
            btnAnalytics,
            btnActivityLogs,
            btnCoupons,
            btnChat
        };

        for (Button button : buttons) {
            if (button != null) {
                button.setStyle(NAV_BASE_STYLE);
            }
        }

        if (activeButton != null) {
            activeButton.setStyle(NAV_ACTIVE_STYLE);
        }
    }

    private double exifOrientationToAngle(int orientation) {
        return switch (orientation) {
            case 3 -> 180;
            case 6 -> 90;
            case 8 -> -90;
            default -> 0;
        };
    }

    private int readExifOrientation(byte[] data) {
        try {
            if (data.length < 2 || (data[0] & 0xFF) != 0xFF || (data[1] & 0xFF) != 0xD8) return 1;
            int offset = 2;
            while (offset + 4 < data.length) {
                if ((data[offset] & 0xFF) != 0xFF) break;
                int marker = data[offset + 1] & 0xFF;
                int segLen = ((data[offset + 2] & 0xFF) << 8) | (data[offset + 3] & 0xFF);
                if (marker == 0xE1 && offset + 9 < data.length
                        && data[offset + 4] == 'E' && data[offset + 5] == 'x'
                        && data[offset + 6] == 'i' && data[offset + 7] == 'f'
                        && data[offset + 8] == 0 && data[offset + 9] == 0) {
                    int tiff = offset + 10;
                    boolean le = data[tiff] == 'I';
                    int ifdOffset = readInt(data, tiff + 4, le);
                    int ifd = tiff + ifdOffset;
                    int entries = readShort(data, ifd, le);
                    for (int i = 0; i < entries; i++) {
                        int e = ifd + 2 + i * 12;
                        if (e + 9 < data.length && readShort(data, e, le) == 0x0112) {
                            return readShort(data, e + 8, le);
                        }
                    }
                }
                if (marker == 0xDA) break;
                offset += 2 + segLen;
            }
        } catch (Exception ignored) {}
        return 1;
    }

    private int readShort(byte[] data, int offset, boolean le) {
        return le
                ? (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8)
                : ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
    }

    private int readInt(byte[] data, int offset, boolean le) {
        return le
                ? (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8) | ((data[offset + 2] & 0xFF) << 16) | ((data[offset + 3] & 0xFF) << 24)
                : ((data[offset] & 0xFF) << 24) | ((data[offset + 1] & 0xFF) << 16) | ((data[offset + 2] & 0xFF) << 8) | (data[offset + 3] & 0xFF);
    }

}
