import { useEffect, useRef, useState } from "react";

import { createRepository, parseGitUrl, type GitRepositoryCreate, type URLParseResult } from "../api/git_repositories";
import { listSSHKeys, type SSHKey } from "../api/ssh_keys";
import { Icon } from "./icon";

type CreateMode = "clone" | "blank";
type UrlValidationStatus = "idle" | "validating" | "valid" | "needs-parsing" | "invalid";

interface RepositoryCreateDialogProps {
  projectId: string;
  open: boolean;
  title: string;
  onClose: () => void;
  onCreated: () => Promise<void> | void;
}

export const RepositoryCreateDialog = ({ projectId, open, title, onClose, onCreated }: RepositoryCreateDialogProps) => {
  const [createMode, setCreateMode] = useState<CreateMode>("clone");
  const [formName, setFormName] = useState("");
  const [owner, setOwner] = useState("");
  const [repoName, setRepoName] = useState("");
  const [advancedUrl, setAdvancedUrl] = useState("");
  const [useAdvancedUrl, setUseAdvancedUrl] = useState(false);
  const [formError, setFormError] = useState<string | null>(null);
  const [urlValidation, setUrlValidation] = useState<{
    status: UrlValidationStatus;
    result: URLParseResult | null;
  }>({ status: "idle", result: null });
  const [sshKeys, setSshKeys] = useState<SSHKey[]>([]);
  const [selectedSshKey, setSelectedSshKey] = useState<string>("");
  const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  useEffect(() => {
    if (!open && debounceTimer.current) {
      clearTimeout(debounceTimer.current);
      debounceTimer.current = null;
    }
  }, [open]);

  useEffect(() => {
    if (!open) return;
    const loadKeys = async () => {
      try {
        const data = await listSSHKeys();
        setSshKeys(data);
      } catch {
        // ignore
      }
    };
    void loadKeys();
  }, [open]);

  useEffect(() => {
    if (!open) return;
    if (!useAdvancedUrl) {
      setUrlValidation({ status: "idle", result: null });
      return;
    }

    if (debounceTimer.current) {
      clearTimeout(debounceTimer.current);
    }

    if (!advancedUrl.trim()) {
      setUrlValidation({ status: "idle", result: null });
      return;
    }

    setUrlValidation({ status: "validating", result: null });

    debounceTimer.current = setTimeout(async () => {
      try {
        const result = await parseGitUrl(advancedUrl.trim());
        if (result.is_valid_clone_url) {
          setUrlValidation({ status: "valid", result });
        } else if (result.needs_parsing) {
          setUrlValidation({ status: "needs-parsing", result });
        } else {
          setUrlValidation({ status: "invalid", result });
        }
      } catch {
        setUrlValidation({ status: "invalid", result: null });
      }
    }, 300);

    return () => {
      if (debounceTimer.current) {
        clearTimeout(debounceTimer.current);
      }
    };
  }, [advancedUrl, open, useAdvancedUrl]);

  const resetForm = () => {
    setCreateMode("clone");
    setFormName("");
    setOwner("");
    setRepoName("");
    setAdvancedUrl("");
    setUseAdvancedUrl(false);
    setFormError(null);
    setUrlValidation({ status: "idle", result: null });
    setSelectedSshKey("");
  };

  const handleClose = () => {
    resetForm();
    onClose();
  };

  const handleSubmit = async (event: React.FormEvent) => {
    event.preventDefault();
    setFormError(null);

    if (!formName.trim()) {
      setFormError("Repository name is required");
      return;
    }

    try {
      const input: GitRepositoryCreate = {
        name: formName.trim(),
        remote_url: undefined,
      };

      if (createMode === "clone") {
        if (useAdvancedUrl) {
          if (!advancedUrl.trim()) {
            setFormError("Remote URL is required for advanced cloning");
            return;
          }
          input.remote_url = advancedUrl.trim();
        } else {
          if (!owner.trim() || !repoName.trim()) {
            setFormError("Owner and repository name are required");
            return;
          }
          input.remote_url = `git@git.commumedia.org:${owner.trim()}/${repoName.trim()}.git`;
        }
        if (selectedSshKey) {
          input.ssh_key_id = selectedSshKey;
        }
      }

      await createRepository(projectId, input);
      handleClose();
      await onCreated();
    } catch (error: unknown) {
      const response = error as { response?: { data?: { detail?: string } } };
      const detail = response.response?.data?.detail;
      setFormError(typeof detail === "string" ? detail : "Failed to create repository");
    }
  };

  const handleUseSuggestedUrl = () => {
    if (urlValidation.result?.base_url) {
      setAdvancedUrl(urlValidation.result.base_url);
      setUrlValidation({ status: "idle", result: null });
      setFormError(null);
    }
  };

  const getUrlInputClass = () => {
    switch (urlValidation.status) {
      case "valid":
        return "valid-url";
      case "needs-parsing":
        return "needs-parsing-url";
      case "invalid":
        return "invalid-url";
      default:
        return "";
    }
  };

  if (!open) return null;

  return (
    <div className="dialog-overlay" role="dialog" aria-modal="true">
      <div className="dialog">
        <h3>{title}</h3>
        <p className="muted">
          Clone an existing repository from git.commumedia.org, or create a blank bare repo here.
        </p>
        <form onSubmit={handleSubmit} className="stack">
          <div className="form-field">
            <label>
              <input
                type="radio"
                name="repository-mode"
                checked={createMode === "clone"}
                onChange={() => setCreateMode("clone")}
              />
              Clone existing repository
            </label>
            <label>
              <input
                type="radio"
                name="repository-mode"
                checked={createMode === "blank"}
                onChange={() => setCreateMode("blank")}
              />
              Create blank repository
            </label>
          </div>
          <label className="form-field">
            Repository name
            <input
              type="text"
              value={formName}
              onChange={(event) => setFormName(event.target.value)}
              placeholder="repository-name"
            />
          </label>
          {createMode === "clone" && !useAdvancedUrl && (
            <>
              <label className="form-field">
                Owner
                <input
                  type="text"
                  value={owner}
                  onChange={(event) => setOwner(event.target.value)}
                  placeholder="owner"
                />
              </label>
              <label className="form-field">
                Repository
                <input
                  type="text"
                  value={repoName}
                  onChange={(event) => setRepoName(event.target.value)}
                  placeholder="repo-name"
                />
              </label>
              <label className="form-field">
                SSH Key
                <select
                  value={selectedSshKey}
                  onChange={(event) => setSelectedSshKey(event.target.value)}
                >
                  <option value="">Select SSH key (optional)...</option>
                  {sshKeys.map((k) => (
                    <option key={k.id} value={k.id}>
                      {k.name}
                    </option>
                  ))}
                </select>
              </label>
              <p className="muted">SSH target: git@git.commumedia.org:{owner || "owner"}/{repoName || "repo"}.git</p>
              <button
                type="button"
                className="secondary-button small"
                onClick={() => setUseAdvancedUrl(true)}
              >
                Use full URL instead
              </button>
            </>
          )}
          {createMode === "clone" && useAdvancedUrl && (
            <>
              <label className="form-field">
                Remote URL
                <input
                  type="text"
                  value={advancedUrl}
                  onChange={(event) => setAdvancedUrl(event.target.value)}
                  placeholder="https://github.com/user/repo.git"
                  className={getUrlInputClass()}
                />
                {urlValidation.status === "validating" && (
                  <span className="validation-status validating">Validating...</span>
                )}
                {urlValidation.status === "valid" && (
                  <span className="validation-status valid">
                    <Icon name="success" size="sm" /> Valid git URL
                  </span>
                )}
                {urlValidation.status === "needs-parsing" && urlValidation.result && (
                  <div className="url-suggestion">
                    <span className="validation-status warning">
                      <Icon name="warning" size="sm" /> This looks like a browser URL
                    </span>
                    <div className="suggestion-actions">
                      <span className="suggested-url">Suggested: {urlValidation.result.base_url}</span>
                      <button
                        type="button"
                        className="secondary-button small"
                        onClick={handleUseSuggestedUrl}
                      >
                        Use Suggested
                      </button>
                    </div>
                  </div>
                )}
                {urlValidation.status === "invalid" && (
                  <span className="validation-status invalid">
                    <Icon name="error" size="sm" /> Invalid URL
                  </span>
                )}
              </label>
              <label className="form-field">
                SSH Key
                <select
                  value={selectedSshKey}
                  onChange={(event) => setSelectedSshKey(event.target.value)}
                >
                  <option value="">Select SSH key (optional)...</option>
                  {sshKeys.map((k) => (
                    <option key={k.id} value={k.id}>
                      {k.name}
                    </option>
                  ))}
                </select>
              </label>
              <button
                type="button"
                className="secondary-button small"
                onClick={() => setUseAdvancedUrl(false)}
              >
                Use owner/repo instead
              </button>
            </>
          )}
          {formError && (
            <div className="error-message">
              <p className="error-text">{formError}</p>
            </div>
          )}
          <div className="dialog-actions">
            <button className="secondary-button" onClick={handleClose} type="button">
              <Icon name="cancel" size="sm" />
              Cancel
            </button>
            <button className="primary-button" type="submit">
              <Icon name="add" size="sm" />
              {createMode === "clone" ? "Clone Repository" : "Create Blank Repository"}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
};
