/**
 * PipelinesPanel - Pipeline Discovery and Execution UI
 *
 * Displays available Pipelines (DSL-based workflows) with
 * category filtering, search, and execution capabilities.
 *
 * Pipelines orchestrate Skills and Hands to accomplish complex tasks.
 */

import { useState, useEffect } from 'react';
import {
  Play,
  RefreshCw,
  Search,
  Loader2,
  XCircle,
  Package,
  Filter,
  X,
} from 'lucide-react';
import {
  PipelineClient,
  PipelineInfo,
  PipelineRunResponse,
  usePipelines,
  validateInputs,
  getDefaultForType,
  formatInputType,
} from '../lib/pipeline-client';
import { useToast } from './ui/Toast';
import { PresentationContainer } from './presentation';

// === Category Badge Component ===

const CATEGORY_CONFIG: Record<string, { label: string; className: string }> = {
  education: { label: '教育', className: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400' },
  marketing: { label: '营销', className: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400' },
  legal: { label: '法律', className: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400' },
  productivity: { label: '生产力', className: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400' },
  research: { label: '研究', className: 'bg-cyan-100 text-cyan-700 dark:bg-cyan-900/30 dark:text-cyan-400' },
  sales: { label: '销售', className: 'bg-rose-100 text-rose-700 dark:bg-rose-900/30 dark:text-rose-400' },
  hr: { label: '人力', className: 'bg-teal-100 text-teal-700 dark:bg-teal-900/30 dark:text-teal-400' },
  finance: { label: '财务', className: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400' },
  default: { label: '其他', className: 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-400' },
};


function CategoryBadge({ category }: { category: string }) {
  const config = CATEGORY_CONFIG[category] || CATEGORY_CONFIG.default;
  return (
    <span className={`px-2 py-0.5 rounded text-xs font-medium ${config.className}`}>
      {config.label}
    </span>
  );
}

// === Pipeline Card Component ===

interface PipelineCardProps {
  pipeline: PipelineInfo;
  onRun: (pipeline: PipelineInfo) => void;
}

function PipelineCard({ pipeline, onRun }: PipelineCardProps) {
  return (
    <div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4 hover:shadow-md transition-shadow">
      <div className="flex items-start justify-between mb-3">
        <div className="flex items-center gap-3">
          <span className="text-2xl">{pipeline.icon}</span>
          <div>
            <h3 className="font-medium text-gray-900 dark:text-white">
              {pipeline.displayName}
            </h3>
            <p className="text-sm text-gray-500 dark:text-gray-400">
              {pipeline.id} · v{pipeline.version}
            </p>
          </div>
        </div>
        <CategoryBadge category={pipeline.category} />
      </div>

      <p className="text-sm text-gray-600 dark:text-gray-300 mb-3 line-clamp-2">
        {pipeline.description}
      </p>

      {pipeline.tags.length > 0 && (
        <div className="flex flex-wrap gap-1 mb-3">
          {pipeline.tags.slice(0, 3).map((tag) => (
            <span
              key={tag}
              className="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-700 rounded text-xs text-gray-600 dark:text-gray-300"
            >
              {tag}
            </span>
          ))}
          {pipeline.tags.length > 3 && (
            <span className="px-1.5 py-0.5 text-xs text-gray-400">
              +{pipeline.tags.length - 3}
            </span>
          )}
        </div>
      )}

      <div className="flex items-center justify-between pt-2 border-t border-gray-100 dark:border-gray-700">
        <span className="text-xs text-gray-400">
          {pipeline.inputs.length} 个输入参数
        </span>
        <button
          onClick={() => onRun(pipeline)}
          className="flex items-center gap-1.5 px-3 py-1.5 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-md transition-colors"
        >
          <Play className="w-4 h-4" />
          运行
        </button>
      </div>
    </div>
  );
}

// === Pipeline Result Modal ===

interface ResultModalProps {
  result: PipelineRunResponse;
  pipeline: PipelineInfo;
  onClose: () => void;
}

function ResultModal({ result, pipeline, onClose }: ResultModalProps) {
  return (
    <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
      <div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-[90vw] max-w-4xl h-[85vh] flex flex-col mx-4">
        {/* Header */}
        <div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
          <div className="flex items-center gap-3">
            <span className="text-2xl">{pipeline.icon}</span>
            <div>
              <h2 className="text-lg font-semibold text-gray-900 dark:text-white">
                {pipeline.displayName} - 执行结果
              </h2>
              <p className="text-sm text-gray-500 dark:text-gray-400">
                状态: {result.status === 'completed' ? '已完成' : '失败'}
              </p>
            </div>
          </div>
          <button
            onClick={onClose}
            className="p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
          >
            <X className="w-5 h-5 text-gray-500" />
          </button>
        </div>

        {/* Content */}
        <div className="flex-1 overflow-hidden">
          {result.outputs ? (
            <PresentationContainer
              data={result.outputs}
              pipelineId={pipeline.id}
              supportedTypes={['document', 'chart', 'quiz', 'slideshow']}
            />
          ) : result.error ? (
            <div className="p-6 text-center text-red-500">
              <XCircle className="w-8 h-8 mx-auto mb-2" />
              <p>{result.error}</p>
            </div>
          ) : (
            <div className="p-6 text-center text-gray-500">
              <Package className="w-8 h-8 mx-auto mb-2" />
              <p>无输出结果</p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// === Pipeline Run Modal ===

interface RunModalProps {
  pipeline: PipelineInfo;
  onClose: () => void;
  onComplete: (result: PipelineRunResponse) => void;
}

function RunModal({ pipeline, onClose, onComplete }: RunModalProps) {
  const [values, setValues] = useState<Record<string, unknown>>(() => {
    const defaults: Record<string, unknown> = {};
    pipeline.inputs.forEach((input) => {
      defaults[input.name] = input.default ?? getDefaultForType(input.inputType);
    });
    return defaults;
  });
  const [errors, setErrors] = useState<string[]>([]);
  const [running, setRunning] = useState(false);
  const [progress, setProgress] = useState<PipelineRunResponse | null>(null);

  const handleInputChange = (name: string, value: unknown) => {
    setValues((prev) => ({ ...prev, [name]: value }));
    setErrors([]);
  };

  const handleRun = async () => {
    // Validate inputs
    const validation = validateInputs(pipeline.inputs, values);
    if (!validation.valid) {
      setErrors(validation.errors);
      return;
    }

    setRunning(true);
    setProgress(null);

    try {
      const result = await PipelineClient.runAndWait(
        { pipelineId: pipeline.id, inputs: values },
        (p) => setProgress(p)
      );

      if (result.status === 'completed') {
        onComplete(result);
      } else if (result.error) {
        setErrors([result.error]);
      }
    } catch (err) {
      setErrors([err instanceof Error ? err.message : String(err)]);
    } finally {
      setRunning(false);
    }
  };

  const renderInput = (input: typeof pipeline.inputs[0]) => {
    const value = values[input.name];

    switch (input.inputType) {
      case 'string':
      case 'text':
        return input.inputType === 'text' ? (
          <textarea
            value={(value as string) || ''}
            onChange={(e) => handleInputChange(input.name, e.target.value)}
            placeholder={input.placeholder}
            rows={3}
            className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
          />
        ) : (
          <input
            type="text"
            value={(value as string) || ''}
            onChange={(e) => handleInputChange(input.name, e.target.value)}
            placeholder={input.placeholder}
            className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
          />
        );

      case 'number':
        return (
          <input
            type="number"
            value={(value as number) ?? ''}
            onChange={(e) => handleInputChange(input.name, e.target.valueAsNumber || 0)}
            className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
          />
        );

      case 'boolean':
        return (
          <label className="flex items-center gap-2">
            <input
              type="checkbox"
              checked={(value as boolean) || false}
              onChange={(e) => handleInputChange(input.name, e.target.checked)}
              className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
            />
            <span className="text-sm text-gray-600 dark:text-gray-300">启用</span>
          </label>
        );

      case 'select':
        return (
          <select
            value={(value as string) || ''}
            onChange={(e) => handleInputChange(input.name, e.target.value)}
            className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
          >
            <option value="">请选择...</option>
            {input.options.map((opt) => (
              <option key={opt} value={opt}>
                {opt}
              </option>
            ))}
          </select>
        );

      case 'multi-select':
        return (
          <div className="space-y-2">
            {input.options.map((opt) => (
              <label key={opt} className="flex items-center gap-2">
                <input
                  type="checkbox"
                  checked={((value as string[]) || []).includes(opt)}
                  onChange={(e) => {
                    const current = (value as string[]) || [];
                    const updated = e.target.checked
                      ? [...current, opt]
                      : current.filter((v) => v !== opt);
                    handleInputChange(input.name, updated);
                  }}
                  className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
                />
                <span className="text-sm text-gray-600 dark:text-gray-300">{opt}</span>
              </label>
            ))}
          </div>
        );

      default:
        return (
          <input
            type="text"
            value={(value as string) || ''}
            onChange={(e) => handleInputChange(input.name, e.target.value)}
            placeholder={input.placeholder}
            className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
          />
        );
    }
  };

  return (
    <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
      <div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-y-auto">
        {/* Header */}
        <div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
          <div className="flex items-center gap-3">
            <span className="text-2xl">{pipeline.icon}</span>
            <div>
              <h2 className="text-lg font-semibold text-gray-900 dark:text-white">
                {pipeline.displayName}
              </h2>
              <p className="text-sm text-gray-500 dark:text-gray-400">
                {pipeline.description}
              </p>
            </div>
          </div>
          <button
            onClick={onClose}
            className="p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
          >
            <X className="w-5 h-5 text-gray-500" />
          </button>
        </div>

        {/* Form */}
        <div className="p-4 space-y-4">
          {pipeline.inputs.map((input) => (
            <div key={input.name}>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
                {input.label}
                {input.required && <span className="text-red-500 ml-1">*</span>}
                <span className="text-xs text-gray-400 ml-2">
                  ({formatInputType(input.inputType)})
                </span>
              </label>
              {renderInput(input)}
            </div>
          ))}

          {errors.length > 0 && (
            <div className="p-3 bg-red-50 dark:bg-red-900/20 rounded-md">
              {errors.map((error, i) => (
                <p key={i} className="text-sm text-red-600 dark:text-red-400">
                  {error}
                </p>
              ))}
            </div>
          )}

          {/* Progress */}
          {running && progress && (
            <div className="p-3 bg-blue-50 dark:bg-blue-900/20 rounded-md">
              <div className="flex items-center gap-2 mb-2">
                <Loader2 className="w-4 h-4 animate-spin text-blue-600" />
                <span className="text-sm font-medium text-blue-700 dark:text-blue-300">
                  {progress.message || '运行中...'}
                </span>
              </div>
              <div className="w-full bg-blue-200 dark:bg-blue-800 rounded-full h-2">
                <div
                  className="bg-blue-600 h-2 rounded-full transition-all"
                  style={{ width: `${progress.percentage}%` }}
                />
              </div>
            </div>
          )}
        </div>

        {/* Footer */}
        <div className="flex items-center justify-end gap-3 p-4 border-t border-gray-200 dark:border-gray-700">
          <button
            onClick={onClose}
            disabled={running}
            className="px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md disabled:opacity-50"
          >
            取消
          </button>
          <button
            onClick={handleRun}
            disabled={running}
            className="flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-md disabled:opacity-50"
          >
            {running ? (
              <>
                <Loader2 className="w-4 h-4 animate-spin" />
                运行中...
              </>
            ) : (
              <>
                <Play className="w-4 h-4" />
                开始运行
              </>
            )}
          </button>
        </div>
      </div>
    </div>
  );
}

// === Main Pipelines Panel ===

export function PipelinesPanel() {
  const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
  const [searchQuery, setSearchQuery] = useState('');
  const [selectedPipeline, setSelectedPipeline] = useState<PipelineInfo | null>(null);
  const [runResult, setRunResult] = useState<{ result: PipelineRunResponse; pipeline: PipelineInfo } | null>(null);
  const { toast } = useToast();

  // Subscribe to pipeline-complete push events (for background completion)
  useEffect(() => {
    let unlisten: (() => void) | undefined;
    PipelineClient.onComplete((event) => {
      // Only show notification if we're not already tracking this run
      // (the polling path handles in-flight runs via handleRunComplete)
      if (selectedPipeline?.id === event.pipelineId) return;
      if (event.status === 'completed') {
        toast(`Pipeline "${event.pipelineId}" 后台执行完成`, 'success');
      } else if (event.status === 'failed') {
        toast(`Pipeline "${event.pipelineId}" 后台执行失败: ${event.error ?? ''}`, 'error');
      }
    }).then((fn) => { unlisten = fn; });
    return () => { unlisten?.(); };
  }, [selectedPipeline, toast]);

  // Fetch all pipelines without filtering
  const { pipelines, loading, error, refresh } = usePipelines({});

  // Get unique categories from ALL pipelines (not filtered)
  const categories = Array.from(
    new Set(pipelines.map((p) => p.category).filter(Boolean))
  );

  // Filter pipelines by selected category and search
  const filteredPipelines = pipelines.filter((p) => {
    // Category filter
    if (selectedCategory && p.category !== selectedCategory) {
      return false;
    }
    // Search filter
    if (searchQuery) {
      const query = searchQuery.toLowerCase();
      return (
        p.displayName.toLowerCase().includes(query) ||
        p.description.toLowerCase().includes(query) ||
        p.tags.some((t) => t.toLowerCase().includes(query))
      );
    }
    return true;
  });


  const handleRunPipeline = (pipeline: PipelineInfo) => {
    setSelectedPipeline(pipeline);
  };

  const handleRunComplete = (result: PipelineRunResponse) => {
    setSelectedPipeline(null);
    if (result.status === 'completed') {
      toast('Pipeline 执行完成', 'success');
      setRunResult({ result, pipeline: selectedPipeline! });
    } else {
      toast(`Pipeline 执行失败: ${result.error}`, 'error');
    }
  };

  return (
    <div className="h-full flex flex-col">
      {/* Header */}
      <div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
        <div className="flex items-center gap-2">
          <Package className="w-5 h-5 text-gray-500" />
          <h2 className="text-lg font-semibold text-gray-900 dark:text-white">
            Pipelines
          </h2>
          <span className="px-2 py-0.5 bg-gray-100 dark:bg-gray-700 rounded-full text-xs text-gray-600 dark:text-gray-300">
            {pipelines.length}
          </span>
        </div>
        <button
          onClick={refresh}
          disabled={loading}
          className="flex items-center gap-1.5 px-3 py-1.5 text-sm text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md"
        >
          <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />
          刷新
        </button>
      </div>

      {/* Filters */}
      <div className="p-4 border-b border-gray-200 dark:border-gray-700 space-y-3">
        {/* Search */}
        <div className="relative">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
          <input
            type="text"
            placeholder="搜索 Pipelines..."
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            className="w-full pl-9 pr-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
          />
        </div>

        {/* Category filters */}
        {categories.length > 0 && (
          <div className="flex items-center gap-2 flex-wrap">
            <Filter className="w-4 h-4 text-gray-400" />
            <button
              onClick={() => setSelectedCategory(null)}
              className={`px-2 py-1 text-xs rounded-md transition-colors ${
                selectedCategory === null
                  ? 'bg-blue-600 text-white'
                  : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
              }`}
            >
              全部
            </button>
            {categories.map((cat) => (
              <button
                key={cat}
                onClick={() => setSelectedCategory(cat)}
                className={`px-2 py-1 text-xs rounded-md transition-colors ${
                  selectedCategory === cat
                    ? 'bg-blue-600 text-white'
                    : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
                }`}
              >
                {CATEGORY_CONFIG[cat]?.label || cat}
              </button>
            ))}
          </div>
        )}

      </div>

      {/* Content */}
      <div className="flex-1 overflow-y-auto p-4">
        {loading ? (
          <div className="flex items-center justify-center h-32">
            <Loader2 className="w-6 h-6 animate-spin text-gray-400" />
          </div>
        ) : error ? (
          <div className="text-center py-8 text-red-500">
            <XCircle className="w-8 h-8 mx-auto mb-2" />
            <p>{error}</p>
          </div>
        ) : filteredPipelines.length === 0 ? (
          <div className="text-center py-8 text-gray-500">
            <Package className="w-8 h-8 mx-auto mb-2" />
            <p>没有找到 Pipeline</p>
            {searchQuery && <p className="text-sm mt-1">尝试修改搜索条件</p>}
          </div>
        ) : (
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            {filteredPipelines.map((pipeline) => (
              <PipelineCard
                key={pipeline.id}
                pipeline={pipeline}
                onRun={handleRunPipeline}
              />
            ))}
          </div>
        )}
      </div>

      {/* Run Modal */}
      {selectedPipeline && (
        <RunModal
          pipeline={selectedPipeline}
          onClose={() => setSelectedPipeline(null)}
          onComplete={handleRunComplete}
        />
      )}

      {/* Result Modal */}
      {runResult && (
        <ResultModal
          result={runResult.result}
          pipeline={runResult.pipeline}
          onClose={() => setRunResult(null)}
        />
      )}
    </div>
  );
}

export default PipelinesPanel;
