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 getInsights from '../../../tests/fixtures/api/get-insights-200.json' with { type: 'json' };
import getInsights2 from '../../../tests/fixtures/api/get-insights-200_2.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 postInsights2 from '../../../tests/fixtures/api/post-insights-200_2.json' with { type: 'json' };
import postMetaDescription from '../../../tests/fixtures/api/post-meta-description-200.json' with { type: 'json' };
import postOutlineExpansion from '../../../tests/fixtures/api/post-outline-expansion-200.json' with { type: 'json' };
import postTextShortener from '../../../tests/fixtures/api/post-text-shortener-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 putInsights from '../../../tests/fixtures/api/put-insights-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;
let insightsRequestCount = 0;

export const resetRequestCounts = () => {
  contentGuidanceRequestCount = 0;
  competitorUrlRequestCount = 0;
  titleRequestCount = 0;
  insightsRequestCount = 0;
};

const returnStream = (
  response: {
    chunk: string | null;
    id: string | null;
  }[],
  delay: number = 20,
) => {
  const encoder = new TextEncoder();

  const stream = new ReadableStream({
    async start(controller) {
      for (const chunk of response) {
        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' },
  });
};

export const handlers = [
  http.get('/conductor/api/settings', () =>
    HttpResponse.json({ accountId: '12345', maxDrafts: 5, usedDrafts: 2 }),
  ),
  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 <= 1) {
        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 ({}) => {
      insightsRequestCount++;
      if (insightsRequestCount % 2 === 0) {
        return HttpResponse.json(postInsights);
      }
      return HttpResponse.json(postInsights2);
    },
  ),
  http.put(
    '/conductor/proxy/v3/accounts/:accountId/insights/:draftId/writing-assistant',
    async ({}) => {
      return HttpResponse.json(putInsights);
    },
  ),
  http.get(
    '/conductor/proxy/v3/accounts/:accountId/insights/:draftId/writing-assistant',
    async ({}) => {
      await delay(2000);
      if (insightsRequestCount % 2 === 0) {
        return HttpResponse.json(getInsights);
      }
      return HttpResponse.json(getInsights2);
    },
  ),
  http.get(
    '/conductor/api/draft/:entityType/:entityId',
    () => new HttpResponse(null, { status: 404 }),
  ),
  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;
    }

    return returnStream(returnedContent, delay);
  }),
  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;
    }

    return returnStream(returnedContent, delay);
  }),
  http.post('/conductor/proxy/v3/outline-expansion/content-generation', async () =>
    returnStream(postOutlineExpansion),
  ),
  http.post('/conductor/proxy/v3/text-shortener/content-generation', async () =>
    returnStream(postTextShortener),
  ),
];
