import { delay, http, HttpResponse } from 'msw';

import getBatchUntrackedSerp200 from '../../../tests/fixtures/api/get-batch-untracked-serp-200.json' with { type: 'json' };
import getBatchUntrackedSerp200_2 from '../../../tests/fixtures/api/get-batch-untracked-serp-200_2.json' with { type: 'json' };
import getContentGuidance from '../../../tests/fixtures/api/get-content-guidance-200.json' with { type: 'json' };
import getContentGuidanceSnippetsError from '../../../tests/fixtures/api/get-content-guidance-200_snippets-error.json' with { type: 'json' };
import getContentGuidancePending from '../../../tests/fixtures/api/get-content-guidance-pending-200.json' with { type: 'json' };
import getRankSources200 from '../../../tests/fixtures/api/get-rank-sources-200.json' with { type: 'json' };
import postContentGuidance from '../../../tests/fixtures/api/post-content-guidance-200.json' with { type: 'json' };
import postContentGuidance_2 from '../../../tests/fixtures/api/post-content-guidance-200_2.json' with { type: 'json' };
import postContentGuidance_3 from '../../../tests/fixtures/api/post-content-guidance-200_3.json' with { type: 'json' };
import postGenerateContentOutline from '../../../tests/fixtures/api/post-generate-content-outline-200.json' with { type: 'json' };
import postGenerateContentOutline2 from '../../../tests/fixtures/api/post-generate-content-outline-200_2.json' with { type: 'json' };
import postGenerateDraft from '../../../tests/fixtures/api/post-generate-draft-200.json' with { type: 'json' };
import postGenerateDraft2 from '../../../tests/fixtures/api/post-generate-draft-200_2.json' with { type: 'json' };
import postGetDraftWritingAssistant from '../../../tests/fixtures/api/post-get-draft-writing-assistant-200.json' with { type: 'json' };
import postInsights from '../../../tests/fixtures/api/post-insights-200.json' with { type: 'json' };
import postMetaDescription from '../../../tests/fixtures/api/post-meta-description-200.json' with { type: 'json' };
import postTitleTag from '../../../tests/fixtures/api/post-title-tag-200.json' with { type: 'json' };
import postTitleTag2 from '../../../tests/fixtures/api/post-title-tag-200_2.json' with { type: 'json' };
import validateKeywords from '../../../tests/fixtures/api/post-validate-keywords-200.json' with { type: 'json' };
import validateKeywords2 from '../../../tests/fixtures/api/post-validate-keywords-200_2.json' with { type: 'json' };
import putDraftWritingAssistant from '../../../tests/fixtures/api/put-draft-writing-assistant-200.json' with { type: 'json' };
import postSuccess from '../../../tests/fixtures/api/success-201.json' with { type: 'json' };

interface RequestBody {
  request_id?: string;
  status?: string;
  input?: {
    topic?: {
      phrase?: string;
    };
  };
  title?: string;
  draftTitle?: string;
}

let contentGuidanceRequestCount = 0;
let competitorUrlRequestCount = 0;
let titleRequestCount = 0;

