package org.example.petshopdesktop.controllers.dialogcontrollers;

import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceDialog;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
import org.example.petshopdesktop.api.dto.adoption.AdoptionRequest;
import org.example.petshopdesktop.api.dto.common.DropdownOption;
import org.example.petshopdesktop.api.endpoints.AdoptionApi;
import org.example.petshopdesktop.api.endpoints.DropdownApi;
import org.example.petshopdesktop.auth.UserSession;
import org.example.petshopdesktop.models.Adoption;
import org.example.petshopdesktop.util.ActivityLogger;

import java.time.LocalDate;
import java.util.List;
import java.util.Objects;

public class AdoptionDialogController {

    @FXML
    private Button btnCancel;

    @FXML
    private Button btnSave;

    @FXML
    private ComboBox<String> cbAdoptionStatus;

    @FXML
    private ComboBox<DropdownOption> cbCustomer;

    @FXML
    private ComboBox<DropdownOption> cbEmployee;

    @FXML
    private ComboBox<DropdownOption> cbPet;

    @FXML
    private DatePicker dpAdoptionDate;

    @FXML
    private Label lblAdoptionId;

    @FXML
    private Label lblMode;

    private String mode = null;
    private Adoption selectedAdoption = null;
    private String selectedPaymentMethod = null;
    private boolean suppressPaymentDialog = false;

    private ObservableList<String> statusList = FXCollections.observableArrayList(
            "Pending", "Completed", "Cancelled"
    );

