/**
 * Document Template Routes
 * Template management and rendering
 */

import { FastifyInstance } from 'fastify';
import {
  createDocumentTemplate,
  getDocumentTemplate,
  getDocumentTemplateByName,
  listDocumentTemplates,
  updateDocumentTemplate,
  createTemplateVersion,
  renderDocumentTemplate,
  extractTemplateVariables,
} from '@the-order/database';
import { authenticateJWT, requireRole } from '@the-order/shared';

export async function registerTemplateRoutes(server: FastifyInstance): Promise<void> {
  // Create template
  server.post(
    '/templates',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'attorney', 'legal_staff')],
      schema: {
        body: {
          type: 'object',
          required: ['name', 'template_content'],
          properties: {
            name: { type: 'string' },
            description: { type: 'string' },
            category: { type: 'string' },
            subcategory: { type: 'string' },
            template_content: { type: 'string' },
            variables: { type: 'object' },
            metadata: { type: 'object' },
            is_public: { type: 'boolean' },
            tags: { type: 'array', items: { type: 'string' } },
          },
        },
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const body = request.body as any;
      const user = (request as any).user;

      const template = await createDocumentTemplate({
        name: body.name,
        description: body.description,
        category: body.category,
        subcategory: body.subcategory,
        template_content: body.template_content,
        variables: body.variables,
        metadata: body.metadata,
        is_public: body.is_public || false,
        tags: body.tags,
        created_by: user?.id,
      });

      return reply.code(201).send(template);
    }
  );

  // Get template by ID
  server.get(
    '/templates/:id',
    {
      preHandler: [authenticateJWT],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const template = await getDocumentTemplate(id);
      if (!template) {
        return reply.code(404).send({ error: 'Template not found' });
      }
      return reply.send(template);
    }
  );

  // Get template by name
  server.get(
    '/templates/name/:name',
    {
      preHandler: [authenticateJWT],
      schema: {
        params: {
          type: 'object',
          properties: {
            name: { type: 'string' },
          },
        },
        querystring: {
          type: 'object',
          properties: {
            version: { type: 'number' },
          },
        },
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { name } = request.params as { name: string };
      const { version } = request.query as { version?: number };
      const template = await getDocumentTemplateByName(name, version);
      if (!template) {
        return reply.code(404).send({ error: 'Template not found' });
      }
      return reply.send(template);
    }
  );

  // List templates
  server.get(
    '/templates',
    {
      preHandler: [authenticateJWT],
      schema: {
        querystring: {
          type: 'object',
          properties: {
            category: { type: 'string' },
            is_active: { type: 'boolean' },
            is_public: { type: 'boolean' },
            search: { type: 'string' },
            limit: { type: 'number' },
            offset: { type: 'number' },
          },
        },
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const query = request.query as any;
      const templates = await listDocumentTemplates(
        {
          category: query.category,
          is_active: query.is_active,
          is_public: query.is_public,
          search: query.search,
        },
        query.limit || 100,
        query.offset || 0
      );
      return reply.send({ templates });
    }
  );

  // Update template
  server.patch(
    '/templates/:id',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'attorney')],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        body: {
          type: 'object',
          properties: {
            description: { type: 'string' },
            template_content: { type: 'string' },
            variables: { type: 'object' },
            is_active: { type: 'boolean' },
            tags: { type: 'array', items: { type: 'string' } },
          },
        },
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const body = request.body as any;
      const template = await updateDocumentTemplate(id, body);
      if (!template) {
        return reply.code(404).send({ error: 'Template not found' });
      }
      return reply.send(template);
    }
  );

  // Create template version
  server.post(
    '/templates/:id/version',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'attorney')],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        body: {
          type: 'object',
          properties: {
            template_content: { type: 'string' },
            description: { type: 'string' },
          },
        },
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const body = request.body as any;
      const template = await createTemplateVersion(id, body);
      return reply.send(template);
    }
  );

  // Render template
  server.post(
    '/templates/:id/render',
    {
      preHandler: [authenticateJWT],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        body: {
          type: 'object',
          required: ['variables'],
          properties: {
            variables: { type: 'object' },
          },
        },
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const { variables } = request.body as { variables: Record<string, unknown> };

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

      const rendered = renderDocumentTemplate(template, variables);
      return reply.send({ rendered });
    }
  );

  // Extract variables from template
  server.get(
    '/templates/:id/variables',
    {
      preHandler: [authenticateJWT],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const template = await getDocumentTemplate(id);
      if (!template) {
        return reply.code(404).send({ error: 'Template not found' });
      }

      const variables = extractTemplateVariables(template.template_content);
      return reply.send({ variables });
    }
  );
}

