import Database from "better-sqlite3";
import path from "path";
import type { SiteContent, TeamMember, RichListItem, VictoryItem } from "@/types/content";

const DB_PATH =
  process.env.DATABASE_PATH ||
  path.join(process.cwd(), "db", "blackheart.db");

let _db: Database.Database | null = null;

function getDb(): Database.Database {
  if (!_db) {
    _db = new Database(DB_PATH);
    _db.pragma("journal_mode = WAL");
    _db.pragma("foreign_keys = ON");
    initTables(_db);
  }
  return _db;
}

function initTables(db: Database.Database) {
  db.exec(`
    CREATE TABLE IF NOT EXISTS sections (
      key TEXT PRIMARY KEY,
      data TEXT NOT NULL,
      updated_at TEXT DEFAULT (datetime('now'))
    );

    CREATE TABLE IF NOT EXISTS team_members (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      role TEXT NOT NULL,
      image TEXT NOT NULL,
      instagram TEXT,
      description TEXT,
      experience TEXT,
      victories TEXT,
      education TEXT,
      sort_order INTEGER NOT NULL DEFAULT 0,
      created_at TEXT DEFAULT (datetime('now')),
      updated_at TEXT DEFAULT (datetime('now'))
    );
  `);

  // Migrate: add bio columns if missing
  const cols = db.prepare("PRAGMA table_info(team_members)").all() as { name: string }[];
  const colNames = new Set(cols.map((c) => c.name));
  if (!colNames.has("experience")) db.exec("ALTER TABLE team_members ADD COLUMN experience TEXT");
  if (!colNames.has("victories")) db.exec("ALTER TABLE team_members ADD COLUMN victories TEXT");
  if (!colNames.has("education")) db.exec("ALTER TABLE team_members ADD COLUMN education TEXT");
}

// --- Sections ---

export function getSection<T = unknown>(key: string): T | null {
  const db = getDb();
  const row = db.prepare("SELECT data FROM sections WHERE key = ?").get(key) as
    | { data: string }
    | undefined;
  return row ? (JSON.parse(row.data) as T) : null;
}

export function setSection(key: string, data: unknown): void {
  const db = getDb();
  db.prepare(
    `INSERT INTO sections (key, data, updated_at) VALUES (?, ?, datetime('now'))
     ON CONFLICT(key) DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`
  ).run(key, JSON.stringify(data));
}

// --- Team Members ---

interface TeamMemberRow {
  id: number;
  name: string;
  role: string;
  image: string;
  instagram: string | null;
  description: string | null;
  experience: string | null;
  victories: string | null;
  education: string | null;
  sort_order: number;
}

function parseJsonArray(val: string | null): string[] | undefined {
  if (!val) return undefined;
  try { const arr = JSON.parse(val); return Array.isArray(arr) && arr.length > 0 ? arr : undefined; } catch { return undefined; }
}

function parseRichList(val: string | null): RichListItem[] | undefined {
  if (!val) return undefined;
  try {
    const arr = JSON.parse(val);
    if (!Array.isArray(arr) || arr.length === 0) return undefined;
    // Handle both old string[] and new RichListItem[] formats
    return arr.map((item: string | RichListItem) =>
      typeof item === "string" ? { text: item } : item
    );
  } catch { return undefined; }
}

function parseVictories(val: string | null): VictoryItem[] | undefined {
  if (!val) return undefined;
  try {
    const arr = JSON.parse(val);
    if (!Array.isArray(arr) || arr.length === 0) return undefined;
    // Handle old string[], old RichListItem[], and new VictoryItem[] formats
    return arr.map((item: string | Record<string, unknown>) => {
      if (typeof item === "string") return { place: "", category: "", competition: item };
      if ("text" in item && !("competition" in item)) return { place: "", category: "", competition: item.text as string, image: item.image as string | undefined, link: item.link as string | undefined };
      return item as unknown as VictoryItem;
    });
  } catch { return undefined; }
}

export function getTeamMembers(): (TeamMember & { id: number })[] {
  const db = getDb();
  const rows = db
    .prepare("SELECT * FROM team_members ORDER BY sort_order ASC, id ASC")
    .all() as TeamMemberRow[];
  return rows.map((r) => ({
    id: r.id,
    name: r.name,
    role: r.role,
    image: r.image,
    instagram: r.instagram ?? undefined,
    description: r.description ?? undefined,
    experience: parseJsonArray(r.experience),
    victories: parseVictories(r.victories),
    education: parseRichList(r.education),
  }));
}

