import React, { useCallback, useEffect, useMemo, useState } from 'react';

import type {
  PromptResponse,
  PromptResponseEntry,
  PromptResponsesResponse,
} from '../../service/visibility/visibility.interface';
import { getPromptResponses } from '../../service/visibility/visibility.service';

import { isOwnDomain, sentimentToTone, toneToBadgeClass } from './helpers';
import Modal from './Modal';

interface PromptResponseModalProps {
  open: boolean;
  prompt: PromptResponse | null;
  onClose: () => void;
  clientId: string;
  token: string;
  brandId: string;
  brandDomain: string | null;
}

const SNIPPET_PREVIEW_CHARS = 500;

const EntryCard = ({
  entry,
  brandDomain,
}: {
  entry: PromptResponseEntry;
  brandDomain: string | null;
}): JSX.Element => {
  const [expanded, setExpanded] = useState(false);
  const snippet = entry.response_snippet ?? '';
  const shouldFold = snippet.length > SNIPPET_PREVIEW_CHARS;
  const visibleSnippet =
    shouldFold && !expanded
      ? `${snippet.slice(0, SNIPPET_PREVIEW_CHARS).trimEnd()}…`
      : snippet;

  const ownCitation = useMemo(
    () => entry.sources.some(source => isOwnDomain(source, brandDomain)),
    [entry.sources, brandDomain]
  );

  return (
    <div className="border border-gray-200 rounded-xl p-4 bg-white">
      <div className="flex flex-col gap-2">
        <div className="flex items-center gap-2 flex-wrap">
          <span
            className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${toneToBadgeClass('info')}`}
          >
            {entry.engine.toUpperCase()}
          </span>
          {entry.scan_date && (
            <span className="text-xs text-gray-500">
              {`Scan date: ${entry.scan_date.slice(0, 10)}`}
            </span>
          )}
          {entry.brand_mentioned ? (
            <span
              className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${toneToBadgeClass('success')}`}
            >
              {entry.brand_position
                ? `Mentioned · position #${entry.brand_position}`
                : 'Mentioned'}
            </span>
          ) : (
            <span
              className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${toneToBadgeClass('critical')}`}
            >
              Not mentioned
            </span>
          )}
          {entry.sentiment && (
            <span
              className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${toneToBadgeClass(sentimentToTone(entry.sentiment))}`}
            >
              {entry.sentiment}
            </span>
          )}
          {ownCitation && (
            <span
              className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${toneToBadgeClass('success')}`}
            >
              Cited from your domain
            </span>
          )}
        </div>

        {snippet && (
          <blockquote
            style={{
              borderLeft: '4px solid #B7007C',
              background: '#fff7fb',
              padding: '10px 14px',
              margin: 0,
              borderRadius: 4,
              color: '#4d4d4d',
              whiteSpace: 'pre-wrap',
              lineHeight: 1.55,
              fontSize: 14,
            }}
          >
            {visibleSnippet}
            {shouldFold && (
              <div style={{ marginTop: 6 }}>
                <button
                  type="button"
                  onClick={() => setExpanded(prev => !prev)}
                  className="text-sm font-medium text-pink-700 hover:underline"
                >
                  {expanded ? 'Show less' : 'Show more'}
                </button>
              </div>
            )}
          </blockquote>
        )}

        {entry.sources.length > 0 && (
          <div className="flex flex-col gap-1">
            <p className="text-xs font-semibold text-gray-900">Sources cited</p>
            <ul className="list-disc pl-5 text-sm">
              {entry.sources.map((source, idx) => {
                const own = isOwnDomain(source, brandDomain);

                return (
                  <li key={idx} className="my-1">
                    <span className="inline-flex items-center gap-1 flex-wrap">
                      {own && (
                        <span
                          aria-hidden="true"
                          className="inline-block w-2 h-2 rounded-full bg-green-700"
                        />
                      )}
                      <a
                        href={source}
                        target="_blank"
                        rel="noreferrer noopener"
                        className="underline break-all"
                        style={{
                          color: own ? '#3f7b00' : '#B7007C',
                          fontWeight: own ? 600 : 400,
                        }}
                      >
                        {source}
                      </a>
                    </span>
                  </li>
                );
              })}
            </ul>
          </div>
        )}
      </div>
    </div>
  );
};

/**
 * Modal showing every historical LLM response recorded for a tracked
 * prompt. Used as the "proof layer" behind visibility scores.
 */
const PromptResponseModal = ({
  open,
  prompt,
  onClose,
  clientId,
  token,
  brandId,
  brandDomain,
}: PromptResponseModalProps): JSX.Element => {
  const [data, setData] = useState<PromptResponsesResponse | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const load = useCallback(async () => {
    if (!prompt) return;
    setLoading(true);
    setError(null);
    try {
      const response = await getPromptResponses(
        clientId,
        token,
        brandId,
        prompt.prompt_id
      );
      setData(response);
    } catch (err) {
      setError(
        err instanceof Error ? err.message : 'Failed to load responses.'
      );
    } finally {
      setLoading(false);
    }
  }, [clientId, token, brandId, prompt]);

  useEffect(() => {
    if (open && prompt) {
      load();
    }
    if (!open) {
      setData(null);
      setError(null);
    }
  }, [open, prompt, load]);

  return (
    <Modal
      open={open}
      onClose={onClose}
      title="Prompt responses"
      size="lg"
      footer={
        <button
          type="button"
          onClick={onClose}
          className="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-50"
        >
          Close
        </button>
      }
    >
      <div className="flex flex-col gap-4">
        {prompt && (
          <div className="flex flex-col gap-2">
            <div className="flex items-center gap-2 flex-wrap">
              <span
                className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${toneToBadgeClass('info')}`}
              >
                {prompt.category}
              </span>
              <span
                className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${toneToBadgeClass(undefined)}`}
              >
                {prompt.language.toUpperCase()}
              </span>
            </div>
            <h3 className="text-base font-semibold text-gray-900">
              {prompt.prompt_text}
            </h3>
          </div>
        )}

        {error && (
          <div className="rounded-lg border border-red-200 bg-red-50 p-3 flex items-center justify-between gap-2">
            <p className="text-sm text-red-700">{error}</p>
            <button
              type="button"
              onClick={load}
              className="text-sm font-medium text-red-700 hover:text-red-900 underline"
            >
              Retry
            </button>
          </div>
        )}

        {loading ? (
          <div className="flex flex-col gap-3 animate-pulse">
            <div className="h-3 bg-gray-200 rounded w-full" />
            <div className="h-3 bg-gray-200 rounded w-11/12" />
            <div className="h-3 bg-gray-200 rounded w-10/12" />
            <div className="h-3 bg-gray-200 rounded w-full" />
          </div>
        ) : data && data.entries.length > 0 ? (
          <div className="flex flex-col gap-3">
            {data.entries.map((entry, idx) => (
              <EntryCard
                key={`${entry.engine}-${entry.scan_date ?? idx}`}
                entry={entry}
                brandDomain={brandDomain}
              />
            ))}
          </div>
        ) : (
          <p className="text-sm text-gray-500">
            No scan responses recorded yet for this prompt. Run a weekly scan to
            populate this history.
          </p>
        )}
      </div>
    </Modal>
  );
};

export default PromptResponseModal;
