import { z } from "zod";
import {
  createHybridActionApiRoute,
  createHybridLoaderApiRoute,
} from "~/services/routeBuilders/apiBuilder.server";
import { json } from "@remix-run/node";
import { apiCors } from "~/utils/apiCors";
import { triggerSpaceSummary } from "~/trigger/spaces/space-summary";
import { SpaceService } from "~/services/space.server";
import { addToQueue } from "~/lib/ingest.server";
import { EpisodeType ,type  DocumentNode } from "@core/types";
import * as crypto from "crypto";
import { saveDocument } from "~/services/graphModels/document";
import { logger } from "~/services/logger.service";
import { prisma } from "~/db.server";

const spaceService = new SpaceService();

// Schema for space ID parameter
const SpaceParamsSchema = z.object({
  spaceId: z.string(),
});

const { action } = createHybridActionApiRoute(
  {
    params: SpaceParamsSchema,
    allowJWT: true,
    authorization: {
      action: "manage",
    },
    corsStrategy: "all",
  },
  async ({ authentication, params, request }) => {
    const userId = authentication.userId;
    const { spaceId } = params;

    if (request.method === "PUT") {
      try {
        // Get the markdown content from request body
        const markdownContent = await request.text();
        
        if (!markdownContent || markdownContent.trim().length === 0) {
          return json({ error: "Empty summary content provided" }, { status: 400 });
        }

        // Get space details
        const space = await spaceService.getSpace(spaceId, userId);
        if (!space) {
          return json({ error: "Space not found" }, { status: 404 });
        }

        // Create updated summary document
        const documentUuid = await createUpdatedSummaryDocument(
          spaceId,
          userId,
          space.name,
          markdownContent
        );

        // Queue document for ingestion
        await queueSummaryDocumentIngestion(
          documentUuid,
          spaceId,
          userId,
          markdownContent
        );

        logger.info(`Updated space summary document ${documentUuid} for space ${spaceId}`);

        return json({
          success: true,
          summary: {
            documentId: documentUuid,
            spaceId,
            updatedAt: new Date().toISOString(),
          },
        });
      } catch (error) {
        logger.error(`Error updating space summary for ${spaceId}:`, error as Record<string, unknown>);
        return json(
          { error: "Failed to update space summary" },
          { status: 500 }
        );
      }
    }

    if (request.method === "POST") {
      try {
        // Get space details first
        const space = await spaceService.getSpace(spaceId, userId);
        if (!space) {
          return json({ error: "Space not found" }, { status: 404 });
        }

        // Get workspace for user
        const user = await prisma.user.findFirst({
          where: { id: userId },
          include: { Workspace: true },
        });

        if (!user?.Workspace?.id) {
          return json(
            { error: "Workspace not found" },
            { status: 400 }
          );
        }

        // Trigger space summary generation using existing infrastructure
        const result = await triggerSpaceSummary({
          userId,
          workspaceId: user.Workspace.id,
          spaceId,
          triggerSource: "manual",
        });

        return json({
          success: true,
          summary: {
            taskId: result.id,
            spaceId,
            triggeredAt: new Date().toISOString(),
            status: "processing",
          },
        });
      } catch (error) {
        logger.error(`Error generating space summary for ${spaceId}:`, error as Record<string, unknown>);
        return json(
          { error: "Failed to generate space summary" },
          { status: 500 }
        );
      }
    }

    return json({ error: "Method not allowed" }, { status: 405 });
  },
);

const loader = createHybridLoaderApiRoute(
  {
    allowJWT: true,
    params: SpaceParamsSchema,
    corsStrategy: "all",
    findResource: async () => 1,
  },
  async ({ authentication, request, params }) => {
    if (request.method.toUpperCase() === "OPTIONS") {
      return apiCors(request, json({}));
    }

    try {
      // Get space details
      const space = await spaceService.getSpace(
        params.spaceId,
        authentication.userId,
      );

      if (!space) {
        return json({ error: "Space not found" }, { status: 404 });
      }

      // Return current space summary information
      return json({
        space: {
          id: space.uuid,
          name: space.name,
          description: space.description,
          summary: space.summary,
          themes: space.themes,
        },
      });
    } catch (error) {
      logger.error(`Error fetching space summary for ${params.spaceId}:`, error as Record<string, unknown>);
      return json(
        { error: "Failed to fetch space summary" },
        { status: 500 }
      );
    }
  },
);

/**
 * Create an updated summary document
 */
async function createUpdatedSummaryDocument(
  spaceId: string,
  userId: string,
  spaceName: string,
  markdownContent: string
): Promise<string> {
  const documentUuid = crypto.randomUUID();
  const contentHash = crypto.createHash('sha256').update(markdownContent).digest('hex');
  
  const document: DocumentNode = {
    uuid: documentUuid,
    title: `${spaceName} - Space Summary (Updated)`,
    originalContent: markdownContent,
    metadata: {
      documentType: "space_summary",
      spaceId,
      spaceName,
      updatedAt: new Date().toISOString(),
      updateSource: "manual",
    },
    source: "space",
    userId,
    createdAt: new Date(),
    validAt: new Date(),
    totalChunks: 1,
    sessionId: spaceId,
    version: 1, // TODO: Implement proper versioning
    contentHash,
    previousVersionUuid: undefined, // TODO: Link to previous version
    chunkHashes: [contentHash],
  };

  await saveDocument(document);
  return documentUuid;
}

/**
 * Queue the updated summary document for ingestion
 */
async function queueSummaryDocumentIngestion(
  documentUuid: string,
  spaceId: string,
  userId: string,
  markdownContent: string
): Promise<void> {
  const ingestBody = {
    episodeBody: markdownContent,
    referenceTime: new Date().toISOString(),
    metadata: {
      documentType: "space_summary",
      documentUuid,
      spaceId,
      updateSource: "manual",
    },
    source: "space",
    spaceId,
    sessionId: spaceId,
    type: EpisodeType.DOCUMENT,
  };

  await addToQueue(ingestBody, userId);
  
  logger.info(`Queued updated space summary document ${documentUuid} for ingestion`);
}

export { action, loader };