import { describe, it, expect, beforeEach } from 'vitest';
import { mount, VueWrapper } from '@vue/test-utils';
import { Decimal } from 'decimal.js';

import SettleShareModal from '../SettleShareModal.vue'; // Adjust path as needed
import type { ExpenseSplitInfo } from '../SettleShareModal.vue'; // Import the interface

// Default props generator
const getDefaultProps = (overrides: Record<string, any> = {}) => ({
  show: true,
  split: {
    id: 1,
    user_id: 100,
    owed_amount: '50.00',
    user: { id: 100, name: 'Test User', email: 'user@example.com' },
  } as ExpenseSplitInfo,
  paidAmount: 10.00,
  isLoading: false,
  ...overrides,
});

describe('SettleShareModal.vue', () => {
  let wrapper: VueWrapper<any>;

  const mountComponent = (props: Record<string, any>) => {
    wrapper = mount(SettleShareModal, {
      props: getDefaultProps(props),
    });
  };

  beforeEach(() => {
    // Default mount before each test, can be overridden in specific tests
    mountComponent({});
  });

  it('renders when show is true', () => {
    expect(wrapper.find('.modal-backdrop-settle').exists()).toBe(true);
  });

  it('does not render when show is false', () => {
    mountComponent({ show: false });
    expect(wrapper.find('.modal-backdrop-settle').exists()).toBe(false);
  });

  it('displays correct split information', () => {
    const props = getDefaultProps({
      split: {
        id: 2,
        user_id: 101,
        owed_amount: '75.50',
        user: { id: 101, name: 'Jane Doe', email: 'jane@example.com' },
      },
      paidAmount: 25.00,
    });
    mountComponent(props);

    const html = wrapper.html();
    expect(html).toContain('Jane Doe');
    expect(html).toContain('$75.50'); // Owed amount
    expect(html).toContain('$25.00'); // Paid amount
    
    const expectedRemaining = new Decimal(props.split.owed_amount).minus(new Decimal(props.paidAmount)).toFixed(2);
    expect(html).toContain(`$${expectedRemaining}`); // Remaining amount
  });
  
  it('calculates and displays correct remaining amount', () => {
    const owed = '100.00';
    const paid = 30.00;
    const remaining = new Decimal(owed).minus(paid).toFixed(2);
    mountComponent({ split: { ...getDefaultProps().split, owed_amount: owed }, paidAmount: paid });
    
    const remainingAmountStrong = wrapper.find('.amount-to-settle');
    expect(remainingAmountStrong.exists()).toBe(true);
    expect(remainingAmountStrong.text()).toBe(`$${remaining}`);
  });

  it('emits "confirm" with correct amount when Confirm Payment is clicked', async () => {
    const owed = '50.00';
    const paid = 10.00;
    const expectedSettleAmount = new Decimal(owed).minus(paid).toNumber();
    
    mountComponent({ 
        split: { ...getDefaultProps().split, owed_amount: owed }, 
        paidAmount: paid 
    });
    
    await wrapper.find('.btn-primary-settle').trigger('click');
    expect(wrapper.emitted().confirm).toBeTruthy();
    expect(wrapper.emitted().confirm[0]).toEqual([expectedSettleAmount]);
  });

  it('emits "cancel" when Cancel button is clicked', async () => {
    await wrapper.find('.btn-neutral-settle').trigger('click');
    expect(wrapper.emitted().cancel).toBeTruthy();
  });

  it('emits "cancel" when backdrop is clicked', async () => {
    await wrapper.find('.modal-backdrop-settle').trigger('click.self');
    expect(wrapper.emitted().cancel).toBeTruthy();
  });
  
  it('disables Confirm Payment button when isLoading is true', () => {
    mountComponent({ isLoading: true });
    const confirmButton = wrapper.find('.btn-primary-settle');
    expect((confirmButton.element as HTMLButtonElement).disabled).toBe(true);
  });

  it('disables Confirm Payment button when remaining amount is zero or less', () => {
    mountComponent({ 
        split: { ...getDefaultProps().split, owed_amount: '20.00' }, 
        paidAmount: 20.00 
    }); // remaining is 0
    const confirmButton = wrapper.find('.btn-primary-settle');
    expect((confirmButton.element as HTMLButtonElement).disabled).toBe(true);

    mountComponent({ 
        split: { ...getDefaultProps().split, owed_amount: '19.00' }, 
        paidAmount: 20.00 
    }); // remaining is < 0 (overpaid)
    const confirmButtonNegative = wrapper.find('.btn-primary-settle');
    expect((confirmButtonNegative.element as HTMLButtonElement).disabled).toBe(true);
  });

  it('Confirm Payment button is enabled when there is a positive remaining amount and not loading', () => {
     mountComponent({ 
        split: { ...getDefaultProps().split, owed_amount: '20.00' }, 
        paidAmount: 10.00,
        isLoading: false
    }); 
    const confirmButton = wrapper.find('.btn-primary-settle');
    expect((confirmButton.element as HTMLButtonElement).disabled).toBe(false);
  });

});
