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

import { useForm } from '@inertiajs/react';

import General from './General';

const { mockPatch, mockDelete } = vi.hoisted(() => ({
  mockPatch: vi.fn(),
  mockDelete: vi.fn(),
}));

let mockFormData = { name: 'Acme', domain: 'https://acme.com' };
let mockErrors: Record<string, string> = {};
let mockProcessing = false;
let mockIsDirty = false;

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    useForm: vi.fn((initial: Record<string, string>) => {
      mockFormData = { ...initial } as { name: string; domain: string };
      return {
        data: mockFormData,
        setData: vi.fn((key: string, value: string) => {
          mockFormData = { ...mockFormData, [key]: value };
          mockIsDirty = true;
        }),
        patch: mockPatch,
        processing: mockProcessing,
        errors: mockErrors,
        isDirty: mockIsDirty,
      };
    }),
    router: { delete: mockDelete, visit: vi.fn(), post: vi.fn(), patch: vi.fn(), on: vi.fn(() => vi.fn()) },
    usePage: vi.fn(() => ({
      props: {
        auth: { user: { id: 1, name: 'Owner' } },
        errors: {},
        flash: {},
        features: {},
        sites: [],
        limits: null,
        ai_defaults: {},
        notifications_unread_count: 0,
      },
    })),
  };
});

vi.mock('@/Layouts/DashboardLayout', () => ({
  default: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="dashboard-layout">{children}</div>
  ),
}));

const defaultSite = {
  id: 1,
  name: 'Acme',
  domain: 'https://acme.com',
  created_at: '2026-04-01T00:00:00Z',
  is_owner: true,
  has_gsc_connection: false,
  has_wp_connection: false,
};

describe('Sites/Settings/General', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    mockErrors = {};
    mockProcessing = false;
    mockIsDirty = false;
    mockFormData = { name: 'Acme', domain: 'https://acme.com' };
    vi.stubGlobal(
      'route',
      vi.fn((name: string, _params?: unknown) => {
        if (name === 'sites.update') return '/sites/1';
        if (name === 'sites.destroy') return '/sites/1';
        return '/sites/1/settings/general';
      }),
    );
  });

  it('renders the form with current site data', () => {
    render(<General site={defaultSite} />);

    expect(screen.getByLabelText(/site name/i)).toHaveValue('Acme');
    expect(screen.getByLabelText(/^domain$/i)).toHaveValue('https://acme.com');
    expect(screen.getByRole('button', { name: /save changes/i })).toBeInTheDocument();
  });

  it('submits patch on save', () => {
    mockIsDirty = true;
    render(<General site={defaultSite} />);

    fireEvent.submit(screen.getByLabelText(/site name/i).closest('form')!);

    expect(mockPatch).toHaveBeenCalledWith('/sites/1', expect.objectContaining({ preserveScroll: true }));
  });

  it('renders server validation errors', () => {
    mockErrors = { name: 'Name is required', domain: 'Invalid URL' };
    render(<General site={defaultSite} />);

    expect(screen.getByText('Name is required')).toBeInTheDocument();
    expect(screen.getByText('Invalid URL')).toBeInTheDocument();
  });

  it('hides danger zone for non-owner', () => {
    render(<General site={{ ...defaultSite, is_owner: false }} />);

    expect(screen.queryByRole('heading', { name: /danger zone/i })).not.toBeInTheDocument();
    expect(screen.queryByRole('button', { name: /delete this site/i })).not.toBeInTheDocument();
  });

  // SC-4: Danger Zone collapsed by default
  it('shows "Danger zone" toggle button for owner but hides delete actions by default (SC-4)', () => {
    render(<General site={defaultSite} />);

    // The Danger zone heading/toggle is visible
    expect(screen.getByRole('button', { name: /danger zone/i })).toBeInTheDocument();
    // But the destructive delete button is hidden until expanded
    expect(screen.queryByRole('button', { name: /delete this site/i })).not.toBeInTheDocument();
  });

  it('reveals delete button when Danger zone is expanded (SC-4)', () => {
    render(<General site={defaultSite} />);

    fireEvent.click(screen.getByRole('button', { name: /danger zone/i }));

    expect(screen.getByRole('button', { name: /delete this site/i })).toBeInTheDocument();
  });

  it('shows danger zone for owner and reveals typed-confirmation flow', () => {
    render(<General site={defaultSite} />);

    // First expand the Danger zone section
    fireEvent.click(screen.getByRole('button', { name: /danger zone/i }));

    const trigger = screen.getByRole('button', { name: /delete this site/i });
    fireEvent.click(trigger);

    expect(screen.getByLabelText(/type/i, { selector: 'input' })).toBeInTheDocument();
    const confirmBtn = screen.getByRole('button', { name: /delete site permanently/i });
    expect(confirmBtn).toBeDisabled();
  });

  it('enables delete only when typed domain matches', () => {
    render(<General site={defaultSite} />);

    // Expand Danger zone first
    fireEvent.click(screen.getByRole('button', { name: /danger zone/i }));
    fireEvent.click(screen.getByRole('button', { name: /delete this site/i }));

    const input = screen.getByLabelText(/type/i, { selector: 'input' });
    fireEvent.change(input, { target: { value: 'https://wrong.com' } });
    expect(screen.getByRole('button', { name: /delete site permanently/i })).toBeDisabled();

    fireEvent.change(input, { target: { value: 'https://acme.com' } });
    expect(screen.getByRole('button', { name: /delete site permanently/i })).toBeEnabled();
  });

  it('calls router.delete on confirmed delete', () => {
    render(<General site={defaultSite} />);

    // Expand Danger zone first
    fireEvent.click(screen.getByRole('button', { name: /danger zone/i }));
    fireEvent.click(screen.getByRole('button', { name: /delete this site/i }));
    fireEvent.change(screen.getByLabelText(/type/i, { selector: 'input' }), {
      target: { value: 'https://acme.com' },
    });
    fireEvent.click(screen.getByRole('button', { name: /delete site permanently/i }));

    expect(mockDelete).toHaveBeenCalledWith('/sites/1', expect.any(Object));
  });

  it('shows GSC reconnect warning when domain differs from site and GSC is connected', () => {
    vi.mocked(useForm).mockReturnValueOnce({
      data: { name: 'Acme', domain: 'https://renamed.com' },
      setData: vi.fn(),
      patch: mockPatch,
      processing: false,
      errors: {},
      isDirty: true,
    } as unknown as ReturnType<typeof useForm>);

    render(
      <General
        site={{
          ...defaultSite,
          domain: 'https://acme.com',
          has_gsc_connection: true,
        }}
      />,
    );

    expect(screen.getByText(/google search console connection/i)).toBeInTheDocument();
  });

  it('does not show reconnect warning when domain unchanged', () => {
    render(<General site={{ ...defaultSite, has_gsc_connection: true }} />);

    expect(screen.queryByText(/google search console connection/i)).not.toBeInTheDocument();
  });
});
