/**
 * Credential template management endpoints
 */

import { FastifyInstance } from 'fastify';
import {
  createCredentialTemplate,
  getCredentialTemplate,
  getCredentialTemplateByName,
  listCredentialTemplates,
  updateCredentialTemplate,
  createTemplateVersion,
  renderCredentialFromTemplate,
} 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', 'issuer')],
      schema: {
        body: {
          type: 'object',
          required: ['name', 'credential_type', 'template_data'],
          properties: {
            name: { type: 'string' },
            description: { type: 'string' },
            credential_type: { type: 'array', items: { type: 'string' } },
            template_data: { type: 'object' },
            version: { type: 'number' },
            is_active: { type: 'boolean' },
          },
        },
        description: 'Create a credential template',
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const body = request.body as {
        name: string;
        description?: string;
        credential_type: string[];
        template_data: Record<string, unknown>;
        version?: number;
        is_active?: boolean;
      };
      const user = (request as any).user;

      const template = await createCredentialTemplate({
        name: body.name,
        description: body.description,
        credential_type: body.credential_type,
        template_data: body.template_data,
        version: body.version || 1,
        is_active: body.is_active !== false,
        created_by: user?.id || null,
      });

      return reply.send(template);
    }
  );

  // Get template by ID
  server.get(
    '/templates/:id',
    {
      preHandler: [authenticateJWT],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        description: 'Get credential template by ID',
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const template = await getCredentialTemplate(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' },
          },
        },
        description: 'Get credential template by name',
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { name } = request.params as { name: string };
      const { version } = request.query as { version?: number };
      const template = await getCredentialTemplateByName(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: {
            activeOnly: { type: 'boolean' },
            limit: { type: 'number' },
            offset: { type: 'number' },
          },
        },
        description: 'List credential templates',
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { activeOnly, limit, offset } = request.query as {
        activeOnly?: boolean;
        limit?: number;
        offset?: number;
      };

      const templates = await listCredentialTemplates(
        activeOnly !== false,
        limit || 100,
        offset || 0
      );

      return reply.send({ templates });
    }
  );

  // Update template
  server.patch(
    '/templates/:id',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'issuer')],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        body: {
          type: 'object',
          properties: {
            description: { type: 'string' },
            template_data: { type: 'object' },
            is_active: { type: 'boolean' },
          },
        },
        description: 'Update credential template',
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const body = request.body as {
        description?: string;
        template_data?: Record<string, unknown>;
        is_active?: boolean;
      };

      const template = await updateCredentialTemplate(id, body);

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

      return reply.send(template);
    }
  );

  // Create new template version
  server.post(
    '/templates/:id/version',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'issuer')],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        body: {
          type: 'object',
          properties: {
            template_data: { type: 'object' },
            description: { type: 'string' },
          },
        },
        description: 'Create new version of credential template',
        tags: ['templates'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const body = request.body as {
        template_data?: Record<string, unknown>;
        description?: string;
      };

      const template = await createTemplateVersion(id, body);
      return reply.send(template);
    }
  );

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

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

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

