import React, { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useZino } from "./provider";
import type { FormField } from "./types";

export interface DynamicFormProps {
  /** Workflow definition ID. */
  workflowId: string;
  /** Activity UID — the form schema is fetched for this activity. */
  activityId: string;
  /** Instance ID — omit for INIT activities (start workflow). */
  instanceId?: string;
  /** Called after successful submission with the result. */
  onSuccess?: (result: unknown) => void;
  /** Called on submission error. */
  onError?: (error: unknown) => void;
  /** Optional CSS class for the form wrapper. */
  className?: string;
}

/**
 * Renders a dynamic form based on the activity's form schema.
 *
 * Fetches the form config from the core-service, renders fields by type,
 * and submits via performActivity or startWorkflow.
 *
 * ```tsx
 * <DynamicForm
 *   workflowId={WORKFLOW_ID}
 *   activityId={ACTIVITY_IDS.ASSIGN_TICKET}
 *   instanceId={instanceId}
 *   onSuccess={() => { closeModal(); }}
 * />
 * ```
 */
export function DynamicForm({
  workflowId,
  activityId,
  instanceId,
  onSuccess,
  onError,
  className,
}: DynamicFormProps) {
  const { workflows } = useZino();
  const queryClient = useQueryClient();
  const [formData, setFormData] = useState<Record<string, string>>({});

  // Fetch form schema
  const { data: form, isLoading: formLoading, error: formError } = useQuery({
    queryKey: ["form", workflowId, activityId, instanceId],
    queryFn: () => workflows.getForm(workflowId, activityId, "desktop", instanceId),
  });

  // Submit mutation
  const submit = useMutation({
    mutationFn: async (data: Record<string, string>) => {
      if (instanceId) {
        return workflows.performActivity(workflowId, instanceId, activityId, data);
      } else {
        return workflows.startWorkflow(workflowId, activityId, data);
      }
    },
    onSuccess: (result) => {
      queryClient.invalidateQueries({ queryKey: ["recordview"] });
      queryClient.invalidateQueries({ queryKey: ["instance"] });
      queryClient.invalidateQueries({ queryKey: ["detailview"] });
      queryClient.invalidateQueries({ queryKey: ["audit"] });
      onSuccess?.(result);
    },
    onError: (err) => {
      onError?.(err);
    },
  });

  const handleChange = (fieldId: string, value: string) => {
    setFormData((prev) => ({ ...prev, [fieldId]: value }));
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // Map form field IDs to their mapped_activity_field_id
    const mapped: Record<string, string> = {};
    for (const field of form?.form_json?.fields ?? []) {
      const key = field.mapped_activity_field_id || field.id;
      mapped[key] = formData[field.id] ?? "";
    }
    submit.mutate(mapped);
  };

  if (formLoading) {
    return <div className="flex justify-center py-8"><div className="animate-spin h-6 w-6 border-2 border-blue-500 border-t-transparent rounded-full" /></div>;
  }

  if (formError) {
    return <div className="text-red-600 text-sm py-4">Failed to load form: {(formError as any)?.message ?? "Unknown error"}</div>;
  }

  const fields: FormField[] = form?.form_json?.fields ?? [];

  return (
    <form onSubmit={handleSubmit} className={className}>
      {form?.form_json?.title && (
        <h3 className="text-lg font-semibold mb-4">{form.form_json.title}</h3>
      )}

      <div className="space-y-4">
        {fields.map((field) => (
          <div key={field.id}>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              {field.label}
            </label>
            {renderField(field, formData[field.id] ?? "", (v) => handleChange(field.id, v))}
          </div>
        ))}
      </div>

      {submit.error && (
        <div className="mt-3 text-sm text-red-600">
          {(submit.error as any)?.message ?? "Submission failed"}
        </div>
      )}

      <button
        type="submit"
        disabled={submit.isPending}
        className="mt-6 w-full bg-blue-600 hover:bg-blue-700 disabled:opacity-50 text-white font-medium py-2.5 px-4 rounded-lg transition-colors"
      >
        {submit.isPending ? "Submitting..." : "Submit"}
      </button>
    </form>
  );
}

function renderField(
  field: FormField,
  value: string,
  onChange: (value: string) => void,
) {
  const baseClass =
    "w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent";

  switch (field.type) {
    case "paragraph":
      return (
        <textarea
          value={value}
          onChange={(e) => onChange(e.target.value)}
          rows={4}
          className={baseClass}
          placeholder={field.label}
        />
      );
    case "number":
      return (
        <input
          type="number"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          className={baseClass}
          placeholder={field.label}
        />
      );
    case "text":
    default:
      return (
        <input
          type="text"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          className={baseClass}
          placeholder={field.label}
        />
      );
  }
}
