/**
 * WorkflowView - Workflow execution interface for PicoAgents
 * Features: Workflow step visualization, input forms, execution monitoring
 */

import { useState, useCallback, useRef } from "react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
  Workflow,
  Play,
  CheckCircle,
  Clock,
  AlertCircle,
  ArrowRight,
  FileCode,
  StopCircle
} from "lucide-react";
import { apiClient } from "@/services/api";
import { WorkflowResultRenderer } from "./workflow-result-renderer";
import type {
  WorkflowInfo,
  StreamEvent,
  RunEntityRequest,
  WorkflowExecutionState
} from "@/types";

interface WorkflowViewProps {
  selectedWorkflow: WorkflowInfo;
  userId?: string;
  onDebugEvent: (event: StreamEvent) => void;
}

export function WorkflowView({
  selectedWorkflow,
  userId,
  onDebugEvent,
}: WorkflowViewProps) {
  const [inputData, setInputData] = useState<Record<string, any>>({});
  const [isExecuting, setIsExecuting] = useState(false);
  const [executionState, setExecutionState] = useState<WorkflowExecutionState>({
    status: "pending",
    steps_completed: [],
  });
  const [result, setResult] = useState<any>(null);
  const [error, setError] = useState<string | null>(null);
  const abortControllerRef = useRef<AbortController | null>(null);

  const isObjectLikeSchema = (property: any): boolean => {
    if (property?.type === "object" || property?.$ref) {
      return true;
    }
    if (Array.isArray(property?.anyOf)) {
      return property.anyOf.some(
        (variant: any) => variant?.type === "object" || variant?.$ref
      );
    }
    return false;
  };

  const getFieldPlaceholder = (key: string, property: any): string => {
    if (property?.description) {
      return property.description;
    }

    if (key === "task") {
      return "Example: Write a short article about solar energy benefits.";
    }
    if (key === "additional_context") {
      return '{"audience":"engineering leaders","tone":"concise","must_include":["cost","risks"]}';
    }
    if (key === "agent_context") {
      return '{"messages":[{"role":"user","content":"Continue the earlier draft.","source":"user"}],"metadata":{"resume_reason":"follow-up"}}';
    }
    if (isObjectLikeSchema(property)) {
      return `Enter ${key} as JSON`;
    }
    return `Enter ${key}`;
  };

  const getFieldHelpText = (key: string, property: any): string | null => {
    if (property?.description) {
      return property.description;
    }
    if (key === "additional_context") {
      return "Optional JSON object for audience, tone, constraints, or supporting notes.";
    }
    if (key === "agent_context") {
      return "Optional AgentContext JSON for resuming or seeding prior conversation history.";
    }
    return null;
  };

  const handleInputChange = (key: string, value: any) => {
    setInputData(prev => ({
      ...prev,
      [key]: value
    }));
  };

  const handleExecute = useCallback(async () => {
    setIsExecuting(true);
    setError(null);
    setResult(null);
    setExecutionState({
      status: "running",
      steps_completed: [],
    });

    // Create new AbortController for this request
    abortControllerRef.current = new AbortController();

    try {
      const schema = selectedWorkflow.input_schema;
      const properties = schema?.properties || {};
      const normalizedInputData = Object.fromEntries(
        Object.entries(inputData)
          .filter(([, value]) => value !== "" && value !== undefined && value !== null)
          .map(([key, value]) => {
            const property = (properties as Record<string, any>)[key];
            if (typeof value === "string" && isObjectLikeSchema(property)) {
              return [key, JSON.parse(value)];
            }
            return [key, value];
          })
      );

      const request: RunEntityRequest = {
        input_data: normalizedInputData,
        user_id: userId,
      };

      for await (const event of apiClient.streamEntityExecution(
        selectedWorkflow.id,
        request,
        abortControllerRef.current.signal
      )) {
        onDebugEvent(event);

        // Handle workflow events - using actual WorkflowRunner event types
        // The API client normalizes events: type = event_type, data = full WorkflowEvent
        const workflowEvent = event.data;
        const eventType = event.type; // API client already extracts event_type to type

        if (eventType === "workflow_started") {
          setExecutionState(prev => ({
            ...prev,
            status: "running",
          }));
        } else if (eventType === "step_started") {
          setExecutionState(prev => ({
            ...prev,
            current_step: workflowEvent?.step_id || "unknown",
          }));
        } else if (eventType === "step_completed") {
          setExecutionState(prev => ({
            ...prev,
            steps_completed: [...prev.steps_completed, workflowEvent?.step_id || "unknown"],
            current_step: undefined, // Clear current step when completed
          }));
        } else if (eventType === "step_failed") {
          setExecutionState(prev => ({
            ...prev,
            status: "failed",
            error: workflowEvent?.error || "Step execution failed",
          }));
          setError(workflowEvent?.error || "Step execution failed");
        } else if (eventType === "workflow_completed") {
          setExecutionState(prev => ({
            ...prev,
            status: "completed",
            current_step: undefined,
          }));
          // final_output is set by the backend from the terminal step's output_data
          setResult(workflowEvent?.final_output ?? null);
        } else if (eventType === "workflow_failed") {
          setExecutionState(prev => ({
            ...prev,
            status: "failed",
            error: workflowEvent?.error || "Workflow execution failed",
          }));
          setError(workflowEvent?.error || "Workflow execution failed");
        } else if (eventType === "workflow_cancelled") {
          setExecutionState(prev => ({
            ...prev,
            status: "failed",
            error: workflowEvent?.reason || "Workflow was cancelled",
          }));
          setError(workflowEvent?.reason || "Workflow was cancelled");
        }
      }
    } catch (err) {
      console.error("Workflow execution error:", err);

      // Check if this was an abort (user clicked stop)
      if (err instanceof Error && err.name === "AbortError") {
        setError("Cancelled by user");
        setExecutionState(prev => ({
          ...prev,
          status: "failed",
          error: "Cancelled by user",
        }));
      } else {
        setError(err instanceof Error ? err.message : "Execution failed");
        setExecutionState(prev => ({
          ...prev,
          status: "failed",
          error: err instanceof Error ? err.message : "Unknown error",
        }));
      }
    } finally {
      setIsExecuting(false);
      abortControllerRef.current = null;
    }
  }, [selectedWorkflow.id, inputData, onDebugEvent, userId]);

  const handleStop = useCallback(() => {
    if (abortControllerRef.current) {
      console.log("🛑 Stopping workflow execution");
      abortControllerRef.current.abort();
    }
  }, []);

  const getStepStatus = (stepId: string) => {
    if (executionState.steps_completed.includes(stepId)) {
      return "completed";
    } else if (executionState.current_step === stepId) {
      return "running";
    } else {
      return "pending";
    }
  };

  const getStatusIcon = (status: string) => {
    switch (status) {
      case "completed":
        return <CheckCircle className="h-4 w-4 text-green-600" />;
      case "running":
        return <Clock className="h-4 w-4 text-blue-600 animate-spin" />;
      case "failed":
        return <AlertCircle className="h-4 w-4 text-red-600" />;
      default:
        return <div className="h-4 w-4 rounded-full border-2 border-gray-300" />;
    }
  };

  const renderInputForm = () => {
    if (!selectedWorkflow.input_schema) {
      return (
        <Card>
          <CardContent className="p-4">
            <p className="text-sm text-muted-foreground">
              No input schema defined for this workflow.
            </p>
          </CardContent>
        </Card>
      );
    }

    const schema = selectedWorkflow.input_schema;
    const properties = schema.properties || {};

    return (
      <Card>
        <CardHeader>
          <CardTitle className="text-sm">Workflow Input</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          {Object.entries(properties).map(([key, prop]) => {
            const property = prop as any;
            return (
              <div key={key} className="space-y-2">
                <Label htmlFor={key} className="text-sm font-medium">
                  {key}
                  {schema.required?.includes(key) && (
                    <span className="text-red-500 ml-1">*</span>
                  )}
                </Label>
                {isObjectLikeSchema(property) ? (
                  <Textarea
                    id={key}
                    placeholder={getFieldPlaceholder(key, property)}
                    value={inputData[key] || ""}
                    onChange={(e) => handleInputChange(key, e.target.value)}
                    disabled={isExecuting}
                    className="min-h-[120px] font-mono text-xs"
                  />
                ) : (
                  <Input
                    id={key}
                    type={property.type === "number" ? "number" : "text"}
                    placeholder={getFieldPlaceholder(key, property)}
                    value={inputData[key] || ""}
                    onChange={(e) => handleInputChange(key, e.target.value)}
                    disabled={isExecuting}
                  />
                )}
                {getFieldHelpText(key, property) && (
                  <p className="text-xs text-muted-foreground">
                    {getFieldHelpText(key, property)}
                  </p>
                )}
              </div>
            );
          })}
        </CardContent>
      </Card>
    );
  };

  return (
    <div className="flex flex-col h-full">
      {/* Workflow Info Header */}
      <div className="border-b p-4 space-y-4">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-3">
            <Workflow className="h-6 w-6 text-green-600" />
            <div>
              <h2 className="text-lg font-semibold">
                {selectedWorkflow.name || selectedWorkflow.id}
              </h2>
              {selectedWorkflow.description && (
                <p className="text-sm text-muted-foreground">
                  {selectedWorkflow.description}
                </p>
              )}
            </div>
          </div>
          <Badge variant="outline" className="gap-1">
            <FileCode className="h-3 w-3" />
            {selectedWorkflow.steps.length} steps
          </Badge>
        </div>

        {/* Workflow Steps */}
        <div className="space-y-2">
          <div className="flex items-center gap-2 text-sm text-muted-foreground">
            <Workflow className="h-4 w-4" />
            <span>Workflow Steps</span>
          </div>
          <div className="flex items-center gap-2 flex-wrap">
            {selectedWorkflow.steps.map((stepId, index) => (
              <div key={stepId} className="flex items-center gap-2">
                <Badge
                  variant={
                    getStepStatus(stepId) === "completed"
                      ? "default"
                      : getStepStatus(stepId) === "running"
                      ? "secondary"
                      : "outline"
                  }
                  className="gap-1"
                >
                  {getStatusIcon(getStepStatus(stepId))}
                  {stepId}
                </Badge>
                {index < selectedWorkflow.steps.length - 1 && (
                  <ArrowRight className="h-3 w-3 text-muted-foreground" />
                )}
              </div>
            ))}
          </div>
        </div>

        {/* Start Step */}
        {selectedWorkflow.start_step && (
          <div className="text-sm">
            <span className="text-muted-foreground">Entry point: </span>
            <Badge variant="outline">{selectedWorkflow.start_step}</Badge>
          </div>
        )}
      </div>

      <div className="flex-1 p-4 space-y-4 overflow-auto">
        {/* Input Form */}
        {renderInputForm()}

        {/* Execution Controls */}
        <Card>
          <CardContent className="p-4">
            <div className="flex items-center justify-between">
              <div>
                <h3 className="font-medium">Execute Workflow</h3>
                <p className="text-sm text-muted-foreground">
                  Run the workflow with the provided input
                </p>
              </div>
              <div className="flex gap-2">
                {isExecuting && (
                  <Button
                    variant="destructive"
                    onClick={handleStop}
                    className="gap-2"
                  >
                    <StopCircle className="h-4 w-4" />
                    Stop
                  </Button>
                )}
                <Button
                  onClick={handleExecute}
                  disabled={isExecuting}
                  className="gap-2"
                >
                  {isExecuting ? (
                    <Clock className="h-4 w-4 animate-spin" />
                  ) : (
                    <Play className="h-4 w-4" />
                  )}
                  {isExecuting ? "Executing..." : "Execute"}
                </Button>
              </div>
            </div>
          </CardContent>
        </Card>

        {/* Execution Status */}
        {executionState.status !== "pending" && (
          <Card>
            <CardHeader>
              <CardTitle className="text-sm flex items-center gap-2">
                {getStatusIcon(executionState.status)}
                Execution Status
              </CardTitle>
            </CardHeader>
            <CardContent className="space-y-2">
              <div className="flex items-center gap-2">
                <span className="text-sm font-medium">Status:</span>
                <Badge
                  variant={
                    executionState.status === "completed"
                      ? "default"
                      : executionState.status === "running"
                      ? "secondary"
                      : "destructive"
                  }
                >
                  {executionState.status}
                </Badge>
              </div>
              <div className="text-sm">
                <span className="font-medium">Steps completed:</span>{" "}
                {executionState.steps_completed.length} of {selectedWorkflow.steps.length}
              </div>
              {executionState.current_step && (
                <div className="text-sm">
                  <span className="font-medium">Current step:</span>{" "}
                  <Badge variant="outline">{executionState.current_step}</Badge>
                </div>
              )}
            </CardContent>
          </Card>
        )}

        {/* Results */}
        {result && (
          <div className="space-y-1">
            <div className="flex items-center gap-2 px-1 pb-1">
              <CheckCircle className="h-4 w-4 text-green-600" />
              <span className="text-sm font-medium">Execution Result</span>
            </div>
            <WorkflowResultRenderer result={result} />
          </div>
        )}

        {/* Error */}
        {error && (
          <Card className="border-destructive">
            <CardHeader>
              <CardTitle className="text-sm flex items-center gap-2 text-destructive">
                <AlertCircle className="h-4 w-4" />
                Execution Error
              </CardTitle>
            </CardHeader>
            <CardContent>
              <p className="text-sm text-destructive">{error}</p>
            </CardContent>
          </Card>
        )}
      </div>
    </div>
  );
}
