import { render, screen } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    usePage: vi.fn(() => ({
      url: '/admin/users/1',
      props: {
        auth: { user: { id: 99, name: 'Admin', email: 'admin@test.com', is_admin: true } },
        features: {
          billing: true,
          socialAuth: false,
          emailVerification: true,
          apiTokens: true,
          userSettings: true,
          notifications: false,
          onboarding: false,
          apiDocs: false,
          twoFactor: false,
          webhooks: false,
          admin: true,
        },
      },
    })),
    Link: ({
      children,
      href,
      ...rest
    }: {
      children: React.ReactNode;
      href: string;
      className?: string;
    }) => (
      <a href={href} {...rest}>
        {children}
      </a>
    ),
    router: {
      patch: vi.fn(),
      delete: vi.fn(),
      post: vi.fn(),
      get: vi.fn(),
      on: vi.fn(() => vi.fn()),
    },
    useForm: vi.fn(() => ({
      data: { subject: '', body: '', preview_only: false, key: '', value: '' },
      setData: vi.fn(),
      post: vi.fn(),
      reset: vi.fn(),
      clearErrors: vi.fn(),
      setError: vi.fn(),
      errors: {},
      processing: false,
    })),
  };
});

vi.mock('@/Components/theme/use-theme', () => ({
  useTheme: vi.fn(() => ({ theme: 'system', setTheme: vi.fn(), resolvedTheme: 'light' })),
}));

vi.mock('sonner', () => ({
  toast: { success: vi.fn(), error: vi.fn() },
}));

import AdminUserShow from './Show';

const makeUser = (overrides = {}) => ({
  id: 1,
  name: 'Alice Example',
  email: 'alice@example.com',
  is_admin: false,
  email_verified_at: '2026-01-01T00:00:00Z',
  last_login_at: '2026-03-01T10:00:00Z',
  created_at: '2026-01-01T00:00:00Z',
  deleted_at: null,
  tokens_count: 3,
  has_password: true,
  two_factor_enabled: false,
  signup_source: 'direct',
  lead_score: null,
  lead_score_tier: null,
  pql_qualified_at: null,
  ...overrides,
});

const makeDefaultProps = (overrides = {}) => ({
  user: makeUser(),
  recent_audit_logs: [],
  subscription: null,
  sites_usage: {
    totals: { sites: 0, drafts: 0, applied_recommendations: 0 },
    sites: [],
  },
  limit_overrides: {},
  limit_defaults: { max_sites_per_user: 5, max_drafts_per_month: 50 },
  branding: null,
  ...overrides,
});

