import { useEffect, useState } from "react";
import { addScene, type Project, type Scene } from "../api/client";
import { formatAiEditCreditsDisplay } from "../lib/formatAiEditCredits";

/** Adding a scene costs this many AI-edit credits (mirrors the backend). */
export const ADD_SCENE_CREDIT_COST = 5;

export interface AddSceneModalProps {
  open: boolean;
  onClose: () => void;
  project: Project;
  /** Total AI-edit budget available (allowance + purchased pool). */
  creditsRemaining: number;
  /**
   * Whether the owner has enough AI-edit budget for one add-scene action.
   */
  canAfford: boolean;
  /**
   * True when the viewer is a collaborator on a shared project (spending the
   * OWNER's credit pool). A collaborator can't fix an exhausted pool by upgrading
   * their own plan.
   */
  isCollaborator?: boolean;
  /** The scene the new one will be inserted AFTER; null = append at the end. */
  anchorScene?: Scene | null;
  /** Called after the add-scene job is enqueued (parent starts polling). */
  onAdded: (position?: number) => void;
  /** Navigate to the billing page from the inline "Upgrade now" link (free viewers). */
  onUpgradeNow: () => void;
  /** Surface an API failure (e.g. the 403 credit / 409 busy error) in the global "Oops" modal. */
  onError: (err: unknown) => void;
}

/**
 * Modal to generate and insert a new AI scene. The user describes the scene; it's
 * inserted right after `anchorScene` (or appended when none). On submit the backend
 * ENQUEUES a background generation job and this closes immediately — the parent shows
 * a placeholder row and polls for completion.
 */
export default function AddSceneModal({
  open,
  onClose,
  project,
  creditsRemaining,
  canAfford,
  isCollaborator = false,
  anchorScene,
  onAdded,
  onError,
  onUpgradeNow,
}: AddSceneModalProps) {
  const [prompt, setPrompt] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Insert position: right after the anchor row, else append (undefined).
  const insertPosition = anchorScene ? anchorScene.order + 1 : undefined;

  // Reset the form whenever the modal (re)opens.
  useEffect(() => {
    if (open) {
      setPrompt("");
      setError(null);
      setLoading(false);
    }
  }, [open]);

  if (!open) return null;

  const handleClose = () => {
    if (loading) return;
    onClose();
  };

  const handleSubmit = async () => {
    const trimmed = prompt.trim();
    if (!trimmed) {
      setError("Please describe the scene you want to add.");
      return;
    }
    if (!canAfford) return;
    setLoading(true);
    setError(null);
    try {
      await addScene(project.id, trimmed, insertPosition);
      // Job enqueued — hand the target position to the parent (for the placeholder)
      // and close. Generation continues in the background.
      onAdded(insertPosition);
      onClose();
    } catch (err: unknown) {
      // Surface API failures (403 credits / 409 busy) in the global "Oops" modal.
      // Close first so the error modal isn't hidden behind this dialog.
      onClose();
      onError(err);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="fixed inset-0 z-[105] flex items-center justify-center p-4">
      <div
        className="absolute inset-0 bg-black/50 backdrop-blur-sm"
        onClick={handleClose}
        aria-hidden
      />
      <div
        className="relative bg-white rounded-2xl shadow-2xl max-w-md w-full flex flex-col overflow-hidden"
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-labelledby="add-scene-title"
      >
        <div className="p-4 border-b border-gray-200 flex-shrink-0">
          <h3 id="add-scene-title" className="text-lg font-semibold text-gray-900">
            Add a scene
          </h3>
          <p className="text-xs text-gray-500 mt-1">
            Describe the scene — it's generated from your prompt and the rest of the video.
          </p>
          <p className="text-xs text-gray-400 mt-1">
            Costs{" "}
            <span className="font-medium text-gray-600">
              {ADD_SCENE_CREDIT_COST} AI edit credits
            </span>
            {isCollaborator ? (
              <>
                {" "}
                from the project owner&apos;s balance (
                {formatAiEditCreditsDisplay(creditsRemaining)} remaining).
              </>
            ) : (
              <>
                {" "}
                · {formatAiEditCreditsDisplay(creditsRemaining)} remaining
                {!canAfford && (
                  <>
                    {" "}
                    ·{" "}
                    <button
                      type="button"
                      onClick={onUpgradeNow}
                      className="text-purple-600 hover:text-purple-700 underline font-medium"
                    >
                      Upgrade for more
                    </button>
                  </>
                )}
              </>
            )}
          </p>
        </div>

        <div className="p-6 flex flex-col gap-4">
          {error && (
            <p className="w-full text-xs text-red-600 bg-red-50 border border-red-200 rounded-lg px-3 py-2">
              {error}
            </p>
          )}

          <div>
            <label htmlFor="add-scene-prompt" className="block text-xs font-medium text-gray-700 mb-1.5">
              What should this scene be about?
            </label>
            <textarea
              id="add-scene-prompt"
              value={prompt}
              onChange={(e) => setPrompt(e.target.value)}
              rows={4}
              autoFocus
              placeholder="e.g. A summary of the key takeaways with an upbeat closing line."
              className="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 resize-none"
            />
          </div>

          {/* Position is auto-determined from where the user clicked "Add scene". */}
          <p className="text-xs text-gray-500">
            {anchorScene
              ? <>The new scene will be added below scene {anchorScene.order}.</>
              : <>The new scene will be added at the end.</>}
          </p>

          {!canAfford && (
            <div className="rounded-lg bg-red-50 border border-red-200 px-3 py-2.5">
              {isCollaborator ? (
                <p className="text-xs font-semibold text-red-700">
                  The project owner is out of AI edit credits — ask them to upgrade or buy more.
                </p>
              ) : (
                <p className="text-xs font-semibold text-red-700">
                  You&apos;re out of AI edit credits — upgrade or buy a video for +20 credits.
                </p>
              )}
            </div>
          )}
        </div>

        <div className="p-4 border-t border-gray-200 flex items-center justify-end gap-2">
          <button
            type="button"
            onClick={handleClose}
            disabled={loading}
            className="px-4 py-2 text-sm font-medium text-gray-700 border border-gray-300 rounded-lg hover:bg-gray-50 disabled:opacity-50"
          >
            Cancel
          </button>
          <button
            type="button"
            onClick={() => void handleSubmit()}
            disabled={loading || !prompt.trim() || !canAfford}
            className="px-4 py-2 text-sm font-medium bg-purple-600 text-white rounded-lg hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            {loading ? "Adding…" : "Add scene"}
          </button>
        </div>
      </div>
    </div>
  );
}
