"use client";

import { useEffect, useState } from "react";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { KeyRound, Loader2, Lock, Unlock } from "lucide-react";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

import {
  getConnectionRepos,
  getForgejoConnections,
  type ForgejoConnection,
  type ForgejoRemoteRepo,
  type ForgejoRepositoryCreate,
} from "@/lib/api-forgejo";

interface ForgejoRepositoryFormProps {
  defaultValues?: Partial<ForgejoRepositoryFormValues>;
  onSubmit: (values: ForgejoRepositoryCreate) => Promise<void>;
  isSubmitting?: boolean;
  title?: string;
  description?: string;
  submitLabel?: string;
}

export interface ForgejoRepositoryFormValues {
  connection_id: string;
  owner: string;
  repo: string;
  display_name?: string;
  default_branch?: string;
  webhook_secret?: string;
  /** When true, shows the webhook secret field (edit mode only) */
  showWebhookSecret?: boolean;
}

export function ForgejoRepositoryForm({
  defaultValues = {},
  onSubmit,
  isSubmitting = false,
  title = "Tracked Repository",
  description = "Add a repository to track issues and pull requests.",
  submitLabel = "Save Repository",
}: ForgejoRepositoryFormProps) {
  const [error, setError] = useState<string | null>(null);
  const [isSaving, setIsSaving] = useState(false);
  const [connectionId, setConnectionId] = useState(
    defaultValues.connection_id || "",
  );
  const [owner, setOwner] = useState(defaultValues.owner || "");
  const [repo, setRepo] = useState(defaultValues.repo || "");
  const [displayName, setDisplayName] = useState(
    defaultValues.display_name || "",
  );
  const [defaultBranch, setDefaultBranch] = useState(
    defaultValues.default_branch || "main",
  );
  const [webhookSecret, setWebhookSecret] = useState(
    defaultValues.webhook_secret || "",
  );
  const showWebhookSecret = Boolean(defaultValues.showWebhookSecret);

  const [connections, setConnections] = useState<ForgejoConnection[]>([]);
  const [isLoadingConnections, setIsLoadingConnections] = useState(false);

  // Remote repo discovery
  const [remoteRepos, setRemoteRepos] = useState<ForgejoRemoteRepo[]>([]);
  const [isLoadingRepos, setIsLoadingRepos] = useState(false);
  const [repoLoadError, setRepoLoadError] = useState<string | null>(null);
  const [selectedFullName, setSelectedFullName] = useState(
    defaultValues.owner && defaultValues.repo
      ? `${defaultValues.owner}/${defaultValues.repo}`
      : "",
  );

  const isBusy = isSubmitting || isSaving;
  const isEditMode = Boolean(defaultValues.connection_id);

  useEffect(() => {
    const fetchConnections = async () => {
      try {
        setIsLoadingConnections(true);
        const data = await getForgejoConnections();
        setConnections(data.filter((c) => c.active));
      } catch {
        setError("Failed to load connections.");
      } finally {
        setIsLoadingConnections(false);
      }
    };
    fetchConnections();
  }, []);

  // When a connection is chosen, fetch accessible repos from that Forgejo instance
  useEffect(() => {
    if (!connectionId || isEditMode) return;
    setRemoteRepos([]);
    setSelectedFullName("");
    setOwner("");
    setRepo("");
    setDefaultBranch("main");
    setRepoLoadError(null);

    const fetchRepos = async () => {
      setIsLoadingRepos(true);
      try {
        const data = await getConnectionRepos(connectionId);
        setRemoteRepos(data);
      } catch (err) {
        setRepoLoadError(
          err instanceof Error
            ? err.message
            : "Could not fetch repositories from this connection.",
        );
      } finally {
        setIsLoadingRepos(false);
      }
    };
    fetchRepos();
  }, [connectionId, isEditMode]);

  const handleRepoSelect = (fullName: string) => {
    setSelectedFullName(fullName);
    const found = remoteRepos.find((r) => r.full_name === fullName);
    if (!found) return;
    setOwner(found.owner);
    setRepo(found.name);
    setDefaultBranch(found.default_branch || "main");
    if (!displayName) setDisplayName(found.name);
  };

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    if (!connectionId) {
      setError("Choose a connection before saving.");
      return;
    }
    if (!owner || !repo) {
      setError("Select a repository or enter an owner and repository name.");
      return;
    }
    try {
      setIsSaving(true);
      await onSubmit({
        connection_id: connectionId,
        owner,
        repo,
        display_name: displayName || undefined,
        default_branch: defaultBranch,
        ...(showWebhookSecret
          ? { webhook_secret: webhookSecret || null }
          : {}),
      });
    } catch (err) {
      setError(err instanceof Error ? err.message : "An error occurred.");
    } finally {
      setIsSaving(false);
    }
  }

  return (
    <form
      onSubmit={handleSubmit}
      className="surface-panel w-full max-w-2xl space-y-6 rounded-2xl p-4 sm:p-6"
    >
      <div className="space-y-4">
        <div>
          <h3 className="text-lg font-semibold text-strong">{title}</h3>
          {description && (
            <p className="mt-1 text-sm text-muted">{description}</p>
          )}
        </div>

        {error && (
          <div className="rounded-xl border border-[color:rgba(248,113,113,0.35)] bg-[color:rgba(248,113,113,0.08)] p-4 text-[color:var(--danger)]">
            <p className="font-medium">Configuration Error</p>
            <p className="text-sm">{error}</p>
          </div>
        )}

        {/* Connection */}
        <div className="space-y-2">
          <label htmlFor="connection_id" className="text-sm font-medium">
            Connection
          </label>
          <Select
            value={connectionId}
            onValueChange={setConnectionId}
            disabled={
              isBusy ||
              isLoadingConnections ||
              connections.length === 0 ||
              isEditMode
            }
          >
            <SelectTrigger id="connection_id">
              <SelectValue
                placeholder={
                  isLoadingConnections
                    ? "Loading connections…"
                    : connections.length === 0
                      ? "No active connections"
                      : "Select a connection"
                }
              />
            </SelectTrigger>
            <SelectContent>
              {connections.map((conn) => (
                <SelectItem key={conn.id} value={conn.id}>
                  {conn.name} — {conn.base_url}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <p className="text-xs text-muted">
            The Forgejo connection to use.{" "}
            {connections.length === 0 && !isLoadingConnections && (
              <span className="text-[color:var(--danger)]">
                Add a connection first.
              </span>
            )}
          </p>
        </div>

        {/* Repo picker — shown when connection is selected in create mode */}
        {!isEditMode && connectionId && (
          <div className="space-y-2">
            <label htmlFor="repo_select" className="text-sm font-medium">
              Repository
            </label>
            {isLoadingRepos ? (
              <div className="flex items-center gap-2 rounded-xl border border-[color:var(--border)] px-3 py-2.5 text-sm text-muted">
                <Loader2 className="h-4 w-4 animate-spin" />
                Fetching repositories from Forgejo…
              </div>
            ) : repoLoadError ? (
              <div className="space-y-2">
                <div className="rounded-xl border border-[color:rgba(248,113,113,0.35)] bg-[color:rgba(248,113,113,0.08)] px-3 py-2 text-xs text-[color:var(--danger)]">
                  {repoLoadError} — enter owner and repository manually below.
                </div>
                <ManualOwnerRepoFields
                  owner={owner}
                  repo={repo}
                  onOwnerChange={setOwner}
                  onRepoChange={setRepo}
                  disabled={isBusy}
                />
              </div>
            ) : remoteRepos.length > 0 ? (
              <>
                <Select
                  value={selectedFullName}
                  onValueChange={handleRepoSelect}
                  disabled={isBusy}
                >
                  <SelectTrigger id="repo_select">
                    <SelectValue placeholder="Select a repository…" />
                  </SelectTrigger>
                  <SelectContent>
                    {remoteRepos.map((r) => (
                      <SelectItem key={r.full_name} value={r.full_name}>
                        <span className="flex items-center gap-2">
                          {r.private ? (
                            <Lock className="h-3.5 w-3.5 shrink-0 text-muted" />
                          ) : (
                            <Unlock className="h-3.5 w-3.5 shrink-0 text-muted" />
                          )}
                          {r.full_name}
                          {r.description && (
                            <span className="ml-1 truncate text-xs text-muted">
                              — {r.description}
                            </span>
                          )}
                        </span>
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <p className="text-xs text-muted">
                  {remoteRepos.length} repositories accessible with this token.
                </p>
              </>
            ) : (
              <div className="space-y-2">
                <p className="text-xs text-muted">
                  No repositories found via this token. Enter manually:
                </p>
                <ManualOwnerRepoFields
                  owner={owner}
                  repo={repo}
                  onOwnerChange={setOwner}
                  onRepoChange={setRepo}
                  disabled={isBusy}
                />
              </div>
            )}
          </div>
        )}

        {/* Manual owner/repo fields — always shown in edit mode */}
        {isEditMode && (
          <ManualOwnerRepoFields
            owner={owner}
            repo={repo}
            onOwnerChange={setOwner}
            onRepoChange={setRepo}
            disabled={isBusy}
          />
        )}

        {/* Display Name */}
        <div className="space-y-2">
          <label htmlFor="display_name" className="text-sm font-medium">
            Display Name{" "}
            <span className="font-normal text-muted">(optional)</span>
          </label>
          <Input
            id="display_name"
            value={displayName}
            onChange={(e) => setDisplayName(e.target.value)}
            placeholder="Pipeline"
            disabled={isBusy}
          />
          <p className="text-xs text-muted">
            Friendly name shown in Pipeline. Defaults to owner/repo if blank.
          </p>
        </div>

        {/* Default Branch */}
        <div className="space-y-2">
          <label htmlFor="default_branch" className="text-sm font-medium">
            Default Branch
          </label>
          <Input
            id="default_branch"
            value={defaultBranch}
            onChange={(e) => setDefaultBranch(e.target.value)}
            placeholder="main"
            disabled={isBusy}
            required
          />
          <p className="text-xs text-muted">
            Auto-filled from Forgejo when a repository is selected.
          </p>
        </div>

        {/* Webhook Secret — edit mode only */}
        {showWebhookSecret && (
          <div className="space-y-2">
            <label
              htmlFor="webhook_secret"
              className="flex items-center gap-2 text-sm font-medium"
            >
              <KeyRound className="h-4 w-4 text-muted" />
              Webhook Secret
            </label>
            <Input
              id="webhook_secret"
              type="password"
              value={webhookSecret}
              onChange={(e) => setWebhookSecret(e.target.value)}
              placeholder="Leave blank to keep existing secret"
              disabled={isBusy}
              autoComplete="new-password"
            />
            <p className="text-xs text-muted">
              Secret used to verify incoming Forgejo webhook payloads. Set the
              same value in your Forgejo repository webhook settings. Leave
              blank to keep the current secret, or clear and save to remove it.
            </p>
          </div>
        )}
      </div>

      <div className="flex flex-col-reverse gap-3 border-t border-[color:var(--border)] pt-4 sm:flex-row sm:justify-end">
        <Button
          type="button"
          variant="outline"
          onClick={() => window.history.back()}
          disabled={isBusy}
        >
          Cancel
        </Button>
        <Button type="submit" disabled={isBusy}>
          {isBusy ? (
            <>
              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              Saving…
            </>
          ) : (
            submitLabel
          )}
        </Button>
      </div>
    </form>
  );
}

function ManualOwnerRepoFields({
  owner,
  repo,
  onOwnerChange,
  onRepoChange,
  disabled,
}: {
  owner: string;
  repo: string;
  onOwnerChange: (v: string) => void;
  onRepoChange: (v: string) => void;
  disabled: boolean;
}) {
  return (
    <div className="grid gap-4 sm:grid-cols-2">
      <div className="space-y-2">
        <label htmlFor="owner" className="text-sm font-medium">
          Owner
        </label>
        <Input
          id="owner"
          value={owner}
          onChange={(e) => onOwnerChange(e.target.value)}
          placeholder="myorg"
          disabled={disabled}
          required
        />
        <p className="text-xs text-muted">Username or organization name.</p>
      </div>
      <div className="space-y-2">
        <label htmlFor="repo" className="text-sm font-medium">
          Repository
        </label>
        <Input
          id="repo"
          value={repo}
          onChange={(e) => onRepoChange(e.target.value)}
          placeholder="my-project"
          disabled={disabled}
          required
        />
        <p className="text-xs text-muted">Repository name.</p>
      </div>
    </div>
  );
}

// Filter/toggle helpers re-exported for table usage
export function RepositoriesTableFilter({
  value,
  onChange,
}: {
  value: string;
  onChange: (value: string) => void;
}) {
  return (
    <input
      type="text"
      placeholder="Filter repositories…"
      value={value ?? ""}
      onChange={(e) => onChange(e.target.value)}
      className="h-9 w-[150px] rounded-xl border border-[color:var(--border)] bg-[color:var(--surface)] px-3 py-1 text-sm text-strong focus:border-[color:var(--accent)] focus:outline-none focus:ring-2 focus:ring-[color:var(--accent)] lg:w-[250px]"
    />
  );
}
