import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { ArrowUp, CircleAlert, Github, LoaderCircle } from "lucide-react";
import { ApiError, api, navigateToLogin } from "../shared/api/client";
import { useMe } from "../features/auth/useAuth";
import { Button } from "./Button";

function mapError(err: unknown): string {
  if (!(err instanceof ApiError)) {
    return "Something went wrong. Please try again.";
  }
  const reason = String(err.context?.reason ?? "");
  const message = String(err.context?.message ?? "");
  if (err.status === 401) {
    return "Please sign in with GitHub to submit a repository.";
  }
  if (err.status === 403) {
    return (
      message ||
      "Only accounts with admin or maintain permission on this repository can submit it."
    );
  }
  if (reason === "ref_not_found" || reason === "invalid_ref") {
    return "That branch/tag/commit was not found in this repository.";
  }
  if (reason === "invalid_github_url") {
    return "That doesn't look like a GitHub repository URL. Expected: https://github.com/owner/repo";
  }
  if (reason === "private_repo") {
    return "This repository is private or does not exist. OpenVuln scans public projects only.";
  }
  if (reason === "cooldown") {
    const days = err.context?.retry_after_days;
    return `This project was scanned recently. You can resubmit after ${days ?? "a few"} day(s).`;
  }
  if (reason === "duplicate" || err.status === 409) {
    return message || "This project is already on OpenVuln.";
  }
  if (err.status === 404) {
    return "This repository is private or does not exist. OpenVuln scans public projects only.";
  }
  if (err.status >= 500) {
    return "OpenVuln is temporarily unavailable. Please try again in a moment.";
  }
  return message || err.message || "Submission failed.";
}

