"use client";

import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import { JM } from "./modal-theme";
import {
  SetupHeader, FieldLabel, TextInput, TextArea, AudienceSelector,
  PrimaryButton, SecondaryButton, StepDots,
  type SetupProps, type Audience,
} from "./setup-shared";

/**
 * "Import existing code" — two-step setup with GitHub OAuth.
 *
 * Step 1: project name + audience + repo source.
 *   Repo source defaults to the connected-GitHub picker; falls back to
 *   "paste a public URL" if the user hasn't linked GitHub yet (or
 *   prefers to bring an arbitrary repo).
 * Step 2: optional "what do you want to do with it" textarea (seeds
 *   the AI's first message).
 */
export function ImportSetup({ workspace, onClose, onBack }: SetupProps) {
  const router = useRouter();
  const [step, setStep] = useState<0 | 1>(0);
  const [name, setName] = useState("");
  const [audience, setAudience] = useState<Audience>("customers");

  // GitHub OAuth state. `connected === undefined` means we haven't
  // checked yet; `null` means "checked, not linked".
  const [connected, setConnected] = useState<undefined | null | { login: string; repos: GhRepo[] }>(undefined);
  const [picker, setPicker] = useState<"github" | "url">("github");
  const [filter, setFilter] = useState("");
  const [selectedRepoId, setSelectedRepoId] = useState<number | null>(null);
  const [manualUrl, setManualUrl] = useState("");

  const [intent, setIntent] = useState("");
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    let cancelled = false;
    fetch("/api/integrations/github/repos", { credentials: "include" })
      .then(r => r.json())
      .then(d => {
        if (cancelled) return;
        if (d?.connected && Array.isArray(d.repos)) {
          setConnected({ login: d.login, repos: d.repos });
          setPicker("github");
        } else {
          setConnected(null);
          setPicker("url"); // no point defaulting to a picker that's empty
        }
      })
      .catch(() => { if (!cancelled) setConnected(null); });
    return () => { cancelled = true; };
  }, []);

  // Surface ?gh_error / ?gh_connected toasts after returning from GitHub.
  useEffect(() => {
    if (typeof window === "undefined") return;
    const u = new URL(window.location.href);
    const err = u.searchParams.get("gh_error");
    const ok = u.searchParams.get("gh_connected");
    if (err) {
      toast.error(`GitHub: ${err}`);
      u.searchParams.delete("gh_error");
      window.history.replaceState({}, "", u.toString());
    }
    if (ok) {
      toast.success(`Connected GitHub as @${ok}`);
      u.searchParams.delete("gh_connected");
      window.history.replaceState({}, "", u.toString());
      // Refresh repo list silently.
      fetch("/api/integrations/github/repos", { credentials: "include" })
        .then(r => r.json())
        .then(d => {
          if (d?.connected) setConnected({ login: d.login, repos: d.repos });
        })
        .catch(() => {});
    }
  }, []);

  const selectedRepo = connected && typeof connected === "object"
    ? connected.repos.find(r => r.id === selectedRepoId) ?? null
    : null;

  const isValidUrl = /^https?:\/\//i.test(manualUrl.trim());
  const canContinue =
    name.trim().length > 0 &&
    ((picker === "github" && !!selectedRepo) || (picker === "url" && isValidUrl));

  const handleConnect = () => {
    const returnTo = window.location.pathname + window.location.search;
    window.location.href = `/api/integrations/github/connect?returnTo=${encodeURIComponent(returnTo)}`;
  };

  const handleDisconnect = async () => {
    await fetch("/api/integrations/github/disconnect", { method: "POST", credentials: "include" });
    setConnected(null);
    setPicker("url");
    setSelectedRepoId(null);
    toast.success("Disconnected GitHub");
  };

  const handleCreate = async () => {
    if (!canContinue) return;
    const repoUrl = picker === "github" && selectedRepo ? selectedRepo.htmlUrl : manualUrl.trim();
    setLoading(true);
    try {
      const res = await fetch("/api/projects/create", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          projectName: name.trim(),
          projectType: "web-app",
          slug: name.toLowerCase().replace(/[^a-z0-9]+/g, "-"),
          vision: intent.trim() || `Continue work on ${repoUrl}`,
          product: { name: name.trim() },
          audience,
          creationMode: "import",
          githubRepoUrl: repoUrl,
          githubDefaultBranch: selectedRepo?.defaultBranch ?? null,
          githubRepoId: selectedRepo?.id ?? null,
          sourceData: {
            audience, repoUrl,
            via: picker === "github" ? "oauth" : "url",
            ghLogin: picker === "github" ? connected && typeof connected === "object" ? connected.login : null : null,
            intent: intent.trim() || null,
          },
        }),
      });
      if (!res.ok) {
        const err = await res.json();
        toast.error(err.error || "Failed to create project");
        return;
      }
      const data = await res.json();
      onClose();
      router.push(`/${workspace}/project/${data.projectId}/product`);
    } catch {
      toast.error("Something went wrong");
    } finally {
      setLoading(false);
    }
  };

  const filteredRepos = connected && typeof connected === "object"
    ? connected.repos.filter(r => {
        const q = filter.trim().toLowerCase();
        if (!q) return true;
        return r.fullName.toLowerCase().includes(q) || (r.description ?? "").toLowerCase().includes(q);
      })
    : [];

  return (
    <div style={{ padding: 28 }}>
      <SetupHeader
        icon="⌘" label="Import existing code" tagline="From GitHub"
        accent="#1D4ED8" onBack={step === 0 ? onBack : () => setStep(0)} onClose={onClose}
      />

      {step === 0 && (
        <>
          <FieldLabel>Project name</FieldLabel>
          <TextInput
            value={name}
            onChange={setName}
            placeholder="What do you want to call this?"
            autoFocus
          />

          <AudienceSelector value={audience} onChange={setAudience} />

          {/* Repo source */}
          {connected === undefined ? (
            <div style={loadingBox}>Checking GitHub connection…</div>
          ) : connected === null ? (
            <NotConnectedBlock
              onConnect={handleConnect}
              picker={picker}
              setPicker={setPicker}
              manualUrl={manualUrl}
              setManualUrl={setManualUrl}
            />
          ) : (
            <ConnectedBlock
              login={connected.login}
              picker={picker}
              setPicker={setPicker}
              repos={filteredRepos}
              filter={filter}
              setFilter={setFilter}
              selectedRepoId={selectedRepoId}
              setSelectedRepoId={setSelectedRepoId}
              manualUrl={manualUrl}
              setManualUrl={setManualUrl}
              onDisconnect={handleDisconnect}
            />
          )}

          <FlowFooter step={0} total={2} primary={
            <PrimaryButton onClick={() => setStep(1)} disabled={!canContinue}>
              Next →
            </PrimaryButton>
          } />
        </>
      )}

      {step === 1 && (
        <>
          <FieldLabel>What do you want to do with it? <span style={{ color: JM.muted, fontWeight: 400 }}>(optional)</span></FieldLabel>
          <TextArea
            value={intent}
            onChange={setIntent}
            placeholder="Add a payments page, fix the login bug, and clean up the dashboard."
            rows={6}
            autoFocus
          />
          <p style={{ fontSize: 12, color: JM.muted, marginTop: -8, marginBottom: 18, lineHeight: 1.5 }}>
            This tells Vibn where to start. Skip it and you can guide things in chat once the project's open.
          </p>

          <FlowFooter
            step={1} total={2}
            secondary={<SecondaryButton onClick={() => setStep(0)}>← Back</SecondaryButton>}
            primary={
              <PrimaryButton onClick={handleCreate} disabled={!canContinue} loading={loading}>
                Import & open →
              </PrimaryButton>
            }
          />
        </>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Sub-blocks
// ─────────────────────────────────────────────────────────────────────────────

interface GhRepo {
  id: number;
  name: string;
  fullName: string;
  description: string | null;
  defaultBranch: string;
  htmlUrl: string;
  private: boolean;
  language: string | null;
  pushedAt: string | null;
  fork: boolean;
}

function NotConnectedBlock({
  onConnect, picker, setPicker, manualUrl, setManualUrl,
}: {
  onConnect: () => void;
  picker: "github" | "url";
  setPicker: (p: "github" | "url") => void;
  manualUrl: string;
  setManualUrl: (s: string) => void;
}) {
  return (
    <>
      <FieldLabel>Where's the code?</FieldLabel>
      <div style={{
        padding: 14, borderRadius: 10, border: `1px solid ${JM.border}`,
        background: JM.cream, marginBottom: 14,
        display: "flex", alignItems: "center", gap: 12,
      }}>
        <div style={{
          width: 34, height: 34, borderRadius: 8, background: "#1A1A1A",
          display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
        }}>
          <GhMark />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 13, fontWeight: 600, color: JM.ink }}>Connect your GitHub</div>
          <div style={{ fontSize: 11.5, color: JM.mid, marginTop: 1 }}>
            Pick from a list of your repos — public or private.
          </div>
        </div>
        <button
          type="button"
          onClick={onConnect}
          style={{
            padding: "7px 13px", borderRadius: 7,
            background: "#1A1A1A", color: "#fff", border: "none",
            fontSize: 12.5, fontWeight: 600, cursor: "pointer",
            fontFamily: JM.fontSans, flexShrink: 0,
          }}
        >
          Connect →
        </button>
      </div>

      <button
        type="button"
        onClick={() => setPicker(picker === "url" ? "github" : "url")}
        style={linkButton}
      >
        {picker === "url" ? "I'd rather connect GitHub" : "Or paste a public repo URL instead →"}
      </button>

      {picker === "url" && (
        <div style={{ marginTop: 10 }}>
          <FieldLabel>Public GitHub URL</FieldLabel>
          <TextInput
            value={manualUrl}
            onChange={setManualUrl}
            placeholder="https://github.com/yourname/your-repo"
          />
          <p style={{ fontSize: 11.5, color: JM.muted, marginTop: -8, marginBottom: 14, lineHeight: 1.5 }}>
            Public repos work without connecting GitHub. Private repos need the connection above.
          </p>
        </div>
      )}
    </>
  );
}

function ConnectedBlock({
  login, picker, setPicker, repos, filter, setFilter,
  selectedRepoId, setSelectedRepoId, manualUrl, setManualUrl, onDisconnect,
}: {
  login: string;
  picker: "github" | "url";
  setPicker: (p: "github" | "url") => void;
  repos: GhRepo[];
  filter: string; setFilter: (s: string) => void;
  selectedRepoId: number | null;
  setSelectedRepoId: (n: number | null) => void;
  manualUrl: string;
  setManualUrl: (s: string) => void;
  onDisconnect: () => void;
}) {
  return (
    <>
      <div style={{
        display: "flex", alignItems: "center", gap: 8,
        padding: "8px 12px", borderRadius: 8,
        background: JM.cream, border: `1px solid ${JM.border}`,
        marginBottom: 12, fontSize: 12, color: JM.mid, fontFamily: JM.fontSans,
      }}>
        <GhMark size={14} dark />
        <span>Connected as <strong style={{ color: JM.ink, fontWeight: 600 }}>@{login}</strong></span>
        <div style={{ flex: 1 }} />
        <button type="button" onClick={onDisconnect} style={textBtn}>Disconnect</button>
      </div>

      {picker === "github" ? (
        <>
          <FieldLabel>Pick a repository</FieldLabel>
          <input
            type="text"
            value={filter}
            onChange={e => setFilter(e.target.value)}
            placeholder={`Search ${repos.length > 0 ? `${repos.length} repos…` : "repos…"}`}
            style={{
              width: "100%", padding: "9px 12px", marginBottom: 8,
              borderRadius: 7, border: `1px solid ${JM.border}`,
              background: JM.inputBg, fontSize: 13,
              fontFamily: JM.fontSans, color: JM.ink,
              outline: "none", boxSizing: "border-box",
            }}
            onFocus={e => (e.currentTarget.style.borderColor = JM.indigo)}
            onBlur={e => (e.currentTarget.style.borderColor = JM.border)}
          />
          <div style={{
            maxHeight: 220, overflowY: "auto",
            border: `1px solid ${JM.border}`, borderRadius: 8,
            background: "#fff", marginBottom: 12,
          }}>
            {repos.length === 0 ? (
              <div style={{ padding: 18, fontSize: 12.5, color: JM.muted, textAlign: "center" }}>
                No matching repos
              </div>
            ) : (
              repos.map(r => {
                const sel = r.id === selectedRepoId;
                return (
                  <button
                    key={r.id}
                    type="button"
                    onClick={() => setSelectedRepoId(r.id)}
                    style={{
                      width: "100%", textAlign: "left",
                      padding: "9px 12px",
                      border: "none", borderBottom: `1px solid ${JM.border}`,
                      background: sel ? "#EEF2FF" : "transparent",
                      cursor: "pointer", fontFamily: JM.fontSans,
                      display: "flex", alignItems: "center", gap: 8,
                    }}
                    onMouseEnter={e => { if (!sel) e.currentTarget.style.background = JM.cream; }}
                    onMouseLeave={e => { if (!sel) e.currentTarget.style.background = "transparent"; }}
                  >
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{
                        fontSize: 13, fontWeight: 600, color: JM.ink,
                        whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
                      }}>
                        {r.fullName}
                      </div>
                      {r.description && (
                        <div style={{
                          fontSize: 11.5, color: JM.mid, marginTop: 1,
                          whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
                        }}>
                          {r.description}
                        </div>
                      )}
                    </div>
                    <div style={{ display: "flex", gap: 5, flexShrink: 0 }}>
                      {r.private && <Badge>Private</Badge>}
                      {r.language && <Badge muted>{r.language}</Badge>}
                    </div>
                  </button>
                );
              })
            )}
          </div>
          <button type="button" onClick={() => setPicker("url")} style={linkButton}>
            Or paste a different URL →
          </button>
        </>
      ) : (
        <>
          <FieldLabel>Public repo URL</FieldLabel>
          <TextInput
            value={manualUrl}
            onChange={setManualUrl}
            placeholder="https://github.com/yourname/your-repo"
          />
          <button type="button" onClick={() => setPicker("github")} style={linkButton}>
            ← Back to your repos
          </button>
        </>
      )}
    </>
  );
}

