/**
 * Changelog repository — Cosmos DB CRUD.
 */

import { getRegisteredContainer } from '@bytelyst/cosmos';
import crypto from 'node:crypto';
import type { ChangelogEntryDoc, CreateChangelogInput, UpdateChangelogInput } from './types.js';

function getContainer() {
  return getRegisteredContainer('changelog');
}

export async function createEntry(
  productId: string,
  input: CreateChangelogInput
): Promise<ChangelogEntryDoc> {
  const now = new Date().toISOString();
  const doc: ChangelogEntryDoc = {
    id: `cl_${crypto.randomUUID()}`,
    productId,
    version: input.version,
    title: input.title,
    body: input.body ?? '',
    categories: input.categories,
    published: input.published ?? false,
    publishedAt: input.published ? now : null,
    createdAt: now,
    updatedAt: now,
  };
  await getContainer().items.create(doc);
  return doc;
}

export async function getEntry(id: string, productId: string): Promise<ChangelogEntryDoc | null> {
  try {
    const { resource } = await getContainer().item(id, productId).read<ChangelogEntryDoc>();
    return resource ?? null;
  } catch {
    return null;
  }
}

export async function listEntries(
  productId: string,
  publishedOnly: boolean = false
): Promise<ChangelogEntryDoc[]> {
  const conditions = ['c.productId = @pid'];
  if (publishedOnly) conditions.push('c.published = true');

  const { resources } = await getContainer()
    .items.query<ChangelogEntryDoc>({
      query: `SELECT * FROM c WHERE ${conditions.join(' AND ')} ORDER BY c.createdAt DESC`,
      parameters: [{ name: '@pid', value: productId }],
    })
    .fetchAll();
  return resources;
}

export async function updateEntry(
  id: string,
  productId: string,
  updates: UpdateChangelogInput
): Promise<ChangelogEntryDoc | null> {
  const existing = await getEntry(id, productId);
  if (!existing) return null;

  const now = new Date().toISOString();
  const updated: ChangelogEntryDoc = {
    ...existing,
    ...updates,
    updatedAt: now,
  };

  // Set publishedAt on first publish
  if (updates.published === true && !existing.publishedAt) {
    updated.publishedAt = now;
  }
  // Clear publishedAt on unpublish
  if (updates.published === false) {
    updated.publishedAt = null;
  }

  await getContainer().item(id, productId).replace(updated);
  return updated;
}

export async function deleteEntry(id: string, productId: string): Promise<boolean> {
  try {
    await getContainer().item(id, productId).delete();
    return true;
  } catch {
    return false;
  }
}