    @FXML
    void initialize() {

        cbAdoptionStatus.setItems(statusList);
        cbAdoptionStatus.valueProperty().addListener((obs, oldVal, newVal) -> {
            if ("Completed".equals(newVal) && !"Completed".equals(oldVal) && !suppressPaymentDialog) {
                ChoiceDialog<String> dialog = new ChoiceDialog<>("Cash", "Cash", "Credit Card", "Debit Card", "E-Transfer");
                dialog.setTitle("Payment Method");
                dialog.setHeaderText("Confirm payment received");
                dialog.setContentText("Select payment method:");
                dialog.showAndWait().ifPresentOrElse(
                    method -> selectedPaymentMethod = method,
                    () -> {
                        selectedPaymentMethod = null;
                        cbAdoptionStatus.setValue(oldVal);
                    }
                );
            } else if (!"Completed".equals(newVal)) {
                selectedPaymentMethod = null;
            }
        });
        cbEmployee.setPromptText("Select an employee");

        new Thread(() -> {
            try {
                List<DropdownOption> pets = DropdownApi.getInstance().getAdoptionPets();
                Platform.runLater(() -> {
                    if (pets != null) {
                        ObservableList<DropdownOption> petsObs = FXCollections.observableArrayList(pets);
                        ensureSelectedPetOption(petsObs);
                        cbPet.setItems(petsObs);
                        applySelectedPet();
                    }
                });
            } catch (Exception e) {
                Platform.runLater(() -> {
                    ActivityLogger.getInstance().logException(
                        "AdoptionDialogController.initialize",
                        e,
                        "Loading pets for combo box");
                    System.out.println("Error loading pets: " + e.getMessage());
                });
            }
        }).start();

        new Thread(() -> {
            try {
                List<DropdownOption> employees = DropdownApi.getInstance().getEmployees();
                Platform.runLater(() -> {
                    ObservableList<DropdownOption> employeesObs = FXCollections.observableArrayList(employees);
                    ensureSelectedEmployeeOption(employeesObs);
                    cbEmployee.setItems(employeesObs);
                    applySelectedEmployee();
                });
            } catch (Exception e) {
                Platform.runLater(() -> {
                    ActivityLogger.getInstance().logException(
                            "AdoptionDialogController.initialize",
                            e,
                            "Loading employees for combo box");
                    cbEmployee.setDisable(true);
                    cbEmployee.setPromptText("Unable to load employees");
                });
            }
        }).start();

        cbEmployee.setCellFactory(param -> new ListCell<>() {
            @Override
            protected void updateItem(DropdownOption option, boolean empty) {
                super.updateItem(option, empty);
                setText(empty || option == null ? null : option.getLabel());
            }
        });
        cbEmployee.setButtonCell(new ListCell<>() {
            @Override
            protected void updateItem(DropdownOption option, boolean empty) {
                super.updateItem(option, empty);
                setText(empty || option == null ? null : option.getLabel());
            }
        });

        new Thread(() -> {
            try {
                List<DropdownOption> customers = DropdownApi.getInstance().getCustomers();
                Platform.runLater(() -> {
                    if (customers != null) {
                        ObservableList<DropdownOption> customersObs = FXCollections.observableArrayList(customers);
                        cbCustomer.setItems(customersObs);
                        applySelectedCustomer();
                    }
                });
            } catch (Exception e) {
                Platform.runLater(() -> {
                    ActivityLogger.getInstance().logException(
                        "AdoptionDialogController.initialize",
                        e,
                        "Loading customers for combo box");
                    System.out.println("Error loading customers: " + e.getMessage());
                });
            }
        }).start();

        btnSave.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                buttonSaveClicked(mouseEvent);
            }
        });

        btnCancel.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                closeStage(mouseEvent);
            }
        });
    }

    private void buttonSaveClicked(MouseEvent mouseEvent) {
        String errorMsg = "";

        if (cbPet.getSelectionModel().getSelectedItem() == null) {
            errorMsg += "Pet is required.\n";
        }

        if (cbCustomer.getSelectionModel().getSelectedItem() == null) {
            errorMsg += "Customer is required.\n";
        }

        if (cbEmployee.getSelectionModel().getSelectedItem() == null) {
            errorMsg += "Employee is required.\n";
        }

        if (dpAdoptionDate.getValue() == null) {
            errorMsg += "Adoption Date is required.\n";
        }

        if (cbAdoptionStatus.getSelectionModel().getSelectedItem() == null) {
            errorMsg += "Status is required.\n";
        }

        if (errorMsg.isEmpty()) {
            try {
                Long storeId = UserSession.getInstance().getStoreId();
                if (storeId == null || storeId <= 0) {
                    throw new IllegalStateException("Store is not set for this account");
                }

                AdoptionRequest request = new AdoptionRequest();
                request.setPetId(cbPet.getSelectionModel().getSelectedItem().getId());
                request.setCustomerId(cbCustomer.getSelectionModel().getSelectedItem().getId());
                request.setEmployeeId(cbEmployee.getSelectionModel().getSelectedItem().getId());
                request.setSourceStoreId(storeId);
                request.setAdoptionDate(dpAdoptionDate.getValue());
                request.setAdoptionStatus(cbAdoptionStatus.getValue());
                request.setPaymentMethod(selectedPaymentMethod);

                if (mode.equals("Add")) {
                    AdoptionApi.getInstance().createAdoption(request);
                } else {
                    String[] parts = lblAdoptionId.getText().split(": ");
                    if (parts.length < 2) {
                        throw new IllegalStateException("Invalid adoption ID format");
                    }
                    Long adoptionId = Long.parseLong(parts[1]);
                    AdoptionApi.getInstance().updateAdoption(adoptionId, request);
                }

                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setHeaderText("Saved");
                alert.setContentText(mode + " succeeded");
                alert.showAndWait();
                closeStage(mouseEvent);
            } catch (Exception e) {
                ActivityLogger.getInstance().logException(
                    "AdoptionDialogController.buttonSaveClicked",
                    e,
                    mode + " adoption");
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setHeaderText("Database Operation Error");
                alert.setContentText(e.getMessage());
                alert.showAndWait();
            }
        } else {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setHeaderText("Input Error");
            alert.setContentText(errorMsg);
            alert.showAndWait();
        }
    }

    private void closeStage(MouseEvent mouseEvent) {
        Node node = (Node) mouseEvent.getSource();
        Stage stage = (Stage) node.getScene().getWindow();
        stage.close();
    }

    public void displayAdoptionDetails(Adoption adoption) {
        if (adoption != null) {
            selectedAdoption = adoption;
            lblAdoptionId.setText("ID: " + adoption.getAdoptionId());
            ensureSelectedEmployeeOption(cbEmployee.getItems());
            applySelectedPet();
            applySelectedCustomer();
            applySelectedEmployee();

            if (adoption.getAdoptionDate() != null && !adoption.getAdoptionDate().isEmpty()) {
                try {
                    dpAdoptionDate.setValue(LocalDate.parse(adoption.getAdoptionDate()));
                } catch (Exception e) {
                    ActivityLogger.getInstance().logException(
                        "AdoptionDialogController.displayAdoptionDetails",
                        e,
                        "Parsing adoption date");
                }
            }

            suppressPaymentDialog = true;
            for (String status : cbAdoptionStatus.getItems()) {
                if (status.equals(adoption.getAdoptionStatus())) {
                    cbAdoptionStatus.getSelectionModel().select(status);
                    break;
                }
            }
            suppressPaymentDialog = false;
        }
    }

    public void setMode(String mode) {
        this.mode = mode;
        lblMode.setText(mode + " Adoption");
        lblAdoptionId.setVisible(mode.equals("Edit"));
    }

    private void applySelectedPet() {
        if (selectedAdoption == null || selectedAdoption.getPetId() <= 0) {
            return;
        }
        DropdownOption selected = findOptionById(cbPet.getItems(), (long) selectedAdoption.getPetId());
        if (selected != null && !Objects.equals(cbPet.getValue(), selected)) {
            cbPet.setValue(selected);
        }
    }

    private void applySelectedCustomer() {
        if (selectedAdoption == null || selectedAdoption.getCustomerId() <= 0) {
            return;
        }
        DropdownOption selected = findOptionById(cbCustomer.getItems(), (long) selectedAdoption.getCustomerId());
        if (selected != null && !Objects.equals(cbCustomer.getValue(), selected)) {
            cbCustomer.setValue(selected);
        }
    }

    private void applySelectedEmployee() {
        if (selectedAdoption == null || selectedAdoption.getEmployeeId() <= 0) {
            return;
        }
        DropdownOption selected = findOptionById(cbEmployee.getItems(), (long) selectedAdoption.getEmployeeId());
        if (selected != null && !Objects.equals(cbEmployee.getValue(), selected)) {
            cbEmployee.setValue(selected);
        }
    }

    private DropdownOption findOptionById(List<DropdownOption> options, Long id) {
        if (id == null || options == null) {
            return null;
        }
        for (DropdownOption option : options) {
            if (option.getId() != null && option.getId().equals(id)) {
                return option;
            }
        }
        return null;
    }

    private void ensureSelectedEmployeeOption(ObservableList<DropdownOption> options) {
        if (selectedAdoption == null || selectedAdoption.getEmployeeId() <= 0 || options == null) {
            return;
        }
        DropdownOption existing = findOptionById(options, (long) selectedAdoption.getEmployeeId());
        if (existing == null) {
            DropdownOption option = new DropdownOption();
            option.setId((long) selectedAdoption.getEmployeeId());
            option.setLabel(selectedAdoption.getEmployeeName() != null ? selectedAdoption.getEmployeeName() : "Employee #" + selectedAdoption.getEmployeeId());
            options.add(0, option);
        }
    }

    private void ensureSelectedPetOption(ObservableList<DropdownOption> options) {
        if (selectedAdoption == null || selectedAdoption.getPetId() <= 0 || options == null) {
            return;
        }
        DropdownOption existing = findOptionById(options, (long) selectedAdoption.getPetId());
        if (existing == null) {
            DropdownOption option = new DropdownOption();
            option.setId((long) selectedAdoption.getPetId());
            option.setLabel(selectedAdoption.getPetName());
            options.add(0, option);
        }
    }
}
