import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { StoreDetailClient } from '../store-detail-client';

const showMock = vi.fn();
const verifyMock = vi.fn();
const suspendMock = vi.fn();
const unsuspendMock = vi.fn();
const storeLedgerMock = vi.fn();
const postAdjustmentMock = vi.fn();
vi.mock('@/lib/api', () => ({
  api: {
    admin: {
      showStore: (...a: unknown[]) => showMock(...a),
      verifyStore: (...a: unknown[]) => verifyMock(...a),
      suspendStore: (...a: unknown[]) => suspendMock(...a),
      unsuspendStore: (...a: unknown[]) => unsuspendMock(...a),
      financials: {
        storeLedger: (...a: unknown[]) => storeLedgerMock(...a),
        postAdjustment: (...a: unknown[]) => postAdjustmentMock(...a),
      },
    },
  },
}));

function wrap(node: React.ReactNode) {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return <QueryClientProvider client={qc}>{node}</QueryClientProvider>;
}

const baseDetail = {
  id: 'store-1',
  name: 'Revive Boutique',
  city: 'Portland',
  state: 'OR',
  is_verified: false,
  is_suspended: false,
  suspended_at: null,
  suspension_reason: null,
  item_count: 3,
  total_sales: null,
  created_at: '2026-01-01T00:00:00Z',
  owner: { id: 'u1', email: 'owner@example.com', name: 'Owner' },
  counters: {
    items_active: 2,
    items_draft: 1,
    orders_open: 1,
    orders_total: 5,
    lifetime_revenue_cents: 12_345,
  },
  recent_orders: [
    { id: 'order-12345', status: 'pending', total: 5500, created_at: '2026-05-01T00:00:00Z' },
  ],
  recent_items: [
    { id: 'item-1', title: 'Vintage Tee', price: 2500, status: 'active', created_at: '2026-04-01T00:00:00Z' },
  ],
};

