/**
 * Document Management Routes
 * CRUD operations for documents with versioning
 */

import { FastifyInstance } from 'fastify';
import {
  createDocument,
  updateDocument,
  getDocumentById,
  listDocuments,
} from '@the-order/database';
import { authenticateJWT, requireRole } from '@the-order/shared';
import {
  createDocumentVersion,
  getDocumentVersions,
  getLatestDocumentVersion,
} from '@the-order/database';
import { createDocumentAuditLog } from '@the-order/database';
import { checkoutDocument, checkinDocument, getDocumentCheckout } from '@the-order/database';

export async function registerDocumentRoutes(server: FastifyInstance): Promise<void> {
  // Create document
  server.post(
    '/documents',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'attorney', 'legal_staff')],
      schema: {
        body: {
          type: 'object',
          required: ['title', 'type'],
          properties: {
            title: { type: 'string' },
            type: { type: 'string', enum: ['legal', 'treaty', 'finance', 'history'] },
            content: { type: 'string' },
            fileUrl: { type: 'string' },
            matter_id: { type: 'string' },
            relationship_type: { type: 'string' },
          },
        },
        tags: ['documents'],
      },
    },
    async (request, reply) => {
      const body = request.body as {
        title: string;
        type: string;
        content?: string;
        fileUrl?: string;
        matter_id?: string;
        relationship_type?: string;
      };
      const user = (request as any).user;

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

      // Create initial version
      await createDocumentVersion({
        document_id: document.id,
        version_number: 1,
        version_label: 'Initial Version',
        content: body.content,
        file_url: body.fileUrl,
        change_type: 'created',
        created_by: user?.id,
      });

      // 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
        );
      }

      // Audit log
      await createDocumentAuditLog({
        document_id: document.id,
        action: 'created',
        performed_by: user?.id,
        ip_address: request.ip,
        user_agent: request.headers['user-agent'],
      });

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

  // Get document by ID
  server.get(
    '/documents/:id',
    {
      preHandler: [authenticateJWT],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        tags: ['documents'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const user = (request as any).user;

      const document = await getDocumentById(id);
      if (!document) {
        return reply.code(404).send({ error: 'Document not found' });
      }

      // Audit log
      await createDocumentAuditLog({
        document_id: id,
        action: 'viewed',
        performed_by: user?.id,
        ip_address: request.ip,
        user_agent: request.headers['user-agent'],
      });

      return reply.send(document);
    }
  );

  // List documents
  server.get(
    '/documents',
    {
      preHandler: [authenticateJWT],
      schema: {
        querystring: {
          type: 'object',
          properties: {
            type: { type: 'string' },
            matter_id: { type: 'string' },
            limit: { type: 'number' },
            offset: { type: 'number' },
            search: { type: 'string' },
          },
        },
        tags: ['documents'],
      },
    },
    async (request, reply) => {
      const query = request.query as {
        type?: string;
        matter_id?: string;
        limit?: number;
        offset?: number;
        search?: string;
      };

      const documents = await listDocuments(
        query.type as any,
        query.limit || 100,
        query.offset || 0
      );

      return reply.send({ documents, total: documents.length });
    }
  );

  // Update document
  server.patch(
    '/documents/:id',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'attorney', 'legal_staff')],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        body: {
          type: 'object',
          properties: {
            title: { type: 'string' },
            content: { type: 'string' },
            fileUrl: { type: 'string' },
            change_summary: { type: 'string' },
          },
        },
        tags: ['documents'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const body = request.body as {
        title?: string;
        content?: string;
        fileUrl?: string;
        change_summary?: string;
      };
      const user = (request as any).user;

      // Check if document is checked out
      const checkout = await getDocumentCheckout(id);
      if (checkout && checkout.checked_out_by !== user?.id) {
        return reply.code(409).send({
          error: 'Document is checked out by another user',
          checked_out_by: checkout.checked_out_by,
        });
      }

      const document = await updateDocument(id, {
        title: body.title,
        content: body.content,
        fileUrl: body.fileUrl,
      });

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

      // Create new version
      const latestVersion = await getLatestDocumentVersion(id);
      await createDocumentVersion({
        document_id: id,
        version_number: (latestVersion?.version_number || 0) + 1,
        content: body.content,
        file_url: body.fileUrl,
        change_summary: body.change_summary,
        change_type: 'modified',
        created_by: user?.id,
      });

      // Audit log
      await createDocumentAuditLog({
        document_id: id,
        action: 'modified',
        performed_by: user?.id,
        ip_address: request.ip,
        user_agent: request.headers['user-agent'],
        details: { change_summary: body.change_summary },
      });

      return reply.send(document);
    }
  );

  // Checkout document
  server.post(
    '/documents/:id/checkout',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'attorney', 'legal_staff')],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        body: {
          type: 'object',
          properties: {
            duration_hours: { type: 'number' },
            notes: { type: 'string' },
          },
        },
        tags: ['documents'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const body = request.body as { duration_hours?: number; notes?: string };
      const user = (request as any).user;

      try {
        const checkout = await checkoutDocument({
          document_id: id,
          checked_out_by: user.id,
          duration_hours: body.duration_hours,
          notes: body.notes,
        });

        await createDocumentAuditLog({
          document_id: id,
          action: 'checked_out',
          performed_by: user.id,
        });

        return reply.send(checkout);
      } catch (error: any) {
        return reply.code(409).send({ error: error.message });
      }
    }
  );

  // Checkin document
  server.post(
    '/documents/:id/checkin',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'attorney', 'legal_staff')],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        tags: ['documents'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const user = (request as any).user;

      try {
        const checkedIn = await checkinDocument(id, user.id);
        if (!checkedIn) {
          return reply.code(404).send({ error: 'Document is not checked out' });
        }

        await createDocumentAuditLog({
          document_id: id,
          action: 'checked_in',
          performed_by: user.id,
        });

        return reply.send({ success: true });
      } catch (error: any) {
        return reply.code(409).send({ error: error.message });
      }
    }
  );

  // Get document checkout status
  server.get(
    '/documents/:id/checkout',
    {
      preHandler: [authenticateJWT],
      schema: {
        params: {
          type: 'object',
          properties: {
            id: { type: 'string' },
          },
        },
        tags: ['documents'],
      },
    },
    async (request, reply) => {
      const { id } = request.params as { id: string };
      const checkout = await getDocumentCheckout(id);
      return reply.send(checkout || { checked_out: false });
    }
  );
}

