import { useState, useEffect, useCallback, useRef } from "react";
import { Button } from "@/components/ui/button";
import { Globe } from "lucide-react";
import { IpcClient } from "@/ipc/ipc_client";
import { useSettings } from "@/hooks/useSettings";
import { useLoadApp } from "@/hooks/useLoadApp";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { App, VercelDeployment } from "@/ipc/ipc_types";

interface VercelConnectorProps {
  appId: number | null;
  folderName: string;
}

interface VercelProject {
  id: string;
  name: string;
  framework: string | null;
}

interface ConnectedVercelConnectorProps {
  appId: number;
  app: App;
  refreshApp: () => void;
}

interface UnconnectedVercelConnectorProps {
  appId: number | null;
  folderName: string;
  settings: any;
  refreshSettings: () => void;
  refreshApp: () => void;
}

function ConnectedVercelConnector({
  appId,
  app,
  refreshApp,
}: ConnectedVercelConnectorProps) {
  const [isLoadingDeployments, setIsLoadingDeployments] = useState(false);
  const [deploymentsError, setDeploymentsError] = useState<string | null>(null);
  const [deployments, setDeployments] = useState<VercelDeployment[]>([]);
  const [isDisconnecting, setIsDisconnecting] = useState(false);
  const [disconnectError, setDisconnectError] = useState<string | null>(null);

  const handleDisconnectProject = async () => {
    setIsDisconnecting(true);
    setDisconnectError(null);
    try {
      await IpcClient.getInstance().disconnectVercelProject({ appId });
      refreshApp();
    } catch (err: any) {
      setDisconnectError(err.message || "Failed to disconnect project.");
    } finally {
      setIsDisconnecting(false);
    }
  };

  const handleGetDeployments = async () => {
    setIsLoadingDeployments(true);
    setDeploymentsError(null);

    try {
      const result = await IpcClient.getInstance().getVercelDeployments({
        appId,
      });
      setDeployments(result);
    } catch (err: any) {
      setDeploymentsError(
        err.message || "Failed to get deployments from Vercel.",
      );
    } finally {
      setIsLoadingDeployments(false);
    }
  };

  return (
    <div
      className="mt-4 w-full rounded-md"
      data-testid="vercel-connected-project"
    >
      <p className="text-sm text-gray-600 dark:text-gray-300">
        Connected to Vercel Project:
      </p>
      <a
        onClick={(e) => {
          e.preventDefault();
          IpcClient.getInstance().openExternalUrl(
            `https://vercel.com/${app.vercelTeamSlug}/${app.vercelProjectName}`,
          );
        }}
        className="cursor-pointer text-blue-600 hover:underline dark:text-blue-400"
        target="_blank"
        rel="noopener noreferrer"
      >
        {app.vercelProjectName}
      </a>
      {app.vercelDeploymentUrl && (
        <div className="mt-2">
          <p className="text-sm text-gray-600 dark:text-gray-300">
            Live URL:{" "}
            <a
              onClick={(e) => {
                e.preventDefault();
                if (app.vercelDeploymentUrl) {
                  IpcClient.getInstance().openExternalUrl(
                    app.vercelDeploymentUrl,
                  );
                }
              }}
              className="cursor-pointer text-blue-600 hover:underline dark:text-blue-400 font-mono"
              target="_blank"
              rel="noopener noreferrer"
            >
              {app.vercelDeploymentUrl}
            </a>
          </p>
        </div>
      )}
      <div className="mt-2 flex gap-2">
        <Button onClick={handleGetDeployments} disabled={isLoadingDeployments}>
          {isLoadingDeployments ? (
            <>
              <svg
                className="animate-spin h-5 w-5 mr-2 inline"
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                style={{ display: "inline" }}
              >
                <circle
                  className="opacity-25"
                  cx="12"
                  cy="12"
                  r="10"
                  stroke="currentColor"
                  strokeWidth="4"
                ></circle>
                <path
                  className="opacity-75"
                  fill="currentColor"
                  d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
                ></path>
              </svg>
              Getting Deployments...
            </>
          ) : (
            "Get Deployments"
          )}
        </Button>
        <Button
          onClick={handleDisconnectProject}
          disabled={isDisconnecting}
          variant="outline"
        >
          {isDisconnecting ? "Disconnecting..." : "Disconnect from project"}
        </Button>
      </div>
      {deploymentsError && (
        <div className="mt-2">
          <p className="text-red-600">{deploymentsError}</p>
        </div>
      )}
      {deployments.length > 0 && (
        <div className="mt-4">
          <h4 className="font-medium mb-2">Recent Deployments:</h4>
          <div className="space-y-2">
            {deployments.map((deployment) => (
              <div
                key={deployment.uid}
                className="bg-gray-50 dark:bg-gray-800 rounded-md p-3"
              >
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-2">
                    <span
                      className={`inline-flex items-center px-2 py-1 rounded-full text-xs font-medium ${
                        deployment.readyState === "READY"
                          ? "bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-300"
                          : deployment.readyState === "BUILDING"
                            ? "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-300"
                            : "bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300"
                      }`}
                    >
                      {deployment.readyState}
                    </span>
                    <span className="text-sm text-gray-600 dark:text-gray-300">
                      {new Date(deployment.createdAt * 1000).toLocaleString()}
                    </span>
                  </div>
                  <a
                    onClick={(e) => {
                      e.preventDefault();
                      IpcClient.getInstance().openExternalUrl(
                        `https://${deployment.url}`,
                      );
                    }}
                    className="cursor-pointer text-blue-600 hover:underline dark:text-blue-400 text-sm"
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    <Globe className="h-4 w-4 inline mr-1" />
                    View
                  </a>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
      {disconnectError && (
        <p className="text-red-600 mt-2">{disconnectError}</p>
      )}
    </div>
  );
}

function UnconnectedVercelConnector({
  appId,
  folderName,
  settings,
  refreshSettings,
  refreshApp,
}: UnconnectedVercelConnectorProps) {
  // --- Manual Token Entry State ---
  const [accessToken, setAccessToken] = useState("");
  const [isSavingToken, setIsSavingToken] = useState(false);
  const [tokenError, setTokenError] = useState<string | null>(null);
  const [tokenSuccess, setTokenSuccess] = useState(false);

  // --- Project Setup State ---
  const [projectSetupMode, setProjectSetupMode] = useState<
    "create" | "existing"
  >("create");
  const [availableProjects, setAvailableProjects] = useState<VercelProject[]>(
    [],
  );
  const [isLoadingProjects, setIsLoadingProjects] = useState(false);
  const [selectedProject, setSelectedProject] = useState<string>("");

  // Create new project state
  const [projectName, setProjectName] = useState(folderName);
  const [projectAvailable, setProjectAvailable] = useState<boolean | null>(
    null,
  );
  const [projectCheckError, setProjectCheckError] = useState<string | null>(
    null,
  );
  const [isCheckingProject, setIsCheckingProject] = useState(false);
  const [isCreatingProject, setIsCreatingProject] = useState(false);
  const [createProjectError, setCreateProjectError] = useState<string | null>(
    null,
  );
  const [createProjectSuccess, setCreateProjectSuccess] =
    useState<boolean>(false);

  const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // Load available projects when Vercel is connected
  useEffect(() => {
    if (settings?.vercelAccessToken && projectSetupMode === "existing") {
      loadAvailableProjects();
    }
  }, [settings?.vercelAccessToken, projectSetupMode]);

  // Cleanup debounce timer on unmount
  useEffect(() => {
    return () => {
      if (debounceTimeoutRef.current) {
        clearTimeout(debounceTimeoutRef.current);
      }
    };
  }, []);

  const loadAvailableProjects = async () => {
    setIsLoadingProjects(true);
    try {
      const projects = await IpcClient.getInstance().listVercelProjects();
      setAvailableProjects(projects);
    } catch (error) {
      console.error("Failed to load Vercel projects:", error);
    } finally {
      setIsLoadingProjects(false);
    }
  };

  const handleSaveAccessToken = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!accessToken.trim()) return;

    setIsSavingToken(true);
    setTokenError(null);
    setTokenSuccess(false);

    try {
      await IpcClient.getInstance().saveVercelAccessToken({
        token: accessToken.trim(),
      });
      setTokenSuccess(true);
      setAccessToken("");
      refreshSettings();
    } catch (err: any) {
      setTokenError(err.message || "Failed to save access token.");
    } finally {
      setIsSavingToken(false);
    }
  };

  const checkProjectAvailability = useCallback(async (name: string) => {
    setProjectCheckError(null);
    setProjectAvailable(null);
    if (!name) return;
    setIsCheckingProject(true);
    try {
      const result = await IpcClient.getInstance().isVercelProjectAvailable({
        name,
      });
      setProjectAvailable(result.available);
      if (!result.available) {
        setProjectCheckError(result.error || "Project name is not available.");
      }
    } catch (err: any) {
      setProjectCheckError(
        err.message || "Failed to check project availability.",
      );
    } finally {
      setIsCheckingProject(false);
    }
  }, []);

  const debouncedCheckProjectAvailability = useCallback(
    (name: string) => {
      if (debounceTimeoutRef.current) {
        clearTimeout(debounceTimeoutRef.current);
      }
      debounceTimeoutRef.current = setTimeout(() => {
        checkProjectAvailability(name);
      }, 500);
    },
    [checkProjectAvailability],
  );

  const handleSetupProject = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!appId) return;

    setCreateProjectError(null);
    setIsCreatingProject(true);
    setCreateProjectSuccess(false);

    try {
      if (projectSetupMode === "create") {
        await IpcClient.getInstance().createVercelProject({
          name: projectName,
          appId,
        });
      } else {
        await IpcClient.getInstance().connectToExistingVercelProject({
          projectId: selectedProject,
          appId,
        });
      }
      setCreateProjectSuccess(true);
      setProjectCheckError(null);
      refreshApp();
    } catch (err: any) {
      setCreateProjectError(
        err.message ||
          `Failed to ${projectSetupMode === "create" ? "create" : "connect to"} project.`,
      );
    } finally {
      setIsCreatingProject(false);
    }
  };

  if (!settings?.vercelAccessToken) {
    return (
      <div className="mt-1 w-full" data-testid="vercel-unconnected-project">
        <div className="w-ful">
          <div className="flex items-center gap-2 mb-4">
            <h3 className="font-medium">Connect to Vercel</h3>
          </div>

          <div className="space-y-4">
            <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-md p-3">
              <p className="text-sm text-blue-800 dark:text-blue-200 mb-2">
                To connect your app to Vercel, you'll need to create an access
                token:
              </p>
              <ol className="list-decimal list-inside text-sm text-blue-700 dark:text-blue-300 space-y-1">
                <li>If you don't have a Vercel account, sign up first</li>
                <li>Go to Vercel settings to create a token</li>
                <li>Copy the token and paste it below</li>
              </ol>

              <div className="flex gap-2 mt-3">
                <Button
                  onClick={() => {
                    IpcClient.getInstance().openExternalUrl(
                      "https://vercel.com/signup",
                    );
                  }}
                  variant="outline"
                  className="flex-1"
                >
                  Sign Up for Vercel
                </Button>
                <Button
                  onClick={() => {
                    IpcClient.getInstance().openExternalUrl(
                      "https://vercel.com/account/settings/tokens",
                    );
                  }}
                  className="flex-1 bg-blue-600 hover:bg-blue-700 text-white"
                >
                  Open Vercel Settings
                </Button>
              </div>
            </div>

            <form onSubmit={handleSaveAccessToken} className="space-y-3">
              <div>
                <Label className="block text-sm font-medium mb-1">
                  Vercel Access Token
                </Label>
                <Input
                  type="password"
                  placeholder="Enter your Vercel access token"
                  value={accessToken}
                  onChange={(e) => setAccessToken(e.target.value)}
                  disabled={isSavingToken}
                  className="w-full"
                />
              </div>

              <Button
                type="submit"
                disabled={!accessToken.trim() || isSavingToken}
                className="w-full"
              >
                {isSavingToken ? (
                  <>
                    <svg
                      className="animate-spin h-4 w-4 mr-2"
                      xmlns="http://www.w3.org/2000/svg"
                      fill="none"
                      viewBox="0 0 24 24"
                    >
                      <circle
                        className="opacity-25"
                        cx="12"
                        cy="12"
                        r="10"
                        stroke="currentColor"
                        strokeWidth="4"
                      ></circle>
                      <path
                        className="opacity-75"
                        fill="currentColor"
                        d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
                      ></path>
                    </svg>
                    Saving Token...
                  </>
                ) : (
                  "Save Access Token"
                )}
              </Button>
            </form>

            {tokenError && (
              <div className="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-md p-3">
                <p className="text-sm text-red-800 dark:text-red-200">
                  {tokenError}
                </p>
              </div>
            )}

            {tokenSuccess && (
              <div className="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-md p-3">
                <p className="text-sm text-green-800 dark:text-green-200">
                  Successfully connected to Vercel! You can now set up your
                  project below.
                </p>
              </div>
            )}
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="mt-4 w-full rounded-md" data-testid="vercel-setup-project">
      {/* Collapsible Header */}
      <div className="font-medium mb-2">Set up your Vercel project</div>

      {/* Collapsible Content */}
      <div
        className={`overflow-hidden transition-all duration-300 ease-in-out`}
      >
        <div className="pt-0 space-y-4">
          {/* Mode Selection */}
          <div>
            <div className="flex rounded-md border border-gray-200 dark:border-gray-700">
              <Button
                type="button"
                variant={projectSetupMode === "create" ? "default" : "ghost"}
                className={`flex-1 rounded-none rounded-l-md border-0 ${
                  projectSetupMode === "create"
                    ? "bg-primary text-primary-foreground"
                    : "hover:bg-gray-50 dark:hover:bg-gray-800"
                }`}
                onClick={() => {
                  setProjectSetupMode("create");
                  setCreateProjectError(null);
                  setCreateProjectSuccess(false);
                }}
              >
                Create new project
              </Button>
              <Button
                type="button"
                variant={projectSetupMode === "existing" ? "default" : "ghost"}
                className={`flex-1 rounded-none rounded-r-md border-0 border-l border-gray-200 dark:border-gray-700 ${
                  projectSetupMode === "existing"
                    ? "bg-primary text-primary-foreground"
                    : "hover:bg-gray-50 dark:hover:bg-gray-800"
                }`}
                onClick={() => {
                  setProjectSetupMode("existing");
                  setCreateProjectError(null);
                  setCreateProjectSuccess(false);
                }}
              >
                Connect to existing project
              </Button>
            </div>
          </div>

          <form className="space-y-4" onSubmit={handleSetupProject}>
            {projectSetupMode === "create" ? (
              <>
                <div>
                  <Label className="block text-sm font-medium">
                    Project Name
                  </Label>
                  <Input
                    data-testid="vercel-create-project-name-input"
                    className="w-full mt-1"
                    value={projectName}
                    onChange={(e) => {
                      const newValue = e.target.value;
                      setProjectName(newValue);
                      setProjectAvailable(null);
                      setProjectCheckError(null);
                      debouncedCheckProjectAvailability(newValue);
                    }}
                    disabled={isCreatingProject}
                  />
                  {isCheckingProject && (
                    <p className="text-xs text-gray-500 mt-1">
                      Checking availability...
                    </p>
                  )}
                  {projectAvailable === true && (
                    <p className="text-xs text-green-600 mt-1">
                      Project name is available!
                    </p>
                  )}
                  {projectAvailable === false && (
                    <p className="text-xs text-red-600 mt-1">
                      {projectCheckError}
                    </p>
                  )}
                </div>
              </>
            ) : (
              <>
                <div>
                  <Label className="block text-sm font-medium">
                    Select Project
                  </Label>
                  <Select
                    value={selectedProject}
                    onValueChange={setSelectedProject}
                    disabled={isLoadingProjects}
                  >
                    <SelectTrigger
                      className="w-full mt-1"
                      data-testid="vercel-project-select"
                    >
                      <SelectValue
                        placeholder={
                          isLoadingProjects
                            ? "Loading projects..."
                            : "Select a project"
                        }
                      />
                    </SelectTrigger>
                    <SelectContent>
                      {availableProjects.map((project) => (
                        <SelectItem key={project.id} value={project.id}>
                          {project.name}{" "}
                          {project.framework && `(${project.framework})`}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
              </>
            )}

            <Button
              type="submit"
              disabled={
                isCreatingProject ||
                (projectSetupMode === "create" &&
                  (projectAvailable === false || !projectName)) ||
                (projectSetupMode === "existing" && !selectedProject)
              }
            >
              {isCreatingProject
                ? projectSetupMode === "create"
                  ? "Creating..."
                  : "Connecting..."
                : projectSetupMode === "create"
                  ? "Create Project"
                  : "Connect to Project"}
            </Button>
          </form>

          {createProjectError && (
            <p className="text-red-600 mt-2">{createProjectError}</p>
          )}
          {createProjectSuccess && (
            <p className="text-green-600 mt-2">
              {projectSetupMode === "create"
                ? "Project created and linked!"
                : "Connected to project!"}
            </p>
          )}
        </div>
      </div>
    </div>
  );
}

export function VercelConnector({ appId, folderName }: VercelConnectorProps) {
  const { app, refreshApp } = useLoadApp(appId);
  const { settings, refreshSettings } = useSettings();

  if (app?.vercelProjectId && appId) {
    return (
      <ConnectedVercelConnector
        appId={appId}
        app={app}
        refreshApp={refreshApp}
      />
    );
  } else {
    return (
      <UnconnectedVercelConnector
        appId={appId}
        folderName={folderName}
        settings={settings}
        refreshSettings={refreshSettings}
        refreshApp={refreshApp}
      />
    );
  }
}
