import { useId, useMemo, useRef, useState } from "react";

import { Icon } from "../../../components/Icon";
import {
  CHAT_MAX_TOKENS_LIMIT,
  CHAT_QUESTION_MAX_LENGTH,
  CHAT_REQUEST_LIMIT_MAX,
  DEFAULT_CHAT_INPUT,
  type ChatCompletionRequest,
  type ChatFormInput,
  validateChatInput,
} from "../types";

interface ChatComposerProps {
  isRunning: boolean;
  onStart: (request: ChatCompletionRequest) => void;
  onStop: () => void;
}

export function ChatComposer({ isRunning, onStart, onStop }: ChatComposerProps) {
  const [input, setInput] = useState<ChatFormInput>(DEFAULT_CHAT_INPUT);
  const [submitted, setSubmitted] = useState(false);
  const formRef = useRef<HTMLFormElement>(null);
  const errorId = useId();
  const validation = useMemo(() => validateChatInput(input), [input]);
  const showValidation = submitted && validation.request === null;

  function updateInput<K extends keyof ChatFormInput>(key: K, value: ChatFormInput[K]) {
    setInput((current) => ({ ...current, [key]: value }));
    if (submitted) setSubmitted(false);
  }

  function submit() {
    setSubmitted(true);
    if (isRunning || validation.request === null) return;
    onStart(validation.request);
  }

  return (
    <section aria-labelledby="chat-composer-heading" className="chat-composer-panel">
      <div className="section-heading">
        <div>
          <span className="eyebrow">GROUNDED QUESTION</span>
          <h2 id="chat-composer-heading">提交证据约束问题</h2>
        </div>
        <span className="section-heading__meta">POST · SSE</span>
      </div>

      <form
        aria-busy={isRunning}
        className="chat-composer"
        onSubmit={(event) => {
          event.preventDefault();
          submit();
        }}
        ref={formRef}
      >
        <label className="field-label" htmlFor="chat-knowledge-base">
          知识库 ID
        </label>
        <input
          className="text-input text-input--mono"
          disabled={isRunning}
          id="chat-knowledge-base"
          onChange={(event) => updateInput("knowledgeBaseId", event.target.value)}
          spellCheck={false}
          type="text"
          value={input.knowledgeBaseId}
        />
        <p className="field-hint">默认使用公开合成知识库，访问 scope 始终由后端身份决定。</p>

        <label className="field-label chat-composer__question-label" htmlFor="chat-question">
          地质问题
        </label>
        <div className={`query-box${showValidation ? " query-box--error" : ""}`}>
          <textarea
            aria-describedby={showValidation ? errorId : undefined}
            aria-invalid={showValidation}
            disabled={isRunning}
            id="chat-question"
            maxLength={CHAT_QUESTION_MAX_LENGTH}
            onChange={(event) => updateInput("question", event.target.value)}
            onKeyDown={(event) => {
              if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
                event.preventDefault();
                formRef.current?.requestSubmit();
              }
            }}
            rows={5}
            value={input.question}
          />
          <span
            className={`character-count${input.question.length >= 450 ? " character-count--warning" : ""}`}
          >
            {input.question.length}/{CHAT_QUESTION_MAX_LENGTH}
          </span>
        </div>
        <p className="field-hint">Enter 发送，Shift + Enter 换行。回答只允许使用本次检索证据。</p>

        <details className="chat-advanced-settings">
          <summary>运行参数</summary>
          <div className="chat-parameter-grid">
            <label htmlFor="chat-vector-top-k">
              <span>Vector Top K</span>
              <input
                disabled={isRunning}
                id="chat-vector-top-k"
                max={CHAT_REQUEST_LIMIT_MAX}
                min={1}
                onChange={(event) => updateInput("vectorTopK", event.target.value)}
                type="number"
                value={input.vectorTopK}
              />
            </label>
            <label htmlFor="chat-rerank-top-n">
              <span>Rerank Top N</span>
              <input
                disabled={isRunning}
                id="chat-rerank-top-n"
                max={CHAT_REQUEST_LIMIT_MAX}
                min={1}
                onChange={(event) => updateInput("rerankTopN", event.target.value)}
                type="number"
                value={input.rerankTopN}
              />
            </label>
            <label htmlFor="chat-max-tokens">
              <span>回答 Token 上限</span>
              <input
                disabled={isRunning}
                id="chat-max-tokens"
                max={CHAT_MAX_TOKENS_LIMIT}
                min={1}
                onChange={(event) => updateInput("maxTokens", event.target.value)}
                type="number"
                value={input.maxTokens}
              />
            </label>
          </div>
        </details>

        {showValidation ? (
          <p className="field-error chat-composer__error" id={errorId} role="alert">
            {validation.message}
          </p>
        ) : null}

        <div className="chat-composer__actions">
          <button
            className="tertiary-button"
            disabled={isRunning}
            onClick={() => {
              setInput(DEFAULT_CHAT_INPUT);
              setSubmitted(false);
            }}
            type="button"
          >
            恢复合成示例
          </button>
          {isRunning ? (
            <button className="stop-button" onClick={onStop} type="button">
              <span aria-hidden="true" />
              停止回答
            </button>
          ) : (
            <button className="primary-button" type="submit">
              <Icon name="layers" size={19} />
              开始证据问答
              <Icon name="arrow" size={17} />
            </button>
          )}
        </div>
      </form>
    </section>
  );
}
