/**
 * Document Assembly Service
 * Handles template-based document generation and clause assembly
 */

import {
  getDocumentTemplate,
  renderDocumentTemplate,
  extractTemplateVariables,
  getClause,
  listClauses,
  renderClause,
  createDocument,
  createDocumentVersion,
} from '@the-order/database';

export interface AssemblyOptions {
  template_id?: string;
  clause_ids?: string[];
  variables: Record<string, unknown>;
  title: string;
  type?: 'legal' | 'treaty' | 'finance' | 'history';
  matter_id?: string;
  save_document?: boolean;
}

export interface AssemblyResult {
  rendered: string;
  document_id?: string;
  template_used?: string;
  clauses_used?: string[];
}

/**
 * Assemble document from template
 */
export async function assembleFromTemplate(
  options: AssemblyOptions
): Promise<AssemblyResult> {
  if (!options.template_id) {
    throw new Error('Template ID is required');
  }

  const template = await getDocumentTemplate(options.template_id);
  if (!template) {
    throw new Error(`Template ${options.template_id} not found`);
  }

  // Render template with variables
  const rendered = renderDocumentTemplate(template, options.variables);

  if (options.save_document) {
    const document = await createDocument({
      title: options.title,
      type: options.type || 'legal',
      content: rendered,
    });

    await createDocumentVersion({
      document_id: document.id,
      version_number: 1,
      version_label: 'Generated from Template',
      content: rendered,
      change_type: 'created',
      change_summary: `Generated from template: ${template.name}`,
    });

    return {
      rendered,
      document_id: document.id,
      template_used: template.name,
    };
  }

  return {
    rendered,
    template_used: template.name,
  };
}

/**
 * Assemble document from clauses
 */
export async function assembleFromClauses(
  options: AssemblyOptions
): Promise<AssemblyResult> {
  if (!options.clause_ids || options.clause_ids.length === 0) {
    throw new Error('At least one clause ID is required');
  }

  // Fetch all clauses
  const clauses = await Promise.all(
    options.clause_ids.map((id) => getClause(id))
  );

  const missing = clauses.findIndex((c) => !c);
  if (missing !== -1) {
    throw new Error(`Clause not found: ${options.clause_ids[missing]}`);
  }

  // Render and combine clauses
  const rendered_parts = clauses.map((clause) =>
    renderClause(clause!, options.variables)
  );
  const rendered = rendered_parts.join('\n\n');

  if (options.save_document) {
    const document = await createDocument({
      title: options.title,
      type: options.type || 'legal',
      content: rendered,
    });

    await createDocumentVersion({
      document_id: document.id,
      version_number: 1,
      version_label: 'Assembled from Clauses',
      content: rendered,
      change_type: 'created',
      change_summary: `Assembled from ${clauses.length} clauses`,
    });

    return {
      rendered,
      document_id: document.id,
      clauses_used: clauses.map((c) => c!.name),
    };
  }

  return {
    rendered,
    clauses_used: clauses.map((c) => c!.name),
  };
}

/**
 * Preview template rendering
 */
export async function previewTemplate(
  template_id: string,
  variables: Record<string, unknown>
): Promise<{ rendered: string; variables_used: string[] }> {
  const template = await getDocumentTemplate(template_id);
  if (!template) {
    throw new Error(`Template ${template_id} not found`);
  }

  const rendered = renderDocumentTemplate(template, variables);
  const variables_used = extractTemplateVariables(template.template_content);

  return {
    rendered,
    variables_used,
  };
}

