import { customElement, noShadowDOM } from 'solid-element';
import {createSignal, createResource, For, Show, createEffect} from 'solid-js';
import { parseYarn, compile, YarnRunner } from '../yarn-spinner';
import type { RunnerOptions } from '../yarn-spinner/runtime/runner';
import type { RuntimeResult, TextResult, OptionsResult } from '../yarn-spinner/runtime/results';
import {loadElementSrc, resolvePath} from "./utils/path";

// 缓存已加载的 yarn 文件内容
const yarnCache = new Map<string, string>();

// 加载 yarn 文件内容
async function loadYarnFile(path: string): Promise<string> {
  if (yarnCache.has(path)) {
    return yarnCache.get(path)!;
  }
  const response = await fetch(path);
  const content = await response.text();
  yarnCache.set(path, content);
  return content;
}

// 加载多个 yarn 文件并拼接
async function loadYarnFiles(paths: string[]): Promise<string> {
  const contents = await Promise.all(paths.map(path => loadYarnFile(path)));
  return contents.join('\n');
}

customElement<RunnerOptions>('md-yarn-spinner', { 
  startAt: "start",
}, (props, { element }) => {
  noShadowDOM();
  
  const [dialogueHistory, setDialogueHistory] = createSignal<RuntimeResult[]>([]);
  const [currentOptions, setCurrentOptions] = createSignal<OptionsResult | null>(null);
  const [isEnded, setIsEnded] = createSignal(false);
  const [runnerInstance, setRunnerInstance] = createSignal<YarnRunner | null>(null);
  
  // 获取文件路径
  const {articlePath, rawSrc} = loadElementSrc(element);
  const yarnPaths = (rawSrc || '').split(',')
      .map((s: string) => resolvePath(articlePath, s.trim()))
      .filter(Boolean);
  
  // 加载 yarn 内容
  const [yarnContent] = createResource(() => yarnPaths, loadYarnFiles);
  
  // 创建 runner
  const createRunner = () => {
    const content = yarnContent();
    if (!content) return null;
    
    try {
      const ast = parseYarn(content);
      const program = compile(ast);
      
      return new YarnRunner(program, props);
    } catch (error) {
      console.error('Failed to initialize YarnRunner:', error);
      return null;
    }
  };
  
  function advance(index?: number){
    const runner = runnerInstance();
    if(!runner) return;
    if(runner.currentResult?.type !== 'options' && runner.currentResult?.isDialogueEnd) return;
    runner.advance(index);
    processRunnerOutput(runner);
  }
  
  createEffect(() => {
    if(!yarnContent()) return;
    setRunnerInstance(createRunner());
    processRunnerOutput(runnerInstance()!);
  });
  
  // 处理 runner 输出
  const processRunnerOutput = (runner: YarnRunner) => {
    const result = runner.currentResult;
    if (!result) return;
    
    if(result.type === 'options'){
      setCurrentOptions(result);
    }else{
      setCurrentOptions(null);
    }
    
    setDialogueHistory([...runner.history]);
  };
  
  // 重新开始
  const restart = () => {
    setDialogueHistory([]);
    setCurrentOptions(null);
    setIsEnded(false);
    setRunnerInstance(createRunner());
    processRunnerOutput(runnerInstance()!);
  };
  
  // 渲染对话历史项
  const renderEntry = (result: RuntimeResult) => {
    
    if (result.type === 'text') {
      const textResult = result as TextResult;
      return (
        <div class="dialogue-entry text-entry">
          <Show when={textResult.speaker}>
            <span class="speaker font-bold text-blue-600">{textResult.speaker}: </span>
          </Show>
          <span class="text">{textResult.text}</span>
        </div>
      );
    }
    
    if (result.type === 'command') {
      return (
        <div class="dialogue-entry command-entry text-gray-500 italic">
          [{result.command}]
        </div>
      );
    }
    
    return null;
  };
  
  return (
    <div class="yarn-spinner w-full max-w-2xl mx-auto shadow-sm relative">
      {/* 对话历史 */}
      <div class="dialogue-history p-4 h-64 overflow-y-auto bg-gray-50">
        <Show when={dialogueHistory().length === 0 && !yarnContent.loading}>
          <div class="text-gray-400 text-center py-8">点击重新开始开始对话</div>
        </Show>
        <Show when={yarnContent.loading}>
          <div class="text-gray-400 text-center py-8">加载对话中...</div>
        </Show>
        <For each={dialogueHistory()}>
          {renderEntry}
        </For>
      </div>

      {/* 当前选项 */}
      <Show when={currentOptions() && !isEnded()}>
        <div class="current-options p-4 border-t bg-white">
          <div class="options-list flex flex-col gap-2">
            <For each={currentOptions()?.options || []}>
              {(option, index) => (
                <button
                  onClick={() => advance(index())}
                  class="option-button text-left px-4 py-2 bg-blue-50 hover:bg-blue-100
                         rounded border border-blue-200 transition-colors cursor-pointer"
                >
                  → {option.text}
                </button>
              )}
            </For>
          </div>
        </div>
      </Show>

      {/* 浮动工具栏 */}
      <div class="toolbar absolute top-0 right-0 p-2 bg-gray-100 border-t border-l rounded-tl-lg shadow-sm flex gap-2">
        <button
          onClick={restart}
          class="restart-button px-3 py-1 text-sm bg-gray-200 hover:bg-gray-300
                 rounded transition-colors cursor-pointer"
          title="重新开始"
        >
          🔄 重新开始
        </button>
        <button
            onClick={() => advance()}
            class="advance-button px-3 py-1 text-sm bg-gray-200 hover:bg-gray-300
                 rounded transition-colors cursor-pointer"
            title="继续"
        >
          ⏩ 继续
        </button>
      </div>
    </div>
  );
});
