import { useEffect, useState } from 'react';
import { CONFIG } from '../config';
import { getPromptGeneratePodcastScript } from '../utils/prompts';
//import { getSSEStreamAsync } from '../utils/utils';
import { EXAMPLES } from '../examples';
import { HfInference } from '@huggingface/inference';

interface SplitContent {
  thought: string;
  codeBlock: string;
}

const getFromTo = (content: string, from: string, to: string): string => {
  const firstSplit = content.split(from, 2);
  if (firstSplit[1] !== undefined) {
    const secondSplit = firstSplit[1].split(to, 1);
    return secondSplit[0];
  } else {
    return '';
  }
};

const splitContent = (content: string): SplitContent => {
  return {
    thought: getFromTo(content, '<think>', '</think>').trim(),
    codeBlock: getFromTo(content, '```yaml', '```').trim(),
  };
};

export const ScriptMaker = ({
  setScript,
  setBusy,
  busy,
  hfToken,
}: {
  setScript: (script: string) => void;
  setBusy: (busy: boolean) => void;
  busy: boolean;
  hfToken: string;
}) => {
  const [model, setModel] = useState<string>(CONFIG.inferenceProviderModels[0]);
  const [customModel, setCustomModel] = useState<string>(
    CONFIG.inferenceProviderModels[0]
  );
  const usingModel = model === 'custom' ? customModel : model;

  const [input, setInput] = useState<string>('');
  const [note, setNote] = useState<string>('');
  const [thought, setThought] = useState<string>('');
  const [isGenerating, setIsGenerating] = useState<boolean>(false);

  useEffect(() => {
    setBusy(isGenerating);
  }, [isGenerating]);

  const generate = async () => {
    setIsGenerating(true);
    setThought('');
    try {
      let responseContent = '';
      /*
      const fetchResponse = await fetch(CONFIG.llmEndpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${hfToken}`,
        },
        body: JSON.stringify({
          model: usingModel,
          messages: [
            {
              role: 'user',
              content: getPromptGeneratePodcastScript(input, note),
            },
          ],
          temperature: 0.3,
          stream: true,
          provider: CONFIG.inferenceProvider,
        }),
      });
      if (fetchResponse.status !== 200) {
        const body = await fetchResponse.json();
        throw new Error(body?.error?.message || body?.error || 'Unknown error');
      }
      const chunks = getSSEStreamAsync(fetchResponse);
      */
      const client = new HfInference(hfToken);
      const chunks = client.chatCompletionStream({
        model: usingModel,
        messages: [
          {
            role: 'user',
            content: getPromptGeneratePodcastScript(input, note),
          },
        ],
        temperature: 0.3,
        stream: true,
        provider: CONFIG.inferenceProvider,
      });
      for await (const chunk of chunks) {
        // const stop = chunk.stop;
        //if (chunk.error) {
        //  throw new Error(chunk.error?.message || 'Unknown error');
        //}
        const addedContent = chunk.choices[0].delta.content;
        responseContent += addedContent;
        const { thought, codeBlock } = splitContent(responseContent);
        setThought(thought);
        if (codeBlock.length > 0) {
          setScript(codeBlock);
        }
      }
    } catch (error) {
      console.error(error);
      alert(`ERROR: ${error}`);
    }
    setIsGenerating(false);
  };

  return (
    <div className="card bg-base-100 w-full shadow-xl">
      <div className="card-body">
        <h2 className="card-title">Step 1: Input information</h2>

        <select
          className="select select-bordered w-full"
          disabled={isGenerating || busy}
          onChange={(e) => {
            const idx = parseInt(e.target.value);
            const ex = EXAMPLES[idx];
            if (ex) {
              setInput(ex.input);
              setNote(ex.note);
            }
          }}
        >
          <option selected disabled value={-1}>
            Try one of these examples!!
          </option>
          {EXAMPLES.map((example, index) => (
            <option key={index} value={index}>
              {example.name}
            </option>
          ))}
        </select>

        <textarea
          className="textarea textarea-bordered w-full h-72 p-2"
          placeholder="Type your input information here (an article, a document, etc)..."
          value={input}
          onChange={(e) => setInput(e.target.value)}
          disabled={isGenerating || busy}
        ></textarea>

        <textarea
          className="textarea textarea-bordered w-full h-24 p-2"
          placeholder="Optional note (the theme, tone, etc)..."
          value={note}
          onChange={(e) => setNote(e.target.value)}
          disabled={isGenerating || busy}
        ></textarea>

        <select
          className="select select-bordered"
          value={model}
          onChange={(e) => setModel(e.target.value)}
        >
          {CONFIG.inferenceProviderModels.map((s) => (
            <option key={s} value={s}>
              {s}
            </option>
          ))}
          <option value="custom">Custom</option>
        </select>

        {model === 'custom' && (
          <input
            type="text"
            placeholder="Use a custom model from HF Hub (must be supported by Inference Providers)"
            className="input input-bordered w-full"
            value={customModel}
            onChange={(e) => setCustomModel(e.target.value)}
          />
        )}

        {thought.length > 0 && (
          <>
            <p>Thought process:</p>
            <textarea
              className="textarea textarea-bordered w-full h-24 p-2"
              value={thought}
              readOnly
            ></textarea>
          </>
        )}
        <button
          className="btn btn-primary mt-2"
          onClick={generate}
          disabled={isGenerating || busy || input.length < 10}
        >
          {isGenerating ? (
            <>
              <span className="loading loading-spinner loading-sm"></span>
              Generating...
            </>
          ) : (
            'Generate script'
          )}
        </button>

        {/* <div role="alert" className="alert text-sm">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            className="stroke-info h-6 w-6 shrink-0"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth="2"
              d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
            ></path>
          </svg>
          <span>
            The LLM may generate an incorrect YAML. If it fails on Step 2,
            re-generate the script or adding a note to force it to follow YAML
            format.
          </span>
        </div> */}
      </div>
    </div>
  );
};