describe('StoreDetailClient', () => {
  beforeEach(() => {
    showMock.mockReset();
    verifyMock.mockReset();
    suspendMock.mockReset();
    unsuspendMock.mockReset();
    storeLedgerMock.mockReset();
    postAdjustmentMock.mockReset();
  });

  it('renders header, counters, and recent activity', async () => {
    showMock.mockResolvedValue({ data: baseDetail });
    render(wrap(<StoreDetailClient storeId="store-1" />));
    await waitFor(() => expect(screen.getByText('Revive Boutique')).toBeInTheDocument());
    expect(screen.getByText('Portland, OR')).toBeInTheDocument();
    expect(screen.getByText('Pending')).toBeInTheDocument();
    expect(screen.getByText('Vintage Tee')).toBeInTheDocument();
    // counter values
    expect(screen.getByText('2')).toBeInTheDocument(); // items_active
    expect(screen.getByText('$123.45')).toBeInTheDocument(); // lifetime
  });

  it('verify flow calls verifyStore', async () => {
    showMock.mockResolvedValue({ data: baseDetail });
    verifyMock.mockResolvedValue({ data: baseDetail });
    render(wrap(<StoreDetailClient storeId="store-1" />));
    await waitFor(() => expect(screen.getByText('Revive Boutique')).toBeInTheDocument());

    fireEvent.click(screen.getByRole('button', { name: 'Verify' }));
    fireEvent.change(screen.getByLabelText('Justification'), {
      target: { value: 'Owner uploaded proof of business identity.' },
    });
    const buttons = screen.getAllByRole('button', { name: 'Verify' });
    fireEvent.click(buttons[buttons.length - 1]);

    await waitFor(() => expect(verifyMock).toHaveBeenCalled());
    const [, just] = verifyMock.mock.calls[0];
    expect(just).toMatch(/proof of business/);
  });

  it('suspend flow calls suspendStore', async () => {
    showMock.mockResolvedValue({ data: { ...baseDetail, is_verified: true } });
    suspendMock.mockResolvedValue({ data: baseDetail });
    render(wrap(<StoreDetailClient storeId="store-1" />));
    await waitFor(() => expect(screen.getByText('Revive Boutique')).toBeInTheDocument());

    fireEvent.click(screen.getByRole('button', { name: 'Suspend' }));
    fireEvent.change(screen.getByLabelText('Justification'), {
      target: { value: 'Multiple unresolved disputes within 30 days.' },
    });
    const buttons = screen.getAllByRole('button', { name: 'Suspend' });
    fireEvent.click(buttons[buttons.length - 1]);

    await waitFor(() => expect(suspendMock).toHaveBeenCalled());
  });

  it('unsuspend button only shows when suspended', async () => {
    showMock.mockResolvedValue({
      data: {
        ...baseDetail,
        is_suspended: true,
        suspended_at: '2026-05-02T00:00:00Z',
        suspension_reason: 'Old reason',
      },
    });
    render(wrap(<StoreDetailClient storeId="store-1" />));
    await waitFor(() => expect(screen.getByText('Revive Boutique')).toBeInTheDocument());

    expect(screen.getByRole('button', { name: 'Unsuspend' })).toBeInTheDocument();
    expect(screen.queryByRole('button', { name: 'Verify' })).not.toBeInTheDocument();
    expect(screen.getByText('Old reason')).toBeInTheDocument();
  });

  it('clicking the Ledger tab switches to the ledger view', async () => {
    showMock.mockResolvedValue({ data: baseDetail });
    storeLedgerMock.mockResolvedValue({
      data: [
        {
          id: 'le-1',
          entry_type: 'order_earned',
          direction: 'credit',
          amount_cents: 5000,
          description: 'Order capture',
          source_type: 'order',
          source_id: 'o-1',
          available_at: '2026-05-17T00:00:00Z',
          payout_id: null,
          created_at: '2026-05-03T00:00:00Z',
        },
      ],
      meta: { current_page: 1, last_page: 1, per_page: 20, total: 1, from: 1, to: 1 },
      links: { first: null, last: null, prev: null, next: null },
    });
    render(wrap(<StoreDetailClient storeId="store-1" />));
    await waitFor(() =>
      expect(screen.getByText('Revive Boutique')).toBeInTheDocument(),
    );
    fireEvent.click(screen.getByTestId('store-detail-tab-ledger'));
    await waitFor(() =>
      expect(
        screen.getByTestId('admin-ledger-row-le-1'),
      ).toBeInTheDocument(),
    );
    // Overview content no longer rendered
    expect(screen.queryByText('Admin actions')).not.toBeInTheDocument();
  });

  it('manual adjustment modal posts credit + reason to the API', async () => {
    showMock.mockResolvedValue({ data: baseDetail });
    storeLedgerMock.mockResolvedValue({
      data: [],
      meta: { current_page: 1, last_page: 1, per_page: 20, total: 0, from: null, to: null },
      links: { first: null, last: null, prev: null, next: null },
    });
    postAdjustmentMock.mockResolvedValue({
      data: {
        id: 'adj-1',
        store_id: 'store-1',
        type: 'credit',
        amount_cents: 500,
        reason: 'Goodwill credit for slow refund',
        admin: null,
        created_at: '2026-05-07T00:00:00Z',
      },
    });
    render(wrap(<StoreDetailClient storeId="store-1" />));
    await waitFor(() =>
      expect(screen.getByText('Revive Boutique')).toBeInTheDocument(),
    );
    fireEvent.click(screen.getByTestId('store-detail-tab-ledger'));
    fireEvent.click(
      await screen.findByTestId('admin-ledger-new-adjustment'),
    );
    // submit disabled until amount + reason valid
    expect(screen.getByTestId('adjustment-submit')).toBeDisabled();
    fireEvent.change(screen.getByTestId('adjustment-amount'), {
      target: { value: '5.00' },
    });
    fireEvent.change(screen.getByTestId('adjustment-reason'), {
      target: { value: 'Goodwill credit for slow refund' },
    });
    expect(screen.getByTestId('adjustment-submit')).toBeEnabled();
    fireEvent.click(screen.getByTestId('adjustment-submit'));
    await waitFor(() => expect(postAdjustmentMock).toHaveBeenCalled());
    const [storeId, body] = postAdjustmentMock.mock.calls[0];
    expect(storeId).toBe('store-1');
    expect(body.type).toBe('credit');
    expect(body.amount_cents).toBe(500);
    expect(body.reason).toBe('Goodwill credit for slow refund');
  });

  it('manual adjustment debit converts dollars to cents correctly', async () => {
    showMock.mockResolvedValue({ data: baseDetail });
    storeLedgerMock.mockResolvedValue({
      data: [],
      meta: { current_page: 1, last_page: 1, per_page: 20, total: 0, from: null, to: null },
      links: { first: null, last: null, prev: null, next: null },
    });
    postAdjustmentMock.mockResolvedValue({
      data: {
        id: 'adj-2',
        store_id: 'store-1',
        type: 'debit',
        amount_cents: 1234,
        reason: 'Chargeback recovery for order',
        admin: null,
        created_at: '2026-05-07T00:00:00Z',
      },
    });
    render(wrap(<StoreDetailClient storeId="store-1" />));
    await waitFor(() =>
      expect(screen.getByText('Revive Boutique')).toBeInTheDocument(),
    );
    fireEvent.click(screen.getByTestId('store-detail-tab-ledger'));
    fireEvent.click(
      await screen.findByTestId('admin-ledger-new-adjustment'),
    );
    fireEvent.click(screen.getByTestId('adjustment-type-debit'));
    fireEvent.change(screen.getByTestId('adjustment-amount'), {
      target: { value: '12.34' },
    });
    fireEvent.change(screen.getByTestId('adjustment-reason'), {
      target: { value: 'Chargeback recovery for order' },
    });
    fireEvent.click(screen.getByTestId('adjustment-submit'));
    await waitFor(() => expect(postAdjustmentMock).toHaveBeenCalled());
    const [, body] = postAdjustmentMock.mock.calls[0];
    expect(body.type).toBe('debit');
    expect(body.amount_cents).toBe(1234);
  });
});
