package at.spengergasse.views.transfer;

import at.spengergasse.domain.Account;
import at.spengergasse.domain.AccountException;
import at.spengergasse.service.BankService;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.BeanValidationBinder;
import com.vaadin.flow.router.Menu;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.theme.lumo.LumoUtility.Margin;
import jakarta.validation.constraints.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.lineawesome.LineAwesomeIconUrl;

import java.time.LocalDate;

@PageTitle("Transfer")
@Route("transfer")
@Menu(order = 1, icon = LineAwesomeIconUrl.DOLLAR_SIGN_SOLID)
public class TransferView extends VerticalLayout {
    private final Button removeAll = new Button("Remove all accouts");
    private final Button add10Accounts = new Button("Add 10 accouts");
    private final Button addWrongAccount = new Button("Add wrong account");
    private final Button add1Account = new Button("Add 1 account");

    private final Grid<Account> grid = new Grid<>(Account.class, false);
    private final BankService bankService;

    public TransferView(@Autowired BankService bankService) {
        this.bankService = bankService;
        setSpacing(true);

        grid.addColumn(a -> a.getAccountId())
                .setHeader("Account ID")
                .setSortable(true);
        grid.addColumn(a -> a.getFirstName())
                .setHeader("First Name")
                .setSortable(true);
        grid.addColumn(a-> a.getOpeningDate())
                .setHeader("Opening Date")
                .setSortable(true);

        Image img = new Image("icons/bank.png", "Bank");
        img.setWidth("32px");
        grid.addColumn(a-> a.getAccountType())
                .setHeader(new HorizontalLayout(img, new Span("AccType")))
                .setSortable(true);

        grid.addColumn(a-> a.getAmount())
                .setHeader("Amount")
                .setSortable(true);
        grid.addColumn(a-> a.getActive())
                .setHeader("Active")
                .setSortable(true);
        grid.addColumn(a-> a.getActive() ? "Y" : "N")
                .setHeader("Active")
                .setSortable(true);
        grid.addComponentColumn(a-> {
            Checkbox cb = new Checkbox();
            cb.setValue(a.getActive());
            cb.setReadOnly(true);
            return cb;
        })
                .setHeader("Active")
                .setSortable(true);
        grid.addComponentColumn(a -> new Button("Delete", e -> remove1(a.getAccountId())))
                .setHeader("Action")
                .setSortable(false);
        grid.addComponentColumn(a -> new Button("Add 100 EUR", e-> add100Eur(a.getAccountId())))
                .setHeader("Action")
                .setSortable(false);
        grid.addComponentColumn(a -> new Button("Edit account", e -> addEditAccount(a)))
                .setHeader("Action")
                .setSortable(false);

        setSizeFull();
        grid.setSizeFull();
        removeAll.addClickListener(e -> removeAllAccouts());
        add10Accounts.addClickListener(e -> add10Accounts());
        addWrongAccount.addClickListener(e -> addWrongAccount());
        add1Account.addClickListener(e -> addEditAccount(null));
        HorizontalLayout buttons = new HorizontalLayout(removeAll, add10Accounts, addWrongAccount, add1Account);
        buttons.setSpacing(true);
        add(buttons);
        add(grid);
        reload();
    }

    private void addEditAccount(Account existingAccount) {
        Dialog dialog = new Dialog();
        Account account;
        if (existingAccount == null) {
            account = new Account();
            dialog.setHeaderTitle("Add Account");
        }
        else {
            account = existingAccount;
            dialog.setHeaderTitle("Edit Account");
        }

        TextField accountId = new TextField("Account ID");
        accountId.setReadOnly(true);
        TextField firstName = new TextField("First Name");
        DatePicker openingDate = new DatePicker("Opening Date");
        ComboBox<String> accountType = new ComboBox<>("Account Type");
        accountType.setItems("Checking","Savings", "Fixed Deposit", "Business", "Joint", "Credit");
        NumberField amount = new NumberField("Amount");
        Checkbox active = new Checkbox("Active");

        BeanValidationBinder<Account> binder = new BeanValidationBinder<>(Account.class);

        binder.forField(firstName)
                .bind("firstName");

        binder.forField(openingDate)
                .bind("openingDate");

        binder.forField(accountType)
                .bind("accountType");

        binder.forField(amount)
                .bind("amount");

        binder.forField(active)
                .bind("active");

        binder.setBean(account);

        accountId.setValue(""+account.getAccountId());
        VerticalLayout formLayout = new VerticalLayout(accountId, firstName, openingDate, accountType, amount, active);

        Button saveButton = new Button("OK");
        saveButton.addClickListener(e-> {
            if (binder.validate().isOk()) {
                if (existingAccount == null)
                    bankService.addAccount(account);
                reload();
                dialog.close();
            }
            else {
                Notification.show("Fehler. Daten nicht korrekt!");
            }
        });
        Button cancelButton = new Button("Cancel");
        cancelButton.addClickListener(e-> {
            dialog.close();
        });
        dialog.add(formLayout);
        dialog.getFooter().add(saveButton, cancelButton);
        dialog.open();
    }

    private void add100Eur(Long accountId) {
        try {
            bankService.add100Eur(accountId);
            reload();
        }
        catch (AccountException e) {
            Notification.show(e.getMessage());
        }
    }

    private void remove1(Long accountId) {
        try {
            bankService.remove1(accountId);
            reload();
        }
        catch (AccountException e) {
            Notification.show(e.getMessage());
        }
    }

    private void addWrongAccount() {
        try {
            Account a = new Account("Fritz", LocalDate.now(), "Savings", -2000.0, true);
            bankService.addAccount(a);
            reload();
        }
        catch (AccountException e) {
            Notification.show(e.getMessage());
        }
    }

    private void add10Accounts() {
        try {
            bankService.fillTestData(10);
            removeAll.setEnabled(true);
            reload();
        }
        catch (AccountException e) {
            Notification.show(e.getMessage());
        }
    }

    private void removeAllAccouts() {
        try {
            bankService.removeAllAccouts();
            removeAll.setEnabled(false);
            reload();
        }
        catch (AccountException e) {
            Notification.show(e.getMessage());
        }
    }

    private void reload() {
        grid.setItems(bankService.findAll());
    }
}
