import React from "react";
import { FileSearch, FileDiff, CheckCircle, AlertTriangle, CircleDashed } from "lucide-react";
import { ToolViewProps } from "./types";
import { extractFilePath, extractStrReplaceContent, formatTimestamp, getToolTitle } from "./utils";
import { GenericToolView } from "./GenericToolView";
import { cn } from "@/lib/utils";

export function StrReplaceToolView({ 
  name = "str-replace",
  assistantContent, 
  toolContent,
  assistantTimestamp,
  toolTimestamp,
  isSuccess = true,
  isStreaming = false
}: ToolViewProps) {
  const filePath = extractFilePath(assistantContent);
  const { oldStr, newStr } = extractStrReplaceContent(assistantContent);
  const toolTitle = getToolTitle(name);
  
  if (!oldStr || !newStr) {
    return (
      <GenericToolView
        name={name}
        assistantContent={assistantContent}
        toolContent={toolContent}
        assistantTimestamp={assistantTimestamp}
        toolTimestamp={toolTimestamp}
        isSuccess={isSuccess}
        isStreaming={isStreaming}
      />
    );
  }
  
  // Perform a character-level diff to identify changes
  const generateDiff = (oldText: string, newText: string) => {
    const i = 0;
    const j = 0;
    
    // Find common prefix length
    let prefixLength = 0;
    while (prefixLength < oldText.length && prefixLength < newText.length && 
          oldText[prefixLength] === newText[prefixLength]) {
      prefixLength++;
    }
    
    // Find common suffix length
    let oldSuffixStart = oldText.length;
    let newSuffixStart = newText.length;
    while (oldSuffixStart > prefixLength && newSuffixStart > prefixLength &&
          oldText[oldSuffixStart - 1] === newText[newSuffixStart - 1]) {
      oldSuffixStart--;
      newSuffixStart--;
    }
    
    // Generate unified diff parts
    const parts = [];
    
    // Add common prefix
    if (prefixLength > 0) {
      parts.push({ text: oldText.substring(0, prefixLength), type: 'unchanged' });
    }
    
    // Add the changed middle parts
    if (oldSuffixStart > prefixLength) {
      parts.push({ text: oldText.substring(prefixLength, oldSuffixStart), type: 'removed' });
    }
    if (newSuffixStart > prefixLength) {
      parts.push({ text: newText.substring(prefixLength, newSuffixStart), type: 'added' });
    }
    
    // Add common suffix
    if (oldSuffixStart < oldText.length) {
      parts.push({ text: oldText.substring(oldSuffixStart), type: 'unchanged' });
    }
    
    return parts;
  };
  
  const diffParts = generateDiff(oldStr, newStr);
  
  return (
    <div className="flex flex-col h-full">
      <div className="flex-1 p-4 overflow-auto">
        <div className="border border-zinc-200 dark:border-zinc-800 rounded-md overflow-hidden h-full flex flex-col">
          <div className="flex items-center p-2 bg-zinc-100 dark:bg-zinc-900 justify-between border-b border-zinc-200 dark:border-zinc-800">
            <div className="flex items-center">
              <FileDiff className="h-4 w-4 mr-2 text-zinc-600 dark:text-zinc-400" />
              <span className="text-xs font-medium text-zinc-700 dark:text-zinc-300">String Replacement</span>
            </div>
          </div>
          
          <div className="px-3 py-2 border-b border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900 flex items-center">
            <code className="text-xs font-mono text-zinc-700 dark:text-zinc-300">{filePath || 'Unknown file'}</code>
          </div>
          
          {isStreaming ? (
            <div className="flex-1 bg-white dark:bg-zinc-950 flex items-center justify-center">
              <div className="text-center p-6">
                <CircleDashed className="h-8 w-8 mx-auto mb-3 text-blue-500 animate-spin" />
                <p className="text-sm font-medium text-zinc-700 dark:text-zinc-300">Processing string replacement...</p>
                {filePath && (
                  <p className="text-xs mt-1 text-zinc-500 dark:text-zinc-400 font-mono">{filePath}</p>
                )}
              </div>
            </div>
          ) : (
            <div className="p-3 bg-white dark:bg-zinc-950 font-mono text-sm flex-1">
              {diffParts.map((part, i) => (
                <span 
                  key={i} 
                  className={cn(
                    part.type === 'removed' ? 'bg-red-50 text-red-700 dark:bg-red-900/20 dark:text-red-400 line-through mx-0.5' : 
                    part.type === 'added' ? 'bg-emerald-50 text-emerald-700 dark:bg-emerald-900/20 dark:text-emerald-400 mx-0.5' : 
                    'text-zinc-700 dark:text-zinc-300'
                  )}
                >
                  {part.text}
                </span>
              ))}
            </div>
          )}
        </div>
      </div>
      
      {/* Footer */}
      <div className="p-4 border-t border-zinc-200 dark:border-zinc-800">
        <div className="flex items-center justify-between text-xs text-zinc-500 dark:text-zinc-400">
          {!isStreaming && (
            <div className="flex items-center gap-2">
              {isSuccess ? (
                <CheckCircle className="h-3.5 w-3.5 text-emerald-500" />
              ) : (
                <AlertTriangle className="h-3.5 w-3.5 text-red-500" />
              )}
              <span>
                {isSuccess ? 'Replacement applied successfully' : 'Replacement failed'}
              </span>
            </div>
          )}
          
          {isStreaming && (
            <div className="flex items-center gap-2">
              <CircleDashed className="h-3.5 w-3.5 text-blue-500 animate-spin" />
              <span>Processing string replacement...</span>
            </div>
          )}
          
          <div className="text-xs">
            {toolTimestamp && !isStreaming 
              ? formatTimestamp(toolTimestamp) 
              : assistantTimestamp 
                ? formatTimestamp(assistantTimestamp)
                : ''}
          </div>
        </div>
      </div>
    </div>
  );
} 