export function getTeamMember(
  id: number
): (TeamMember & { id: number }) | null {
  const db = getDb();
  const r = db
    .prepare("SELECT * FROM team_members WHERE id = ?")
    .get(id) as TeamMemberRow | undefined;
  if (!r) return null;
  return {
    id: r.id,
    name: r.name,
    role: r.role,
    image: r.image,
    instagram: r.instagram ?? undefined,
    description: r.description ?? undefined,
    experience: parseJsonArray(r.experience),
    victories: parseVictories(r.victories),
    education: parseRichList(r.education),
  };
}

export function createTeamMember(
  data: Omit<TeamMember, "id">
): number {
  const db = getDb();
  const maxOrder = db
    .prepare("SELECT COALESCE(MAX(sort_order), -1) as max FROM team_members")
    .get() as { max: number };
  const result = db
    .prepare(
      `INSERT INTO team_members (name, role, image, instagram, description, experience, victories, education, sort_order)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
    )
    .run(
      data.name,
      data.role,
      data.image,
      data.instagram ?? null,
      data.description ?? null,
      data.experience?.length ? JSON.stringify(data.experience) : null,
      data.victories?.length ? JSON.stringify(data.victories) : null,
      data.education?.length ? JSON.stringify(data.education) : null,
      maxOrder.max + 1
    );
  return result.lastInsertRowid as number;
}

export function updateTeamMember(
  id: number,
  data: Partial<Omit<TeamMember, "id">>
): void {
  const db = getDb();
  const fields: string[] = [];
  const values: unknown[] = [];

  if (data.name !== undefined) { fields.push("name = ?"); values.push(data.name); }
  if (data.role !== undefined) { fields.push("role = ?"); values.push(data.role); }
  if (data.image !== undefined) { fields.push("image = ?"); values.push(data.image); }
  if (data.instagram !== undefined) { fields.push("instagram = ?"); values.push(data.instagram || null); }
  if (data.description !== undefined) { fields.push("description = ?"); values.push(data.description || null); }
  if (data.experience !== undefined) { fields.push("experience = ?"); values.push(data.experience?.length ? JSON.stringify(data.experience) : null); }
  if (data.victories !== undefined) { fields.push("victories = ?"); values.push(data.victories?.length ? JSON.stringify(data.victories) : null); }
  if (data.education !== undefined) { fields.push("education = ?"); values.push(data.education?.length ? JSON.stringify(data.education) : null); }

  if (fields.length === 0) return;
  fields.push("updated_at = datetime('now')");
  values.push(id);

  db.prepare(`UPDATE team_members SET ${fields.join(", ")} WHERE id = ?`).run(
    ...values
  );
}

export function deleteTeamMember(id: number): void {
  const db = getDb();
  db.prepare("DELETE FROM team_members WHERE id = ?").run(id);
}

export function reorderTeamMembers(ids: number[]): void {
  const db = getDb();
  const stmt = db.prepare(
    "UPDATE team_members SET sort_order = ? WHERE id = ?"
  );
  const tx = db.transaction(() => {
    ids.forEach((id, index) => stmt.run(index, id));
  });
  tx();
}

// --- Full site content ---

const SECTION_KEYS = [
  "meta",
  "hero",
  "about",
  "classes",
  "faq",
  "pricing",
  "schedule",
  "contact",
] as const;

export function getSiteContent(): SiteContent | null {
  const db = getDb();
  const rows = db.prepare("SELECT key, data FROM sections").all() as {
    key: string;
    data: string;
  }[];

  if (rows.length === 0) return null;

  const sections: Record<string, unknown> = {};
  for (const row of rows) {
    sections[row.key] = JSON.parse(row.data);
  }

  // Merge team members from dedicated table
  const members = getTeamMembers();
  const teamSection = (sections.team as { title?: string }) || {};

  return {
    meta: sections.meta,
    hero: sections.hero,
    about: sections.about,
    classes: sections.classes,
    faq: sections.faq,
    pricing: sections.pricing,
    schedule: sections.schedule,
    contact: sections.contact,
    team: {
      title: teamSection.title || "",
      members: members.map(({ id, ...rest }) => rest),
    },
  } as SiteContent;
}

export function isDatabaseSeeded(): boolean {
  const db = getDb();
  const row = db
    .prepare("SELECT COUNT(*) as count FROM sections")
    .get() as { count: number };
  return row.count > 0;
}

export { SECTION_KEYS };