describe('AdminUserShow', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('heading and breadcrumb', () => {
    it('renders the user name as a level-1 heading', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByRole('heading', { name: 'Alice Example', level: 1 })).toBeInTheDocument();
    });

    it('renders breadcrumb with Users link and user name', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      // The sidebar also has a "Users" link, so there are multiple matches
      const usersLinks = screen.getAllByRole('link', { name: /Users/i });
      expect(usersLinks.length).toBeGreaterThanOrEqual(1);
      // Breadcrumb page item (the last segment) should contain the user name
      expect(screen.getAllByText('Alice Example').length).toBeGreaterThanOrEqual(1);
    });
  });

  describe('user information card', () => {
    it('shows user email as subtitle', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('alice@example.com')).toBeInTheDocument();
    });

    it('shows User badge for non-admin user', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('User')).toBeInTheDocument();
    });

    it('shows Admin badge for admin user', () => {
      render(<AdminUserShow {...makeDefaultProps({ user: makeUser({ is_admin: true }) })} />);
      // "Admin" appears in layout badge AND in user info card
      const adminBadges = screen.getAllByText('Admin');
      expect(adminBadges.length).toBeGreaterThanOrEqual(1);
    });

    it('shows Verified badge when email is verified', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('Verified')).toBeInTheDocument();
    });

    it('shows Unverified badge when email is not verified', () => {
      render(
        <AdminUserShow {...makeDefaultProps({ user: makeUser({ email_verified_at: null }) })} />,
      );
      expect(screen.getByText('Unverified')).toBeInTheDocument();
    });

    it('shows Active badge for active user', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('Active')).toBeInTheDocument();
    });

    it('shows Deactivated badge for soft-deleted user', () => {
      render(
        <AdminUserShow
          {...makeDefaultProps({ user: makeUser({ deleted_at: '2026-02-01T00:00:00Z' }) })}
        />,
      );
      // May appear multiple times (badge in user info + possibly elsewhere)
      expect(screen.getAllByText('Deactivated').length).toBeGreaterThanOrEqual(1);
    });

    it('shows tokens count in user info', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('3')).toBeInTheDocument();
    });

    it('shows signup source', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('direct')).toBeInTheDocument();
    });

    it('shows "Yes" for has_password', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('Yes')).toBeInTheDocument();
    });

    it('shows "No (OAuth only)" when user has no password', () => {
      render(<AdminUserShow {...makeDefaultProps({ user: makeUser({ has_password: false }) })} />);
      expect(screen.getByText('No (OAuth only)')).toBeInTheDocument();
    });
  });

  describe('action buttons', () => {
    it('shows "Make Admin" button for non-admin user', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByRole('button', { name: /Make Admin/i })).toBeInTheDocument();
    });

    it('shows "Remove Admin" button for admin user', () => {
      render(<AdminUserShow {...makeDefaultProps({ user: makeUser({ is_admin: true }) })} />);
      expect(screen.getByRole('button', { name: /Remove Admin/i })).toBeInTheDocument();
    });

    it('shows "Deactivate" button for active user', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByRole('button', { name: /^Deactivate$/i })).toBeInTheDocument();
    });

    it('shows "Restore" button for deleted user', () => {
      render(
        <AdminUserShow
          {...makeDefaultProps({ user: makeUser({ deleted_at: '2026-02-01T00:00:00Z' }) })}
        />,
      );
      expect(screen.getByRole('button', { name: /^Restore$/i })).toBeInTheDocument();
    });

    it('shows "Send Email" button for active user', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByRole('button', { name: /Send Email/i })).toBeInTheDocument();
    });

    it('does not show "Send Email" button for deleted user', () => {
      render(
        <AdminUserShow
          {...makeDefaultProps({ user: makeUser({ deleted_at: '2026-02-01T00:00:00Z' }) })}
        />,
      );
      expect(screen.queryByRole('button', { name: /Send Email/i })).not.toBeInTheDocument();
    });

    it('shows "Impersonate" button for non-admin non-deleted other user', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByRole('button', { name: /Impersonate/i })).toBeInTheDocument();
    });

    it('does not show "Impersonate" button for admin user', () => {
      render(<AdminUserShow {...makeDefaultProps({ user: makeUser({ is_admin: true }) })} />);
      expect(screen.queryByRole('button', { name: /Impersonate/i })).not.toBeInTheDocument();
    });

    it('does not show "Impersonate" button for deleted user', () => {
      render(
        <AdminUserShow
          {...makeDefaultProps({ user: makeUser({ deleted_at: '2026-02-01T00:00:00Z' }) })}
        />,
      );
      expect(screen.queryByRole('button', { name: /Impersonate/i })).not.toBeInTheDocument();
    });

    it('does not show "Impersonate" button when viewing own account', async () => {
      // usePage returns auth.user.id = 99; set user.id = 99 to match
      const inertia = await import('@inertiajs/react');
      vi.mocked(inertia.usePage).mockReturnValueOnce({
        url: '/admin/users/99',
        props: {
          auth: { user: { id: 99, name: 'Admin', email: 'admin@test.com', is_admin: true } },
          features: {},
        },
      } as unknown as ReturnType<typeof inertia.usePage>);

      render(<AdminUserShow {...makeDefaultProps({ user: makeUser({ id: 99 }) })} />);
      expect(screen.queryByRole('button', { name: /Impersonate/i })).not.toBeInTheDocument();
    });
  });

  describe('subscription card', () => {
    it('does not render subscription card when subscription is null', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.queryByText('Subscription')).not.toBeInTheDocument();
    });

    it('renders subscription card when subscription is provided', () => {
      render(
        <AdminUserShow
          {...makeDefaultProps({
            subscription: {
              stripe_status: 'active',
              stripe_price: 'price_pro_monthly',
              quantity: 1,
              trial_ends_at: null,
            },
          })}
        />,
      );
      expect(screen.getByText('Subscription')).toBeInTheDocument();
      expect(screen.getByText('active')).toBeInTheDocument();
      expect(screen.getByText('price_pro_monthly')).toBeInTheDocument();
    });

    it('shows trial end date when trial_ends_at is set', () => {
      render(
        <AdminUserShow
          {...makeDefaultProps({
            subscription: {
              stripe_status: 'trialing',
              stripe_price: 'price_pro_monthly',
              quantity: 1,
              trial_ends_at: '2026-04-01T00:00:00Z',
            },
          })}
        />,
      );
      expect(screen.getByText('Trial Ends')).toBeInTheDocument();
    });
  });

  describe('sites & usage', () => {
    it('shows empty state when user has no sites', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('No sites')).toBeInTheDocument();
    });

    it('shows totals and site table when user has sites', () => {
      render(
        <AdminUserShow
          {...makeDefaultProps({
            sites_usage: {
              totals: { sites: 1, drafts: 5, applied_recommendations: 2 },
              sites: [
                {
                  id: 10,
                  name: 'My Blog',
                  domain: 'myblog.com',
                  gsc_status: 'synced',
                  gsc_last_synced_at: null,
                  wp_status: null,
                  wp_last_synced_at: null,
                  latest_analysis_status: null,
                  latest_analysis_at: null,
                  drafts_count: 5,
                  recommendations_count: 3,
                  applied_recommendations_count: 2,
                },
              ],
            },
          })}
        />,
      );
      expect(screen.getByRole('link', { name: 'My Blog' })).toBeInTheDocument();
      expect(screen.queryByText('No sites')).not.toBeInTheDocument();
    });
  });

  describe('usage limits', () => {
    it('renders the Usage Limits card heading', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('Usage Limits')).toBeInTheDocument();
    });

    it('renders a row for each limit_defaults key', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      // max_sites_per_user → "Max Sites Per User"
      expect(screen.getByText('Max Sites Per User')).toBeInTheDocument();
      expect(screen.getByText('Max Drafts Per Month')).toBeInTheDocument();
    });

    it('shows default values in the table', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      // default value 5 is shown in the Default column
      expect(screen.getAllByText('5').length).toBeGreaterThanOrEqual(1);
    });
  });

  describe('audit logs', () => {
    it('shows empty state when no audit logs', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByText('No activity yet')).toBeInTheDocument();
    });

    it('renders audit log rows when logs are present', () => {
      render(
        <AdminUserShow
          {...makeDefaultProps({
            recent_audit_logs: [
              {
                id: 1,
                event: 'auth.login',
                ip: '127.0.0.1',
                created_at: '2026-03-01T10:00:00Z',
                metadata: null,
              },
            ],
          })}
        />,
      );
      expect(screen.getByText('auth.login')).toBeInTheDocument();
      expect(screen.getByText('127.0.0.1')).toBeInTheDocument();
    });
  });

  describe('back navigation', () => {
    it('renders "Back to Users" link', () => {
      render(<AdminUserShow {...makeDefaultProps()} />);
      expect(screen.getByRole('link', { name: /Back to Users/i })).toBeInTheDocument();
    });
  });
});
