import React from 'react';
import ReactDOM from 'react-dom';
import { mount } from 'enzyme';
import { BankAccount } from 'web-foundation';
import {
    ACCOUNT_TYPE_INDIVIDUAL,
    ACCOUNT_TYPE_BUSINESS
} from 'web-foundation/components/bank-account/bank-account.js';

describe('BankAccount', function() {
    const account = {
        accountType: ACCOUNT_TYPE_BUSINESS,
        accountHolder: 'Acc Ountholdier',
        accountNumber: '123456789012',
        routingNumber: '123456789'
    };

    it('should fill properly', function() {
        const model = new BankAccount.Model(account);

        expect(model.accountType).to.equal(account.accountType);
        expect(model.accountHolder).to.equal(account.accountHolder);
        expect(model.accountNumber).to.equal(account.accountNumber);
        expect(model.routingNumber).to.equal(account.routingNumber);
    });

    it('should fill individual properties correctly', function() {
        const model = new BankAccount.Model(account),
            changes = {
                accountType: ACCOUNT_TYPE_BUSINESS,
                accountHolder: 'Firs Te-Name'
            };

        expect(model.accountType).to.equal(account.accountType);
        expect(model.accountHolder).to.equal(account.accountHolder);

        model.fill(changes);

        expect(model.accountType).to.equal(changes.accountType);
        expect(model.accountHolder).to.equal(changes.accountHolder);
    });

    it('should know a valid routing number', function() {
        expect(BankAccount.Model.validateRoutingNumber('110000000'))
            .to.be.true;
        expect(BankAccount.Model.validateRoutingNumber('123456789'))
            .to.be.false;
    });
});

describe('<BankAccount />', function() {
    const account = {
        taxId: '123456789',
        accountType: ACCOUNT_TYPE_INDIVIDUAL,
        accountHolder: 'Acc Ountholdier',
        accountNumber: '123456789012',
        routingNumber: '123456789'
    };

    it('should initialize properly', function() {
        const wrapper = mount(<BankAccount.View />);

        expect(wrapper.children().find('.row.t100')).to.have.length(6);
    });

    it('should have nickname field if passes as prop', function() {
        const wrapper = mount(<BankAccount.View nickname />);

        expect(wrapper.children().find('.row.t100')).to.have.length(7);
    });

    it('should fill with stuff', function() {
        const model = new BankAccount.Model(account),
            wrapper = mount(<BankAccount.View model={ model } />),
            node = ReactDOM.findDOMNode(wrapper.instance());

        expect(node.querySelector('.dropdown .header').textContent)
            .to.equal('Individual');
        expect(node.getElementsByTagName('input')[0].value)
            .to.equal(account.accountHolder);
        expect(node.getElementsByTagName('input')[2].value)
            .to.equal(account.routingNumber);
        expect(node.getElementsByTagName('input')[3].value)
            .to.equal(account.accountNumber);
    });

    it('should switch between SSN and EIN', function() {
        const model = new BankAccount.Model(),
            wrapper = mount(
                <BankAccount.View
                    native
                    model={ model }/>);

        const placeholder = wrapper.find('TextInput').at(1).prop('placeholder');

        wrapper.find('select').simulate('change', {
            target: { value: ACCOUNT_TYPE_BUSINESS }
        });

        // the placeholder should have changed
        wrapper.update();
        expect(wrapper.find('TextInput').at(1).prop('placeholder'))
            .to.not.equal(placeholder);

        wrapper.find('select').simulate('change', {
            target: { value: ACCOUNT_TYPE_INDIVIDUAL }
        });

        wrapper.update();
        expect(wrapper.find('TextInput').at(1).prop('placeholder'))
            .to.equal(placeholder);
    });

    it('should update error when switching SSN and EIN', function(done) {
        const model = new BankAccount.Model(),
            wrapper = mount(
                <BankAccount.View
                    native
                    model={ model }/>);

        wrapper.instance().formValidate(() => {
            const msg = wrapper.instance().model.errors.taxId;

            wrapper.find('select').simulate('change', {
                target: { value: ACCOUNT_TYPE_BUSINESS }
            });
            wrapper.update();

            setTimeout(() => {
                expect(wrapper.instance().model.errors.taxId).to.not.equal(msg);
                done();
            }, 10);
        });
    });

    it('should validate errors', function(done) {
        const model = new BankAccount.Model(),
            wrapper = mount(<BankAccount.View model={ model } />),
            requiredFields = [
                'accountType',
                'taxId',
                'accountNumber',
                'accountHolder',
                'routingNumber'
            ];

        wrapper.instance().formValidate(() => {
            requiredFields.forEach((field) => {
                expect(wrapper.instance().model.errors[field]).to.exist;
            });
            done();
        });
    });

    it('should know what is correct', function(done) {
        const model = new BankAccount.Model(account),
            wrapper = mount(<BankAccount.View model={ model } />),
            node = ReactDOM.findDOMNode(wrapper.instance());

        node.getElementsByTagName('input')[3].value = account.accountNumber;

        wrapper.instance().formValidate(() => {
            const errors = wrapper.instance().model.errors;

            expect(Object.keys(errors).every((key) => !errors[key]));
            done();
        });
    });

    it('should check if account number is confirmed', function(done) {
        const model = new BankAccount.Model(account),
            wrapper = mount(
                <BankAccount.View model={ model }
                    inlineErrors />),
            ml = wrapper.instance(),
            node = ReactDOM.findDOMNode(wrapper.instance()),
            accountNumber = node.getElementsByTagName('input')[4],
            errorMessages = BankAccount.View.defaultErrorMessages;

        // updating confirmation field before form validation should do nothing
        wrapper.instance().onConfirmationUpdate();
        expect(ml.model.errors.accountNumber).to.not.exist;

        ml.formValidate(() => {
            // confirmation field is blank, should report mismatch error
            expect(ml.model.errors.accountNumber)
                .to.equal(errorMessages.accountNumber.mismatch);

            // confirmation matches account number, error msg should clear
            accountNumber.value = account.accountNumber;
            wrapper.instance().onConfirmationUpdate();
            expect(ml.model.errors.accountNumber).to.be.null;

            done();
        });
    });

    it('should allow setting custom error messages', function(done) {
        const model = new BankAccount.Model(account),
            wrapper = mount(<BankAccount.View model={ model } />),
            msg = 'z8O00YisZv';

        wrapper.instance().setErrorMessages({
            accountNumber: {
                mismatch: msg
            }
        });

        wrapper.instance().formValidate(() => {
            expect(wrapper.instance().model.errors.accountNumber)
                .to.equal(msg);
            done();
        });
    });
});
