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

export interface YarnSpinnerProps extends RunnerOptions {
  startNode?: string;
  multipleFiles?: boolean;
}

interface DialogueEntry {
  id: number;
  result: RuntimeResult;
  selectedOptionIndex?: number;
}

// 缓存已加载的 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('md-yarn-spinner', { 
  startNode: undefined as string | undefined,
  multipleFiles: false 
}, (props, { element }) => {
  noShadowDOM();
  
  const [dialogueHistory, setDialogueHistory] = createSignal<DialogueEntry[]>([]);
  const [currentOptions, setCurrentOptions] = createSignal<OptionsResult | null>(null);
  const [isEnded, setIsEnded] = createSignal(false);
  const [entryIdCounter, setEntryIdCounter] = createSignal(0);
  const [runnerInstance, setRunnerInstance] = createSignal<YarnRunner | null>(null);
  
  // 获取文件路径
  const rawSrc = element?.textContent?.trim() || '';
  const articleEl = element?.closest('article[data-src]');
  const articlePath = articleEl?.getAttribute('data-src') || '';
  
  // 隐藏原始文本内容
  if (element) {
    element.textContent = '';
  }
  
  // 解析路径列表（支持多文件）
  const yarnPaths = createMemo(() => {
    const src = rawSrc;
    if (!src) return [];
    if (props.multipleFiles) {
      return src.split('\n').map((s: string) => s.trim()).filter(Boolean);
    }
    return [src];
  });
  
  // 解析相对路径
  const resolvedPaths = createMemo(() => {
    return yarnPaths().map((path: string) => {
      if (path.startsWith('/')) return path;
      if (path.startsWith('http://') || path.startsWith('https://')) return path;
      
      const baseParts = articlePath.split('/').filter(Boolean);
      if (baseParts.length > 0 && !articlePath.endsWith('/')) {
        baseParts.pop();
      }
      
      const relativeParts = path.split('/');
      for (const part of relativeParts) {
        if (part === '.' || part === '') continue;
        else if (part === '..') baseParts.pop();
        else baseParts.push(part);
      }
      
      return '/' + baseParts.join('/');
    });
  });
  
  // 加载 yarn 内容
  const [yarnContent] = createResource(
    () => resolvedPaths(),
    async (paths) => {
      if (paths.length === 0) return '';
      if (paths.length === 1) {
        return await loadYarnFile(paths[0]);
      }
      return await loadYarnFiles(paths);
    }
  );
  
  // 创建 runner
  const createRunner = (content: string, startNode?: string) => {
    if (!content) return null;
    
    try {
      const ast = parseYarn(content);
      const program = compile(ast);
      
      const runnerOptions: RunnerOptions = {
        startAt: startNode || 'Start',
        variables: (props as YarnSpinnerProps).variables,
        functions: (props as YarnSpinnerProps).functions,
        handleCommand: (props as YarnSpinnerProps).handleCommand,
        onStoryEnd: (props as YarnSpinnerProps).onStoryEnd,
      };
      
      return new YarnRunner(program, runnerOptions);
    } catch (error) {
      console.error('Failed to initialize YarnRunner:', error);
      return null;
    }
  };
  
  // 初始化 runner
  createEffect(() => {
    const content = yarnContent();
    if (content && !runnerInstance()) {
      const startNode = (props as YarnSpinnerProps).startNode;
      const runner = createRunner(content, startNode);
      if (runner) {
        setRunnerInstance(runner);
      }
    }
  });
  
  // 处理 runner 输出
  const processRunnerOutput = (runner: YarnRunner) => {
    const result = runner.currentResult;
    if (!result) return;
    
    const newEntry: DialogueEntry = {
      id: entryIdCounter(),
      result,
    };
    
    setDialogueHistory(prev => [...prev, newEntry]);
    setEntryIdCounter(prev => prev + 1);
    
    if (result.type === 'options') {
      setCurrentOptions(result as OptionsResult);
    } else if (result.type === 'text' && (result as TextResult).isDialogueEnd) {
      // 检查是否是对话结束
      const lastOptions = runner.history.slice().reverse().find(r => r.type === 'options') as OptionsResult | undefined;
      if (lastOptions && runner.currentResult?.type !== 'options') {
        // 之前有选项但没有选择，等待用户输入
        setCurrentOptions(lastOptions);
        return;
      }
    }
    
    // 检查故事是否结束
    if ((result as TextResult).isDialogueEnd && result.type !== 'options') {
      setIsEnded(true);
      setCurrentOptions(null);
    }
  };
  
  // 监听 runner 变化
  createEffect(() => {
    const runner = runnerInstance();
    if (runner && runner.currentResult) {
      processRunnerOutput(runner);
    }
  });
  
  // 选择选项
  const selectOption = (index: number) => {
    const runner = runnerInstance();
    if (!runner || !currentOptions()) return;
    
    // 更新历史记录，标记已选择的选项
    setDialogueHistory(prev => {
      const lastOptionsIndex = prev.slice().reverse().findIndex(e => e.result.type === 'options');
      if (lastOptionsIndex === -1) return prev;
      
      const actualIndex = prev.length - 1 - lastOptionsIndex;
      return prev.map((entry, i) => 
        i === actualIndex
          ? { ...entry, selectedOptionIndex: index }
          : entry
      );
    });
    
    setCurrentOptions(null);
    runner.advance(index);
    
    // 处理选择后的输出
    setTimeout(() => {
      processRunnerOutput(runner);
    }, 0);
  };
  
  // 重新开始
  const restart = () => {
    setDialogueHistory([]);
    setCurrentOptions(null);
    setIsEnded(false);
    setEntryIdCounter(0);
    
    // 重新创建 runner
    const content = yarnContent();
    if (!content) return;
    
    const runner = createRunner(content, (props as YarnSpinnerProps).startNode);
    if (runner) {
      setRunnerInstance(runner);
    }
  };
  
  // 渲染对话历史项
  const renderEntry = (entry: DialogueEntry) => {
    const result = entry.result;
    
    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>
      );
    }
    
    if (result.type === 'options') {
      const optionsResult = result as OptionsResult;
      return (
        <div class="dialogue-entry options-entry">
          <Show when={entry.selectedOptionIndex !== undefined}>
            <div class="selected-option text-gray-600">
              → {optionsResult.options[entry.selectedOptionIndex!].text}
            </div>
          </Show>
          <Show when={entry.selectedOptionIndex === undefined}>
            <div class="options-list flex flex-col gap-2">
              <For each={optionsResult.options}>
                {(option, index) => (
                  <button
                    onClick={() => selectOption(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>
          </Show>
        </div>
      );
    }
    
    return null;
  };
  
  return (
    <div class="yarn-spinner w-full max-w-2xl mx-auto border rounded-lg shadow-sm">
      {/* 对话历史 */}
      <div class="dialogue-history p-4 min-h-[200px] max-h-[60vh] 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()}>
          {entry => renderEntry(entry)}
        </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={() => selectOption(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 p-2 border-t bg-gray-100 flex justify-end 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>
      </div>
    </div>
  );
});