export const handlers = [
  http.get<{ accountId: string }>(
    '/conductor/proxy/v3/:accountId/rank-sources/content-guidance',
    () => HttpResponse.json(getRankSources200),
  ),
  http.get<{ accountId: string }>(
    '/conductor/proxy/v3/accounts/:accountId/batch-untracked-serp/serp-explorer',
    async ({ request }) => {
      competitorUrlRequestCount++;
      const url = new URL(request.url);
      const firstQuery = url.searchParams.get('queries[0]');
      if (firstQuery === 'jawn') {
        return HttpResponse.json(getBatchUntrackedSerp200);
      } else if (firstQuery === 'schuylkill' && competitorUrlRequestCount <= 2) {
        return new HttpResponse(null, { status: 500 });
      }
      return HttpResponse.json(getBatchUntrackedSerp200_2);
    },
  ),
  http.post<{ accountId: string }>(
    '/conductor/proxy/v3/:accountId/content-guidance',
    async ({ request }) => {
      const body = (await request.json()) as RequestBody;
      if (
        body?.request_id === 'e24d85a7-33a5-4707-80f2-79bb908793ba' &&
        body.status === 'SUBMITTED'
      ) {
        return HttpResponse.json(postContentGuidance);
      } else if (body?.input?.topic?.phrase === 'cheese steak') {
        return new HttpResponse(null, { status: 500 });
      } else if (body?.input?.topic?.phrase === 'rocky') {
        return HttpResponse.json(postContentGuidance_3);
      }

      return HttpResponse.json(postContentGuidance_2);
    },
  ),
  http.post<{ accountId: string }>(
    '/conductor/proxy/v3/accounts/:accountId/drafts/writing-assistant',
    () => HttpResponse.json(postGetDraftWritingAssistant),
  ),
  http.put<{ accountId: string; draftId: string }>(
    '/conductor/proxy/v3/accounts/:accountId/drafts/:draftId/writing-assistant',
    async ({ request }) => {
      const body = (await request.json()) as RequestBody;
      if (body?.draftTitle === 'Bad title') {
        return new HttpResponse(null, { status: 500 });
      }
      return HttpResponse.json(putDraftWritingAssistant);
    },
  ),
  http.get<{ accountId: string; draftId: string }>(
    '/conductor/proxy/v3/accounts/:accountId/drafts/:draftId/writing-assistant',
    () => HttpResponse.json(postGetDraftWritingAssistant),
  ),
  http.get<{ accountId: string }>(
    '/conductor/proxy/v3/:accountId/content-guidance',
    ({ request }) => {
      const url = new URL(request.url);
      const requestId = url.searchParams.get('requestUuid');
      if (requestId === '2615c4f4-0f90-48c4-83d4-74bb3ce87f82') {
        return HttpResponse.json(getContentGuidanceSnippetsError);
      }

      contentGuidanceRequestCount++;

      // Return the completed data every 3rd request.
      if (contentGuidanceRequestCount % 3) {
        return HttpResponse.json(getContentGuidancePending);
      }
      return HttpResponse.json(getContentGuidance);
    },
  ),
  http.post('/conductor/proxy/v3/title-tag/content-generation', async () => {
    await delay(2000);
    titleRequestCount++;
    if (titleRequestCount % 2) {
      return HttpResponse.json(postTitleTag);
    }
    return HttpResponse.json(postTitleTag2);
  }),
  http.post('/conductor/proxy/v3/meta-description/content-generation', async () => {
    await delay(2000);
    return HttpResponse.json(postMetaDescription);
  }),
  http.post(
    '/conductor/proxy/v3/:accountId/drafts/:draftId/validate-keywords/content-guidance',
    async ({ request }) => {
      const body = (await request.json()) as RequestBody;
      if (body?.title === 'Title with no relevance') {
        return HttpResponse.json(validateKeywords2);
      }
      return HttpResponse.json(validateKeywords);
    },
  ),
  http.post(
    '/conductor/proxy/v3/accounts/:accountId/insights/:draftId/writing-assistant',
    async ({}) => {
      return HttpResponse.json(postInsights);
    },
  ),
  http.post<{
    canvasPageId: string;
    data: string;
  }>('/conductor/api/draft/:entityType/:entityId', async ({}) => {
    return HttpResponse.json(postSuccess, { status: 201 });
  }),
  http.post('/conductor/proxy/v3/content-outline/content-generation', async ({ request }) => {
    const url = new URL(request.url);
    const draftId = url.searchParams.get('draft_id');

    if (draftId === '12345-bad') {
      return new HttpResponse(null, { status: 500 });
    }

    let delay = 100;
    let returnedContent = postGenerateContentOutline;
    if (draftId === '12345') {
      delay = 0;
      returnedContent = postGenerateContentOutline2;
    }
    const encoder = new TextEncoder();

    const stream = new ReadableStream({
      async start(controller) {
        for (const chunk of returnedContent) {
          await new Promise((resolve) => setTimeout(resolve, delay));
          const line = JSON.stringify(chunk) + '\n';
          controller.enqueue(encoder.encode(line));
        }

        controller.close();
      },
    });

    return new HttpResponse(stream, {
      headers: { 'Content-Type': 'application/x-ndjson' },
    });
  }),
  http.post('/conductor/proxy/v3/draft-generation/content-generation', async ({ request }) => {
    const url = new URL(request.url);
    const draftId = url.searchParams.get('draft_id');

    if (draftId === '12345-bad') {
      return new HttpResponse(null, { status: 500 });
    }

    let delay = 20;
    let returnedContent = postGenerateDraft;
    if (draftId === '12345') {
      delay = 0;
      returnedContent = postGenerateDraft2;
    }
    const encoder = new TextEncoder();

    const stream = new ReadableStream({
      async start(controller) {
        for (const chunk of returnedContent) {
          await new Promise((resolve) => setTimeout(resolve, delay));
          const line = JSON.stringify(chunk) + '\n';
          controller.enqueue(encoder.encode(line));
        }

        controller.close();
      },
    });

    return new HttpResponse(stream, {
      headers: { 'Content-Type': 'application/x-ndjson' },
    });
  }),
];
