/**
 * Document Assembly Routes
 * Template-based document generation and assembly
 */

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

export async function registerAssemblyRoutes(server: FastifyInstance): Promise<void> {
  // Generate document from template
  server.post(
    '/assembly/generate',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'attorney', 'legal_staff')],
      schema: {
        body: {
          type: 'object',
          required: ['template_id', 'variables', 'title'],
          properties: {
            template_id: { type: 'string' },
            variables: { type: 'object' },
            title: { type: 'string' },
            type: { type: 'string', enum: ['legal', 'treaty', 'finance', 'history'] },
            matter_id: { type: 'string' },
            relationship_type: { type: 'string' },
            save_document: { type: 'boolean' },
          },
        },
        tags: ['assembly'],
      },
    },
    async (request, reply) => {
      const body = request.body as {
        template_id: string;
        variables: Record<string, unknown>;
        title: string;
        type?: string;
        matter_id?: string;
        relationship_type?: string;
        save_document?: boolean;
      };
      const user = (request as any).user;

      const template = await getDocumentTemplate(body.template_id);
      if (!template) {
        return reply.code(404).send({ error: 'Template not found' });
      }

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

      if (body.save_document) {
        // Create document from rendered template
        const document = await createDocument({
          title: body.title,
          type: (body.type || 'legal') as 'legal' | 'treaty' | 'finance' | 'history',
          content: rendered,
        });

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

        // Link to matter if provided
        if (body.matter_id && body.relationship_type) {
          const { linkDocumentToMatter } = await import('@the-order/database');
          await linkDocumentToMatter(body.matter_id, document.id, body.relationship_type);
        }

        return reply.code(201).send({
          document,
          rendered,
          template_used: template.name,
        });
      }

      return reply.send({ rendered, template_used: template.name });
    }
  );

  // Preview template rendering
  server.post(
    '/assembly/preview',
    {
      preHandler: [authenticateJWT],
      schema: {
        body: {
          type: 'object',
          required: ['template_id', 'variables'],
          properties: {
            template_id: { type: 'string' },
            variables: { type: 'object' },
          },
        },
        tags: ['assembly'],
      },
    },
    async (request, reply) => {
      const { template_id, variables } = request.body as {
        template_id: string;
        variables: Record<string, unknown>;
      };

      const template = await getDocumentTemplate(template_id);
      if (!template) {
        return reply.code(404).send({ error: 'Template not found' });
      }

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

      return reply.send({
        rendered,
        variables_used,
        template_name: template.name,
      });
    }
  );

  // Assemble document from multiple clauses
  server.post(
    '/assembly/from-clauses',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'attorney', 'legal_staff')],
      schema: {
        body: {
          type: 'object',
          required: ['clause_ids', 'title'],
          properties: {
            clause_ids: { type: 'array', items: { type: 'string' } },
            variables: { type: 'object' },
            title: { type: 'string' },
            type: { type: 'string' },
            matter_id: { type: 'string' },
            save_document: { type: 'boolean' },
          },
        },
        tags: ['assembly'],
      },
    },
    async (request, reply) => {
      const body = request.body as {
        clause_ids: string[];
        variables?: Record<string, unknown>;
        title: string;
        type?: string;
        matter_id?: string;
        save_document?: boolean;
      };
      const user = (request as any).user;

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

      const missing = clauses.findIndex((c) => !c);
      if (missing !== -1) {
        return reply.code(404).send({
          error: `Clause not found: ${body.clause_ids[missing]}`,
        });
      }

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

      if (body.save_document) {
        const document = await createDocument({
          title: body.title,
          type: (body.type || 'legal') as 'legal' | 'treaty' | 'finance' | 'history',
          content: rendered,
        });

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

        if (body.matter_id) {
          const { linkDocumentToMatter } = await import('@the-order/database');
          await linkDocumentToMatter(body.matter_id, document.id, 'draft');
        }

        return reply.code(201).send({
          document,
          rendered,
          clauses_used: clauses.map((c) => c!.name),
        });
      }

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

