// Datenmodel-Layer. Liest aus SQLite und formt die Werte in TS-Typen.
// Wird sowohl von den Server Components (Public Routes) als auch von der
// Admin-API genutzt.

import type Database from "better-sqlite3";

export type Locale = "de" | "en";

export type ProfileLink = {
  label: string;
  href: string;
  kind: string; // "git" | "service" | "external" | "social" | ...
};

export type Profile = {
  handle: string;
  realName: string;
  role: string;
  location: string;
  bio: string;            // je nach Locale
  facts: string[];
  links: ProfileLink[];
  updatedAt: string;
};

type ProfileRow = {
  id: number;
  handle: string;
  real_name: string;
  role: string;
  location: string;
  bio_de: string;
  bio_en: string;
  facts_de: string;
  facts_en: string;
  links_json: string;
  updated_at: string;
};

function safeJsonArray(s: string): string[] {
  try {
    const v = JSON.parse(s);
    if (Array.isArray(v) && v.every((x) => typeof x === "string")) return v;
    return [];
  } catch {
    return [];
  }
}

function safeJsonLinks(s: string): ProfileLink[] {
  try {
    const v = JSON.parse(s);
    if (Array.isArray(v)) return v as ProfileLink[];
    return [];
  } catch {
    return [];
  }
}

export function getProfile(db: Database.Database, locale: Locale): Profile {
  const row = db.prepare("SELECT * FROM profile WHERE id = 1").get() as ProfileRow | undefined;
  if (!row) {
    return {
      handle: "eldov",
      realName: "Jan Wagner",
      role: "Self-Hoster · Bot-Bauer · Privatprojekte",
      location: "Deutschland",
      bio: "",
      facts: [],
      links: [],
      updatedAt: new Date().toISOString(),
    };
  }
  return {
    handle: row.handle,
    realName: row.real_name,
    role: row.role,
    location: row.location,
    bio: locale === "de" ? row.bio_de : row.bio_en,
    facts: safeJsonArray(locale === "de" ? row.facts_de : row.facts_en),
    links: safeJsonLinks(row.links_json),
    updatedAt: row.updated_at,
  };
}

export type Project = {
  slug: string;
  number: string;
  status: string;
  category: string;
  stack: string;
  href: string | null;
  featured: boolean;
  summary: string;
  body: string;
  stance: string;
  sortIndex: number;
  updatedAt: string;
};

type ProjectRow = {
  slug: string;
  number: string;
  status: string;
  category: string;
  stack: string;
  href: string | null;
  featured: number;
  summary_de: string;
  summary_en: string;
  body_de: string;
  body_en: string;
  stance_de: string;
  stance_en: string;
  sort_index: number;
  created_at: string;
  updated_at: string;
};

function rowToProject(row: ProjectRow, locale: Locale): Project {
  return {
    slug: row.slug,
    number: row.number,
    status: row.status,
    category: row.category,
    stack: row.stack,
    href: row.href,
    featured: row.featured === 1,
    summary: locale === "de" ? row.summary_de : row.summary_en,
    body: locale === "de" ? row.body_de : row.body_en,
    stance: locale === "de" ? row.stance_de : row.stance_en,
    sortIndex: row.sort_index,
    updatedAt: row.updated_at,
  };
}

export function listProjects(db: Database.Database, locale: Locale): Project[] {
  const rows = db
    .prepare("SELECT * FROM projects ORDER BY sort_index ASC, number ASC")
    .all() as ProjectRow[];
  return rows.map((r) => rowToProject(r, locale));
}

export function listFeaturedProjects(db: Database.Database, locale: Locale): Project[] {
  const rows = db
    .prepare(
      "SELECT * FROM projects WHERE featured = 1 ORDER BY sort_index ASC, number ASC"
    )
    .all() as ProjectRow[];
  return rows.map((r) => rowToProject(r, locale));
}

export function getProject(db: Database.Database, locale: Locale, slug: string): Project | null {
  const row = db
    .prepare("SELECT * FROM projects WHERE slug = ?")
    .get(slug) as ProjectRow | undefined;
  if (!row) return null;
  return rowToProject(row, locale);
}

// --- Admin-Schreiboperationen ---

export type ProfilePatch = {
  handle?: string;
  realName?: string;
  role?: string;
  location?: string;
  bioDe?: string;
  bioEn?: string;
  factsDe?: string[];
  factsEn?: string[];
  links?: ProfileLink[];
};

export function updateProfile(db: Database.Database, patch: ProfilePatch): void {
  const fields: string[] = [];
  const values: Record<string, unknown> = { id: 1 };
  if (patch.handle !== undefined) { fields.push("handle = @handle"); values.handle = patch.handle; }
  if (patch.realName !== undefined) { fields.push("real_name = @realName"); values.realName = patch.realName; }
  if (patch.role !== undefined) { fields.push("role = @role"); values.role = patch.role; }
  if (patch.location !== undefined) { fields.push("location = @location"); values.location = patch.location; }
  if (patch.bioDe !== undefined) { fields.push("bio_de = @bioDe"); values.bioDe = patch.bioDe; }
  if (patch.bioEn !== undefined) { fields.push("bio_en = @bioEn"); values.bioEn = patch.bioEn; }
  if (patch.factsDe !== undefined) { fields.push("facts_de = @factsDe"); values.factsDe = JSON.stringify(patch.factsDe); }
  if (patch.factsEn !== undefined) { fields.push("facts_en = @factsEn"); values.factsEn = JSON.stringify(patch.factsEn); }
  if (patch.links !== undefined) { fields.push("links_json = @linksJson"); values.linksJson = JSON.stringify(patch.links); }
  if (fields.length === 0) return;
  fields.push("updated_at = datetime('now')");
  db.prepare(`UPDATE profile SET ${fields.join(", ")} WHERE id = @id`).run(values);
}

