import { describe, test, expect, vi } from 'vitest';
import { render, waitFor } from '@testing-library/react';
import { AppStateProvider, type Draft, useDraft, useDrupal } from '../Context.js';
import DraftManager from './DraftManager.js';
import createDraftResponse from '../../../tests/fixtures/api/post-get-draft-writing-assistant-200.json' with { type: 'json' };

describe('DraftManager', () => {
  describe('Draft Creation', () => {
    test('Saves newly created draft information to drupalSettings', async () => {
      Object.defineProperty(window, 'drupalSettings', {
        writable: true,
        configurable: true,
        value: {
          conductor: {
            accountId: '12345',
            draftId: '',
            maxDrafts: 5,
            usedDrafts: 2,
          },
          canvas: {
            entityId: '1',
            entityType: 'canvas_page',
          },
        },
      });

      const initialState = {
        accountId: '12345',
        drupal: {
          entity: {
            id: 1,
            type: 'canvas_page',
          },
          draftLinked: false,
        },
      };

      render(
        <AppStateProvider initialState={initialState}>
          <DraftManager />
        </AppStateProvider>,
      );

      await waitFor(() => {
        expect(window?.drupalSettings?.conductor?.draftId).toBe(
          'bead88f1-bd37-48a7-9861-46f04058141d',
        );
      });

      expect(window?.drupalSettings?.conductor?.usedDrafts).toBe(3);
    });

    test('Creates a draft and links it when no draft ID exists', async () => {
      const initialState = {
        accountId: '12345',
        drupal: {
          entity: {
            id: 1,
            type: 'canvas_page',
          },
          draftLinked: false,
        },
      };
      const isLoading = vi.fn();
      const hasError = vi.fn();

      let draft: Draft;
      let drupal: { draftLinked?: boolean };
      const ContextCapture = () => {
        draft = useDraft();
        drupal = useDrupal();
        return null;
      };
      render(
        <AppStateProvider initialState={initialState}>
          <DraftManager isLoading={isLoading} hasError={hasError} />
          <ContextCapture />
        </AppStateProvider>,
      );

      await waitFor(() => {
        expect(draft.id).toBe(createDraftResponse.id);
        expect(drupal.draftLinked).toBe(true);
      });
      expect(isLoading).toHaveBeenCalled();
    });

    test('When draft.id exists Draft is not created', async () => {
      let draft: Draft;
      const ContextCapture = () => {
        draft = useDraft();
        return null;
      };
      render(
        <AppStateProvider initialState={{ draft: { id: 'existing-draft-id-123' } }}>
          <DraftManager />
          <ContextCapture />
        </AppStateProvider>,
      );

      await waitFor(() => {
        expect(draft.id).toBe('existing-draft-id-123');
      });
    });
  });

  describe('Draft Linking with Drupal Entity', () => {
    test('Links draft with Drupal entity when draft.id exists and draftLinked is false', async () => {
      const initialState = {
        accountId: '12345',
        draft: {
          id: 'existing-draft-id-123',
        },
        drupal: {
          entity: {
            id: 1,
            type: 'canvas_page',
          },
          draftLinked: false,
        },
      };

      let drupal: { draftLinked?: boolean };
      const ContextCapture = () => {
        drupal = useDrupal();
        return null;
      };

      render(
        <AppStateProvider initialState={initialState}>
          <DraftManager />
          <ContextCapture />
        </AppStateProvider>,
      );

      await waitFor(() => {
        expect(drupal.draftLinked).toBe(true);
      });
    });

    test('does not link draft when entity.id is invalid', async () => {
      const initialState = {
        accountId: '12345',
        draft: {
          id: 'existing-draft-123',
        },
        drupal: {
          entity: {
            id: 0,
            type: 'canvas_page',
          },
          draftLinked: false,
        },
      };

      let drupal: { draftLinked?: boolean };
      const ContextCapture = () => {
        drupal = useDrupal();
        return null;
      };
      render(
        <AppStateProvider initialState={initialState}>
          <DraftManager />
          <ContextCapture />
        </AppStateProvider>,
      );

      await waitFor(() => {
        expect(drupal.draftLinked).toBe(false);
      });
    });
  });

  describe('Draft Update', () => {
    test('updates draft when draft.id, lastUpdated exist', async () => {
      const initialState = {
        accountId: '12345',
        draft: {
          id: 'existing-draft-123',
          lastUpdated: 1760026532,
        },
        drupal: {
          entity: {
            id: 1,
            type: 'canvas_page',
          },
          draftLinked: true,
        },
      };

      let draft: Draft;
      const ContextCapture = () => {
        draft = useDraft();
        return null;
      };
      render(
        <AppStateProvider initialState={initialState}>
          <DraftManager />
          <ContextCapture />
        </AppStateProvider>,
      );

      await waitFor(() => {
        expect(draft.id).toBe('existing-draft-123');
        expect(draft.title).toBe('Untitled Canvas draft');
        expect(draft.lastUpdated).toBe(1760088081);
      });
    });
  });

  describe('Content Insights', () => {
    test('requests content insights when draft.id exists', async () => {
      const isLoading = vi.fn();
      const hasError = vi.fn();
      const initialState = {
        accountId: '12345',
        draft: {
          id: 'existing-draft-123',
          lastUpdated: 1760026532,
        },
        drupal: {
          entity: {
            id: 1,
            type: 'canvas_page',
          },
          draftLinked: true,
        },
        keywords: ['test keyword', 'seo'],
        rankSource: {
          id: 1,
          description: 'Google US',
          isoLocale: 'en-US',
        },
        competitorUrls: ['https://example.com'],
      };

      render(
        <AppStateProvider initialState={initialState}>
          <DraftManager isLoading={isLoading} hasError={hasError} />
        </AppStateProvider>,
      );

      // Wait for the insights to be loaded successfully
      // isLoading(false) is only called when insights data is available
      await waitFor(() => {
        expect(isLoading).toHaveBeenCalledWith(false);
      });
      expect(hasError).not.toHaveBeenCalledWith(true);
      expect(isLoading).toHaveBeenCalledWith(true);
    });
  });
});