export function RepoSubmitForm({
  size = "default",
  appearance = "default",
  className = "",
  align = "center",
}: {
  size?: "default" | "hero";
  appearance?: "default" | "dark";
  className?: string;
  align?: "center" | "left";
}) {
  const nav = useNavigate();
  const meQ = useMe();
  const [url, setUrl] = useState("");
  const [ref, setRef] = useState("");
  const [showRef, setShowRef] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [pending, setPending] = useState(false);

  const hero = size === "hero";
  const dark = appearance === "dark";

  const onSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);
    const git_url = url.trim();
    if (!git_url) {
      setError("Please paste a GitHub repository URL.");
      return;
    }
    // 未登录 → 整页跳 GitHub OAuth，登录后回到部署首页
    if (meQ.data && !meQ.data.authenticated) {
      navigateToLogin();
      window.dispatchEvent(new Event("ov-oauth-popup-opened"));
      return;
    }
    setPending(true);
    try {
      const res = await api.submitProject({ git_url, ...(ref.trim() ? { ref: ref.trim() } : {}) });
      nav(`/p/${res.project.owner_login}/${res.project.name}`, {
        state: { justSubmitted: true },
      });
    } catch (err) {
      setError(mapError(err));
    } finally {
      setPending(false);
    }
  };

  if (dark) {
    // hero composer（暗色控制台）；appearance prop 名保留为调用方兼容
    const centered = align === "center";
    return (
      <form
        onSubmit={(e) => void onSubmit(e)}
        className={className}
        aria-label="Submit a GitHub repository"
        aria-busy={pending}
      >
        <div
          className={`openvuln-composer group flex min-h-[58px] items-center gap-3 rounded-xl border bg-surface-raised p-2 pl-4 shadow-[0_20px_48px_-20px_rgba(0,0,0,0.65)] transition focus-within:bg-surface-sunken/60 ${
            error ? "border-danger/60" : "border-line focus-within:border-line-strong"
          }`}
        >
          <Github
            size={18}
            className="shrink-0 text-ink-tertiary transition group-focus-within:text-ink-secondary"
          />
          <input
            type="url"
            value={url}
            onChange={(e) => {
              setUrl(e.target.value);
              setError(null);
            }}
            placeholder="Paste a public GitHub repository URL"
            spellCheck={false}
            className="min-w-0 flex-1 bg-transparent py-3 font-mono text-[13px] text-ink outline-none placeholder:text-ink-tertiary sm:text-[14px]"
            aria-label="GitHub repository URL"
            aria-invalid={!!error}
          />
          <button
            type="submit"
            aria-label={pending ? "Submitting repository" : "Analyze repository"}
            className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-ink text-surface shadow-sm transition hover:bg-white active:scale-95 focus-ring disabled:cursor-not-allowed disabled:bg-surface-sunken disabled:text-ink-tertiary disabled:opacity-100"
            disabled={!url.trim() || pending}
          >
            {pending ? (
              <LoaderCircle size={19} className="animate-spin motion-reduce:animate-none" />
            ) : (
              <ArrowUp size={19} strokeWidth={2.2} />
            )}
          </button>
        </div>

        <div className={`mt-2.5 flex ${centered ? "justify-center" : "justify-start"}`}>
          {showRef ? (
            <input
              type="text"
              value={ref}
              onChange={(e) => setRef(e.target.value)}
              placeholder="Branch, tag, or commit SHA (optional)"
              spellCheck={false}
              className="h-8 w-72 rounded-lg border border-line bg-surface-raised px-3 font-mono text-xs text-ink outline-none placeholder:text-ink-tertiary focus:border-line-strong"
              aria-label="Version to scan (branch, tag, or commit SHA)"
            />
          ) : (
            <button
              type="button"
              onClick={() => setShowRef(true)}
              className="font-mono text-[11px] text-ink-tertiary underline decoration-line underline-offset-2 transition hover:text-ink-secondary"
            >
              Scan a specific version
            </button>
          )}
        </div>

        <div className={`mt-2.5 flex min-h-5 items-start gap-1.5 text-xs text-ink-tertiary ${centered ? "justify-center text-center" : "justify-start text-left"}`}>
          {error ? (
            <span className="inline-flex items-start gap-1.5 text-danger" role="alert">
              <CircleAlert size={14} className="mt-px shrink-0" />
              <span>{error}</span>
            </span>
          ) : pending ? (
            <span className="text-ink-secondary" role="status">Submitting repository…</span>
          ) : (
            <span className="inline-flex items-center gap-1.5">
              <CircleAlert size={13} strokeWidth={1.8} className="shrink-0" aria-hidden />
              <span>Public repositories · Repository maintainers only</span>
            </span>
          )}
        </div>
      </form>
    );
  }

  return (
    <form onSubmit={(e) => void onSubmit(e)} className={className}>
      <div className="flex flex-col gap-2 sm:flex-row">
        <input
          type="text"
          value={url}
          onChange={(e) => setUrl(e.target.value)}
          placeholder="https://github.com/owner/repo"
          spellCheck={false}
          className={`h-12 flex-1 rounded-lg border bg-surface-raised px-3.5 font-mono text-sm text-ink placeholder:text-ink-tertiary focus-ring ${
            error ? "border-danger" : "border-line"
          }`}
          aria-invalid={!!error}
        />
        <Button type="submit" size="lg" disabled={pending} className="rounded-lg shrink-0">
          {pending ? "Submitting…" : "Submit"}
        </Button>
      </div>
      <div className="mt-2">
        {showRef ? (
          <input
            type="text"
            value={ref}
            onChange={(e) => setRef(e.target.value)}
            placeholder="Branch, tag, or commit SHA (optional — default: default branch HEAD)"
            spellCheck={false}
            className="h-9 w-full rounded-md border border-line bg-surface-raised px-3 font-mono text-xs text-ink placeholder:text-ink-tertiary focus-ring"
            aria-label="Version to scan (branch, tag, or commit SHA)"
          />
        ) : (
          <button
            type="button"
            onClick={() => setShowRef(true)}
            className="text-[12px] text-ink-tertiary underline decoration-line underline-offset-2 transition-colors hover:text-ink-secondary"
          >
            Scan a specific version
          </button>
        )}
      </div>
      {error && (
        <p
          className={`mt-2 flex items-start gap-1.5 text-sm text-danger ${hero ? "justify-center text-left" : ""}`}
          role="alert"
        >
          <CircleAlert size={16} className="mt-0.5 shrink-0" />
          <span>{error}</span>
        </p>
      )}
    </form>
  );
}