export type ProjectPatch = {
  slug?: string;
  number?: string;
  status?: string;
  category?: string;
  stack?: string;
  href?: string | null;
  featured?: boolean;
  summaryDe?: string;
  summaryEn?: string;
  bodyDe?: string;
  bodyEn?: string;
  stanceDe?: string;
  stanceEn?: string;
  sortIndex?: number;
};

export function insertProject(db: Database.Database, patch: Required<Pick<ProjectPatch, "slug">> & ProjectPatch): void {
  if (!patch.slug) throw new Error("slug ist erforderlich");
  const exists = db.prepare("SELECT 1 FROM projects WHERE slug = ?").get(patch.slug);
  if (exists) throw new Error(`Slug '${patch.slug}' existiert bereits`);
  db.prepare(
    `INSERT INTO projects
       (slug, number, status, category, stack, href, featured,
        summary_de, summary_en, body_de, body_en, stance_de, stance_en, sort_index)
     VALUES
       (@slug, @number, @status, @category, @stack, @href, @featured,
        @summaryDe, @summaryEn, @bodyDe, @bodyEn, @stanceDe, @stanceEn, @sortIndex)`
  ).run({
    slug: patch.slug,
    number: patch.number ?? "—",
    status: patch.status ?? "Draft",
    category: patch.category ?? "Sonstiges",
    stack: patch.stack ?? "",
    href: patch.href ?? null,
    featured: patch.featured ? 1 : 0,
    summaryDe: patch.summaryDe ?? "",
    summaryEn: patch.summaryEn ?? "",
    bodyDe: patch.bodyDe ?? "",
    bodyEn: patch.bodyEn ?? "",
    stanceDe: patch.stanceDe ?? "",
    stanceEn: patch.stanceEn ?? "",
    sortIndex: patch.sortIndex ?? 0,
  });
}

export function updateProject(db: Database.Database, slug: string, patch: ProjectPatch): void {
  const fields: string[] = [];
  const values: Record<string, unknown> = { slug };
  if (patch.slug !== undefined && patch.slug !== slug) {
    const exists = db.prepare("SELECT 1 FROM projects WHERE slug = ?").get(patch.slug);
    if (exists) throw new Error(`Slug '${patch.slug}' existiert bereits`);
    fields.push("slug = @newSlug"); values.newSlug = patch.slug;
  }
  if (patch.number !== undefined) { fields.push("number = @number"); values.number = patch.number; }
  if (patch.status !== undefined) { fields.push("status = @status"); values.status = patch.status; }
  if (patch.category !== undefined) { fields.push("category = @category"); values.category = patch.category; }
  if (patch.stack !== undefined) { fields.push("stack = @stack"); values.stack = patch.stack; }
  if (patch.href !== undefined) { fields.push("href = @href"); values.href = patch.href; }
  if (patch.featured !== undefined) { fields.push("featured = @featured"); values.featured = patch.featured ? 1 : 0; }
  if (patch.summaryDe !== undefined) { fields.push("summary_de = @summaryDe"); values.summaryDe = patch.summaryDe; }
  if (patch.summaryEn !== undefined) { fields.push("summary_en = @summaryEn"); values.summaryEn = patch.summaryEn; }
  if (patch.bodyDe !== undefined) { fields.push("body_de = @bodyDe"); values.bodyDe = patch.bodyDe; }
  if (patch.bodyEn !== undefined) { fields.push("body_en = @bodyEn"); values.bodyEn = patch.bodyEn; }
  if (patch.stanceDe !== undefined) { fields.push("stance_de = @stanceDe"); values.stanceDe = patch.stanceDe; }
  if (patch.stanceEn !== undefined) { fields.push("stance_en = @stanceEn"); values.stanceEn = patch.stanceEn; }
  if (patch.sortIndex !== undefined) { fields.push("sort_index = @sortIndex"); values.sortIndex = patch.sortIndex; }
  if (fields.length === 0) return;
  fields.push("updated_at = datetime('now')");
  const result = db.prepare(`UPDATE projects SET ${fields.join(", ")} WHERE slug = @slug`).run(values);
  if (result.changes === 0) throw new Error(`Projekt '${slug}' nicht gefunden`);
}

export function deleteProject(db: Database.Database, slug: string): void {
  const result = db.prepare("DELETE FROM projects WHERE slug = ?").run(slug);
  if (result.changes === 0) throw new Error(`Projekt '${slug}' nicht gefunden`);
}
