import { ContactsApi } from '../../api/contactsApi';
import * as sinon from 'sinon';

describe('ContactApi Unit Test', () => {
    let contactApiStub: sinon.SinonStubbedInstance<ContactsApi>;

    beforeEach(() => {
        // Create a stub instance for the ContactApi
        contactApiStub = sinon.createStubInstance(ContactsApi);

        contactApiStub.createContact = sinon.stub().resolves({ contactId: 'contact_id' });
        contactApiStub.updateContact = sinon.stub().resolves({
            success: true,
            message: 'Contact updated successfully',
        });
    });

    afterEach(() => {
        sinon.restore();
    });

    it('should mock and verify createContact call', async () => {
        const mockContactCreated = {
            contactId: 'contact_id',
        };

        const contactData = {
            name: 'New contact',
            email: 'newEmail@gmail.com',
            phoneNumber: '9876543210',
            jobTitle: 'Test',
            companyName: 'Syncfusion',
        };

        contactApiStub.createContact.resolves(mockContactCreated);

        const result = await contactApiStub.createContact(contactData);

        expect(result).toBeDefined();
        expect(result.contactId).toBe('contact_id');

        sinon.assert.calledOnceWithExactly(contactApiStub.createContact, contactData);
    });

    it('should mock and verify listContacts call', async () => {
        const mockContactList = [
            {
                contactId: 'contact_1',
                name: 'Contact One',
                email: 'contact1@example.com',
            },
            {
                contactId: 'contact_2',
                name: 'Contact Two',
                email: 'contact2@example.com',
            },
        ];
    
        contactApiStub.listContacts = sinon.stub().resolves(mockContactList);
    
        const result = await contactApiStub.listContacts();
    
        expect(result).toBeDefined();
        expect(result.length).toBe(2);
        expect(result[0].contactId).toBe('contact_1');
        expect(result[0].name).toBe('Contact One');
        expect(result[0].email).toBe('contact1@example.com');
    
        sinon.assert.calledOnce(contactApiStub.listContacts);
    });

    it('should mock and verify updateContact call', async () => {
        const mockUpdatedContact = {
            success: true,
            message: 'Contact updated successfully',
        };
    
        const contactId = 'contact_1';
        const updatedContactData = {
            name: 'Updated Contact One',
            email: 'updatedEmail@example.com',
            phoneNumber: '1234567890',
            jobTitle: 'Updated Job Title',
            companyName: 'Updated Company',
        };
    
        contactApiStub.updateContact = sinon.stub().resolves(mockUpdatedContact);
    
        const result = await contactApiStub.updateContact(contactId, updatedContactData);
    
        expect(result).toBeDefined();
        expect(result.success).toBe(true);
        expect(result.message).toBe('Contact updated successfully');
    
        sinon.assert.calledOnceWithExactly(contactApiStub.updateContact, contactId, updatedContactData);
    });

    it('should mock and verify deleteContact call', async () => {
        const mockDeleteResponse = {
            success: true,
            message: 'Contact deleted successfully',
        };
    
        const contactId = 'contact_1';
    
        contactApiStub.deleteContact = sinon.stub().resolves(mockDeleteResponse);
    
        const result = await contactApiStub.deleteContact(contactId);
    
        expect(result).toBeDefined();
        expect(result.success).toBe(true);
        expect(result.message).toBe('Contact deleted successfully');
    
        sinon.assert.calledOnceWithExactly(contactApiStub.deleteContact, contactId);
    });
    
    it('should mock and verify getContact call', async () => {
        const mockContactDetails = {
            contactId: 'contact_1',
            name: 'Contact One',
            email: 'contact1@example.com',
            phoneNumber: '9876543210',
            jobTitle: 'Software Engineer',
            companyName: 'TechCorp',
        };
    
        const contactId = 'contact_1';
    
        contactApiStub.getContact = sinon.stub().resolves(mockContactDetails);
    
        const result = await contactApiStub.getContact(contactId);
    
        expect(result).toBeDefined();
        expect(result.contactId).toBe('contact_1');
        expect(result.name).toBe('Contact One');
        expect(result.email).toBe('contact1@example.com');
        expect(result.phoneNumber).toBe('9876543210');
        expect(result.jobTitle).toBe('Software Engineer');
        expect(result.companyName).toBe('TechCorp');
    
        sinon.assert.calledOnceWithExactly(contactApiStub.getContact, contactId);
    });
});