import { WORKSPACE_STORAGE_TYPE } from '@learnitive/constants';
import { useCoreServices } from '@learnitive/context';
import {
  normalizeProjectSlug,
  requestPersistentBrowserStorage,
  supportsOpfsProjectStorage,
} from '@learnitive/project-storage';
import {
  isDefaultPublicGitCorsProxy,
  readBrowserGitSettings,
  writeBrowserGitCorsProxySetting,
} from '@learnitive/service-core';
import {
  Button,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  Input,
  Label,
  toast,
} from '@learnitive/ui-components';
import { WsPath } from '@learnitive/ws-path';
import React from 'react';
import { finalizeCreatedBrowserProject } from '../saas/project-mirror-service';

export function CloneGitRepositoryDialog({
  open,
  onOpenChange,
  navigateOnSuccess = true,
  onCloned,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  navigateOnSuccess?: boolean;
  onCloned?: (workspaceName: string) => void | Promise<void>;
}) {
  const core = useCoreServices();
  const { navigation, projectGit, projectStorage, workspaceOps } = core;
  const [workspaceName, setWorkspaceName] = React.useState('');
  const [url, setUrl] = React.useState('');
  const [token, setToken] = React.useState('');
  const [corsProxy, setCorsProxy] = React.useState(
    () => readBrowserGitSettings().corsProxy,
  );
  const [publicProxyAuthConfirmed, setPublicProxyAuthConfirmed] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState<string>();

  React.useEffect(() => {
    writeBrowserGitCorsProxySetting(corsProxy);
  }, [corsProxy]);

  React.useEffect(() => {
    setPublicProxyAuthConfirmed(false);
  }, [token, corsProxy]);

  const clone = async () => {
    const displayName = workspaceName.trim() || 'Project';
    const name = normalizeProjectSlug(displayName, { fallback: 'project' });
    const repositoryUrl = url.trim();
    const validName = WsPath.safeFromParts(name, '');
    if (!validName.ok) {
      setError(validName.validationError?.reason ?? t.app.git.cloneInvalidName);
      return;
    }
    if (!repositoryUrl) {
      setError(t.app.git.cloneUrlRequired);
      return;
    }
    if (
      token.trim() &&
      isDefaultPublicGitCorsProxy(corsProxy) &&
      !publicProxyAuthConfirmed
    ) {
      setError(
        'Authentication would be sent through the public CORS proxy. Confirm the proxy warning first or use a trusted/self-hosted proxy.',
      );
      return;
    }

    setBusy(true);
    setError(undefined);
    let workspaceCreated = false;
    try {
      await workspaceOps.createWorkspaceInfo({
        name,
        type: supportsOpfsProjectStorage()
          ? WORKSPACE_STORAGE_TYPE.BrowserOPFS
          : WORKSPACE_STORAGE_TYPE.Browser,
        metadata: { product: 'learnitive', projectDisplayName: displayName },
      });
      workspaceCreated = true;
      await requestPersistentBrowserStorage();
      await projectGit.clone(name, repositoryUrl, {
        token: token || undefined,
        corsProxy: corsProxy || undefined,
      });
      const targets = await projectStorage.detectProjectTargets(name);
      const profile = targets[0]?.profile;
      if (profile) await projectStorage.updateProjectProfile(name, profile);
      await finalizeCreatedBrowserProject(name, core);
      await onCloned?.(name);
      toast.success(t.app.git.cloned({ workspace: name }));
      onOpenChange(false);
      if (navigateOnSuccess) {
        if (profile?.entry) navigation.goWsFile(WsPath.fromParts(name, profile.entry).wsPath);
        else navigation.goWorkspace(name);
      }
    } catch (reason) {
      if (workspaceCreated) {
        await workspaceOps.deleteWorkspaceInfo(name).catch(() => undefined);
      }
      const message = reason instanceof Error ? reason.message : String(reason);
      setError(message);
      toast.error(t.app.git.cloneFailed);
    } finally {
      setBusy(false);
    }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle>{t.app.git.cloneRepository}</DialogTitle>
          <DialogDescription>{t.app.git.cloneDescription}</DialogDescription>
        </DialogHeader>
        {error && (
          <div className="rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive" role="alert">
            {error}
          </div>
        )}
        <div className="space-y-3">
          <div className="space-y-1.5">
            <Label htmlFor="interactive-clone-workspace">{t.app.git.cloneWorkspaceName}</Label>
            <Input
              id="interactive-clone-workspace"
              value={workspaceName}
              autoComplete="off"
              onChange={(event) => setWorkspaceName(event.currentTarget.value)}
            />
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="interactive-clone-url">{t.app.git.remoteUrl}</Label>
            <Input
              id="interactive-clone-url"
              value={url}
              placeholder="https://github.com/user/project.git"
              autoComplete="off"
              onChange={(event) => setUrl(event.currentTarget.value)}
            />
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="interactive-clone-token">{t.app.git.token}</Label>
            <Input
              id="interactive-clone-token"
              type="password"
              value={token}
              autoComplete="off"
              onChange={(event) => setToken(event.currentTarget.value)}
            />
            <p className="text-xs text-muted-foreground">{t.app.git.tokenMemoryOnly}</p>
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="interactive-clone-proxy">{t.app.git.corsProxy}</Label>
            <Input
              id="interactive-clone-proxy"
              value={corsProxy}
              autoComplete="off"
              onChange={(event) => setCorsProxy(event.currentTarget.value)}
            />
            <p className="text-xs text-muted-foreground">A CORS proxy is an external network intermediary for browser Git traffic.</p>
          </div>
          {token.trim() && isDefaultPublicGitCorsProxy(corsProxy) && (
            <label className="flex items-start gap-2 rounded-md border border-amber-500/40 bg-amber-500/5 p-2 text-xs">
              <input
                className="mt-0.5"
                type="checkbox"
                checked={publicProxyAuthConfirmed}
                onChange={(event) => setPublicProxyAuthConfirmed(event.currentTarget.checked)}
              />
              <span>I understand this authentication token will be sent through the public CORS proxy for this clone.</span>
            </label>
          )}
          <Button className="w-full" disabled={busy} onClick={() => void clone()}>
            {busy ? t.app.git.cloning : t.app.git.cloneRepository}
          </Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}
