/**
 * Live-Projektdaten für den Abschnitt „Projekte".
 *
 * Quelle: GET /api/projects (contact-api-Container) – führt serverseitig alle
 * Gitea-Repositories mit den Hosting-Metadaten aus Appwrite zusammen.
 * Im Browser liegen dadurch weder Gitea-Token noch Appwrite-Key.
 */

export type ProjectCategory = "website" | "preview" | "template" | "app" | "internal" | "test";

/** live = öffentlich + einbettbar, online = öffentlich, protected = hinter Portal-Login */
export type ProjectState = "live" | "online" | "protected" | "hosted" | "repo" | "archived";

export type LiveProject = {
  id: string;
  name: string;
  repo: string;
  owner: string;
  description: string;
  category: ProjectCategory;
  state: ProjectState;
  url: string | null;
  repoUrl: string;
  language: string | null;
  sizeKb: number;
  updatedAt: string | null;
  archived: boolean;
  private: boolean;
  hosted: boolean;
  hostingStatus: string | null;
  subdomain: string | null;
  embeddable: boolean;
  reachable: boolean;
  gated: boolean;
  lastCommit: { message: string; author: string | null; date: string | null } | null;
};

export type ProjectsSnapshot = {
  generatedAt: string;
  total: number;
  counts: Partial<Record<ProjectCategory, number>>;
  embeddable: number;
  source: string;
  projects: LiveProject[];
};

const API_URL = import.meta.env.VITE_PROJECTS_API ?? "/api/projects";

export async function fetchProjects(signal?: AbortSignal): Promise<ProjectsSnapshot> {
  const res = await fetch(API_URL, { signal, headers: { Accept: "application/json" } });
  if (!res.ok) throw new Error(`Projekte konnten nicht geladen werden (HTTP ${res.status})`);
  const data = (await res.json()) as ProjectsSnapshot;
  if (!Array.isArray(data?.projects)) throw new Error("Unerwartete Antwort der Projekt-API");
  return data;
}

export const CATEGORY_LABELS: Record<ProjectCategory, string> = {
  website: "Kundenprojekte",
  preview: "Kunden-Previews",
  template: "Vorlagen",
  app: "Apps & Tools",
  internal: "Eigene Systeme",
  test: "Tests",
};

/** Reihenfolge der Filter-Chips */
export const CATEGORY_ORDER: ProjectCategory[] = [
  "website",
  "preview",
  "app",
  "template",
  "internal",
  "test",
];

export const STATE_LABELS: Record<ProjectState, string> = {
  live: "Live-Vorschau",
  online: "Öffentlich online",
  protected: "Login geschützt",
  hosted: "Gehostet",
  repo: "Nur Repository",
  archived: "Archiviert",
};

/**
 * Deterministische Akzentfarbe aus dem Repo-Namen – gleiche Kachel behält beim
 * Neuladen ihre Farbe, ohne dass wir Farben pflegen müssen.
 */
export function accentFor(seed: string): { hue: number; from: string; to: string } {
  let hash = 0;
  for (let i = 0; i < seed.length; i++) hash = (hash * 31 + seed.charCodeAt(i)) >>> 0;
  const hue = hash % 360;
  return {
    hue,
    from: `hsl(${hue} 70% 55% / 0.55)`,
    to: `hsl(${(hue + 48) % 360} 70% 45% / 0.18)`,
  };
}

/** Kürzel für die Platzhalter-Kachel (max. 2 Zeichen) */
export function monogram(name: string): string {
  const words = name
    .replace(/[^\p{L}\p{N}\s-]/gu, " ")
    .split(/[\s-]+/)
    .filter(Boolean);
  if (words.length === 0) return "··";
  if (words.length === 1) return words[0].slice(0, 2).toUpperCase();
  return (words[0][0] + words[1][0]).toUpperCase();
}