function Badge({ children, muted }: { children: React.ReactNode; muted?: boolean }) {
  return (
    <span style={{
      fontSize: 10, fontWeight: 600, padding: "2px 7px", borderRadius: 4,
      background: muted ? "#F3F4F6" : "#FEF3C7",
      color: muted ? "#6B7280" : "#92400E",
      letterSpacing: "0.02em", fontFamily: JM.fontSans,
    }}>{children}</span>
  );
}

function GhMark({ size = 18, dark }: { size?: number; dark?: boolean }) {
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill={dark ? "#1A1A1A" : "#fff"}>
      <path fillRule="evenodd" d="M8 0C3.58 0 0 3.58 0 8a8 8 0 005.47 7.59c.4.07.55-.17.55-.38v-1.34c-2.23.48-2.7-1.07-2.7-1.07-.36-.92-.89-1.17-.89-1.17-.73-.5.05-.49.05-.49.81.06 1.24.83 1.24.83.72 1.23 1.88.87 2.34.66.07-.52.28-.87.5-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.13 0 0 .67-.21 2.2.82a7.6 7.6 0 014 0c1.53-1.04 2.2-.82 2.2-.82.44 1.11.16 1.93.08 2.13.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48v2.2c0 .21.15.46.55.38A8.001 8.001 0 0016 8c0-4.42-3.58-8-8-8z"/>
    </svg>
  );
}

function FlowFooter({
  step, total, primary, secondary,
}: {
  step: number; total: number;
  primary: React.ReactNode; secondary?: React.ReactNode;
}) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 6 }}>
      <StepDots step={step} total={total} />
      <div style={{ flex: 1 }} />
      {secondary}
      <div style={{ minWidth: 160 }}>{primary}</div>
    </div>
  );
}

const linkButton: React.CSSProperties = {
  background: "none", border: "none", padding: 0,
  fontSize: 12, color: JM.indigo, cursor: "pointer",
  fontFamily: JM.fontSans, fontWeight: 500,
  marginBottom: 14,
};

const textBtn: React.CSSProperties = {
  background: "none", border: "none", padding: 0,
  fontSize: 11.5, color: JM.muted, cursor: "pointer",
  fontFamily: JM.fontSans,
  textDecoration: "underline",
};

const loadingBox: React.CSSProperties = {
  padding: "14px 16px", borderRadius: 8,
  background: JM.cream, border: `1px solid ${JM.border}`,
  fontSize: 12.5, color: JM.mid, marginBottom: 14, fontFamily: JM.fontSans,
};
