import React, { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { Link } from 'react-router-dom';
import { HiSparkles as Sparkles } from 'react-icons/hi';
import { FaPaperPlane as Send } from 'react-icons/fa';

import { prepareGapKbDraft } from '../../service/agent-analytics/agent-analytics.service';
import { createTextEntry } from '../../service/knowledge-base/knowledge-base.service';
import {
  TEXT_ENTRY_BODY_MAX_LENGTH,
  TEXT_ENTRY_TITLE_MAX_LENGTH,
} from '../../service/knowledge-base/knowledge-base.routes';
import type {
  IAgentGap,
  IAgentGapKbDraft,
} from '../../service/agent-analytics/agent-analytics.interface';

/** Server-enforced max length of the "suggest more" hint - matches the
 *  ``extra_prompt`` cap on ``AgentGapKbDraftRequest`` in recomaze-agent. */
const SUGGEST_MORE_MAX_LENGTH: number = 600;

interface GapKbDraftModalProps {
  /** Gap row the merchant clicked "Prepare fix" on; used for the title
   *  fallback when the LLM returns an empty title. */
  gap: IAgentGap;
  /** Editable draft the agent generated (already language-detected). */
  draft: IAgentGapKbDraft;
  /** Called when the merchant cancels (also fired after a successful publish). */
  onClose: () => void;
  /** Called once the publish round-trip succeeds so the trigger button can
   *  flip into a "Published" state. */
  onPublished?: () => void;
}

/**
 * Modal that lets the merchant edit the LLM-drafted KB entry before
 * pushing it through ``createTextEntry``. The "Suggest more" zone
 * re-fires ``prepareGapKbDraft`` with the merchant's hint so the draft
 * can be regenerated in place without closing the modal.
 *
 * @param {GapKbDraftModalProps} props - Component props.
 * @return {JSX.Element} Modal overlay.
 */
function GapKbDraftModal({
  gap,
  draft,
  onClose,
  onPublished,
}: GapKbDraftModalProps): JSX.Element {
  const [title, setTitle] = useState<string>(draft.title || gap.target);
  const [body, setBody] = useState<string>(draft.body);
  const [language, setLanguage] = useState<string>(draft.language || 'en');
  const [extraPrompt, setExtraPrompt] = useState<string>('');
  const [submitting, setSubmitting] = useState<boolean>(false);
  const [regenerating, setRegenerating] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);

  const busy: boolean = submitting || regenerating;

  useEffect(() => {
    setTitle(draft.title || gap.target);
    setBody(draft.body);
    setLanguage(draft.language || 'en');
    setExtraPrompt('');
    setError(null);
  }, [draft.title, draft.body, draft.language, gap.target]);

  useEffect(() => {
    const handleEscape = (event: KeyboardEvent) => {
      if (event.key === 'Escape' && !busy) onClose();
    };
    document.addEventListener('keydown', handleEscape);
    return () => {
      document.removeEventListener('keydown', handleEscape);
    };
  }, [onClose, busy]);

  const handleRegenerate = async (): Promise<void> => {
    if (busy) return;
    setError(null);
    setRegenerating(true);
    try {
      const trimmedHint: string = extraPrompt.trim();
      const firstSample = gap.samples[0];
      const result: IAgentGapKbDraft | null = await prepareGapKbDraft({
        target: gap.target,
        category: gap.category,
        sample_fingerprint: firstSample?.fingerprint ?? null,
        sample_message_index: firstSample?.message_index ?? null,
        extra_prompt: trimmedHint || null,
      });
      if (!result) {
        setError('Failed to regenerate the draft.');
        return;
      }
      setTitle(result.title || gap.target);
      setBody(result.body);
      setLanguage(result.language || 'en');
      setExtraPrompt('');
    } catch (regenerateError) {
      setError(
        regenerateError instanceof Error
          ? regenerateError.message
          : 'Failed to regenerate the draft.'
      );
    } finally {
      setRegenerating(false);
    }
  };

  const handlePublish = async (): Promise<void> => {
    const trimmedTitle: string = title.trim();
    const trimmedBody: string = body.trim();
    if (!trimmedTitle || !trimmedBody) {
      setError('Title and body are both required.');
      return;
    }
    if (trimmedTitle.length > TEXT_ENTRY_TITLE_MAX_LENGTH) {
      setError(
        `Title must be ${TEXT_ENTRY_TITLE_MAX_LENGTH} characters or fewer.`
      );
      return;
    }
    if (trimmedBody.length > TEXT_ENTRY_BODY_MAX_LENGTH) {
      setError(
        `Body must be ${TEXT_ENTRY_BODY_MAX_LENGTH} characters or fewer. For longer documents, upload a file from the Knowledge Base page.`
      );
      return;
    }
    setError(null);
    setSubmitting(true);
    try {
      await createTextEntry({ title: trimmedTitle, description: trimmedBody });
      onPublished?.();
      onClose();
    } catch (publishError) {
      setError(
        publishError instanceof Error
          ? publishError.message
          : 'Failed to publish the KB entry.'
      );
    } finally {
      setSubmitting(false);
    }
  };

  if (typeof document === 'undefined') return <></>;

  return createPortal(
    <div className="fixed inset-0 z-[9999] flex items-center justify-center">
      <div
        className="absolute inset-0 bg-black/50"
        onClick={() => !busy && onClose()}
      />
      <div className="relative z-10 mx-4 flex max-h-[90vh] w-[min(100%,56rem)] flex-col overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-2xl">
        <div className="flex items-start justify-between gap-3 border-b border-gray-200 px-6 py-4">
          <div className="space-y-1">
            <h2 className="text-base font-semibold text-gray-900">
              Publish KB entry from gap
            </h2>
            <p className="text-xs text-gray-500">
              Edit the draft below, then publish it to the knowledge base. The
              agent will use it the next time a customer asks about{' '}
              <span className="font-semibold text-gray-900">{gap.target}</span>.
              Detected language: <span className="uppercase">{language}</span>.
            </p>
          </div>
          <button
            type="button"
            onClick={() => !busy && onClose()}
            aria-label="Close"
            className="flex h-7 w-7 cursor-pointer items-center justify-center rounded text-gray-500 hover:bg-gray-100 hover:text-gray-900"
          >
            ×
          </button>
        </div>

        <div className="flex-1 space-y-4 overflow-y-auto px-6 py-4">
          <div className="space-y-1.5">
            <label
              htmlFor="gap-kb-draft-title"
              className="text-xs font-medium text-gray-700"
            >
              Title
            </label>
            <input
              id="gap-kb-draft-title"
              value={title}
              onChange={event => setTitle(event.target.value)}
              maxLength={TEXT_ENTRY_TITLE_MAX_LENGTH}
              disabled={busy}
              placeholder="Short customer-facing question"
              className="block w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 focus:border-[#B7007C] focus:outline-none focus:ring-1 focus:ring-[#B7007C]"
            />
            <p className="text-[11px] text-gray-500">
              {title.length}/{TEXT_ENTRY_TITLE_MAX_LENGTH}
            </p>
          </div>

          <div className="space-y-1.5">
            <label
              htmlFor="gap-kb-draft-body"
              className="text-xs font-medium text-gray-700"
            >
              Body
            </label>
            <textarea
              id="gap-kb-draft-body"
              value={body}
              onChange={event => setBody(event.target.value)}
              maxLength={TEXT_ENTRY_BODY_MAX_LENGTH}
              disabled={busy}
              rows={14}
              placeholder="Plain-text answer the agent will quote next time"
              className="block w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm leading-relaxed text-gray-900 focus:border-[#B7007C] focus:outline-none focus:ring-1 focus:ring-[#B7007C]"
            />
            <p className="text-[11px] text-gray-500">
              {body.length}/{TEXT_ENTRY_BODY_MAX_LENGTH} characters. For longer
              documents, upload a file from the{' '}
              <Link
                to="/knowledge-base"
                className="font-medium text-[#B7007C] underline-offset-2 hover:underline"
              >
                Knowledge Base page
              </Link>
              .
            </p>
          </div>

          <div className="space-y-1.5 rounded-md border border-dashed border-[#B7007C]/40 bg-[#fff5fa] p-3">
            <label
              htmlFor="gap-kb-draft-extra-prompt"
              className="flex items-center gap-1.5 text-xs font-medium text-gray-700"
            >
              <Sparkles className="h-3.5 w-3.5 text-[#B7007C]" />
              Suggest more
            </label>
            <p className="text-xs text-gray-500">
              Tell the AI what to change in the draft above (e.g. make it
              shorter, add the 30-day return window, more formal tone). Leave
              empty to regenerate from scratch.
            </p>
            <textarea
              id="gap-kb-draft-extra-prompt"
              value={extraPrompt}
              onChange={event => setExtraPrompt(event.target.value)}
              maxLength={SUGGEST_MORE_MAX_LENGTH}
              disabled={busy}
              rows={3}
              placeholder="e.g. shorten, include shipping cost, more formal..."
              className="block w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm leading-relaxed text-gray-900 focus:border-[#B7007C] focus:outline-none focus:ring-1 focus:ring-[#B7007C]"
            />
            <div className="flex items-center justify-between gap-3">
              <p className="text-[11px] text-gray-500">
                {extraPrompt.length}/{SUGGEST_MORE_MAX_LENGTH}
              </p>
              <button
                type="button"
                onClick={handleRegenerate}
                disabled={busy}
                className="inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-md bg-[#B7007C] px-3 text-xs font-semibold text-white shadow-sm shadow-[#B7007C]/30 transition-colors hover:bg-[#9c006a] disabled:cursor-not-allowed disabled:opacity-60"
              >
                {regenerating ? (
                  <>
                    <span className="h-3.5 w-3.5 animate-spin rounded-full border-2 border-white/30 border-t-white" />
                    Regenerating...
                  </>
                ) : (
                  <>
                    <Sparkles className="h-3.5 w-3.5" />
                    Regenerate
                  </>
                )}
              </button>
            </div>
          </div>

          {error && (
            <p className="text-sm text-red-600" role="alert">
              {error}
            </p>
          )}
        </div>

        <div className="flex items-center justify-end gap-3 border-t border-gray-200 bg-gray-50 px-6 py-3">
          <button
            type="button"
            onClick={() => !busy && onClose()}
            disabled={busy}
            className="inline-flex h-9 cursor-pointer items-center rounded-md border border-gray-200 bg-white px-4 text-sm font-medium text-gray-700 transition-colors hover:border-gray-300 disabled:cursor-not-allowed disabled:opacity-50"
          >
            Cancel
          </button>
          <button
            type="button"
            onClick={handlePublish}
            disabled={busy}
            className="inline-flex h-9 cursor-pointer items-center gap-2 rounded-md bg-[#B7007C] px-4 text-sm font-semibold text-white shadow-sm shadow-[#B7007C]/30 transition-colors hover:bg-[#9c006a] disabled:cursor-not-allowed disabled:opacity-60"
          >
            {submitting ? (
              <>
                <span className="h-3.5 w-3.5 animate-spin rounded-full border-2 border-white/30 border-t-white" />
                Publishing...
              </>
            ) : (
              <>
                <Send className="h-3.5 w-3.5" />
                Publish to knowledge base
              </>
            )}
          </button>
        </div>
      </div>
    </div>,
    document.body
  );
}

export default GapKbDraftModal;
