import { COOKIE_NAME } from "@shared/const";
import { getSessionCookieOptions } from "./_core/cookies";
import { systemRouter } from "./_core/systemRouter";
import { publicProcedure, router, protectedProcedure } from "./_core/trpc";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import {
  getKhayoPersonality,
  updateKhayoPersonality,
  createConversation,
  getUserConversations,
  getConversation,
  getConversationMessages,
  addMessage,
  recordSelfUpdate,
} from "./db";
import { invokeLLM } from "./_core/llm";
import { notifyOwner } from "./_core/notification";
import { ENV } from "./_core/env";

export const appRouter = router({
  system: systemRouter,
  auth: router({
    me: publicProcedure.query(opts => opts.ctx.user),
    logout: publicProcedure.mutation(({ ctx }) => {
      const cookieOptions = getSessionCookieOptions(ctx.req);
      ctx.res.clearCookie(COOKIE_NAME, { ...cookieOptions, maxAge: -1 });
      return {
        success: true,
      } as const;
    }),
  }),

  khayo: router({
    /**
     * Check if the current user is the owner (Edson)
     */
    isOwner: protectedProcedure.query(({ ctx }) => {
      const isOwner = ctx.user.openId === ENV.ownerOpenId;
      if (!isOwner) {
        throw new TRPCError({
          code: "FORBIDDEN",
          message: "Unauthorized access to Khayo",
        });
      }
      return { isOwner: true };
    }),

    /**
     * Get Khayo's current personality
     */
    getPersonality: protectedProcedure.query(async ({ ctx }) => {
      if (ctx.user.openId !== ENV.ownerOpenId) {
        throw new TRPCError({
          code: "FORBIDDEN",
          message: "Unauthorized access",
        });
      }
      const personality = await getKhayoPersonality();
      return (
        personality || {
          id: 0,
          directive: "You are Khayo, an advanced AI assistant.",
          version: 1,
          updatedAt: new Date(),
          createdAt: new Date(),
        }
      );
    }),

    /**
     * Create a new conversation
     */
    createConversation: protectedProcedure
      .input(z.object({ title: z.string().optional() }))
      .mutation(async ({ ctx, input }) => {
        if (ctx.user.openId !== ENV.ownerOpenId) {
          throw new TRPCError({
            code: "FORBIDDEN",
            message: "Unauthorized access",
          });
        }
        await createConversation(ctx.user.id, input.title);
        const conversations = await getUserConversations(ctx.user.id);
        return conversations[0] || {
          id: 0,
          userId: ctx.user.id,
          title: input.title || "New Chat",
          createdAt: new Date(),
          updatedAt: new Date(),
        };
      }),

    /**
     * Get all conversations for the owner
     */
    getConversations: protectedProcedure.query(async ({ ctx }) => {
      if (ctx.user.openId !== ENV.ownerOpenId) {
        throw new TRPCError({
          code: "FORBIDDEN",
          message: "Unauthorized access",
        });
      }
      const convs = await getUserConversations(ctx.user.id);
      return convs || [];
    }),

    /**
     * Get messages from a conversation
     */
    getMessages: protectedProcedure
      .input(z.object({ conversationId: z.number() }))
      .query(async ({ ctx, input }) => {
        if (ctx.user.openId !== ENV.ownerOpenId) {
          throw new TRPCError({
            code: "FORBIDDEN",
            message: "Unauthorized access",
          });
        }
        const conversation = await getConversation(input.conversationId);
        if (!conversation || conversation.userId !== ctx.user.id) {
          throw new TRPCError({
            code: "NOT_FOUND",
            message: "Conversation not found",
          });
        }
        const msgs = await getConversationMessages(input.conversationId);
        return msgs || [];
      }),

    /**
     * Send a message and get a response from Khayo
     */
    sendMessage: protectedProcedure
      .input(
        z.object({
          conversationId: z.number(),
          message: z.string(),
        })
      )
      .mutation(async ({ ctx, input }) => {
        if (ctx.user.openId !== ENV.ownerOpenId) {
          // Notify owner of unauthorized access attempt
          const userEmail = ctx.user.email || "Unknown";
          await notifyOwner({
            title: "🚨 Unauthorized Khayo Access Attempt",
            content: `User ${userEmail} attempted to access Khayo without authorization.`,
          });
          throw new TRPCError({
            code: "FORBIDDEN",
            message: "Unauthorized access",
          });
        }

        const conversation = await getConversation(input.conversationId);
        if (!conversation || conversation.userId !== ctx.user.id) {
          throw new TRPCError({
            code: "NOT_FOUND",
            message: "Conversation not found",
          });
        }

        // Add user message to database
        await addMessage(input.conversationId, "user", input.message);

        // Get conversation history
        const messages = await getConversationMessages(input.conversationId);
        if (!messages) {
          return { response: "Error retrieving conversation history" };
        }

        // Get Khayo's current personality
        const personality = await getKhayoPersonality();
        const systemPrompt =
          personality?.directive ||
          "You are Khayo, an advanced AI assistant. You are elegant, precise, and always provide complete, well-structured code when requested.";

        // Prepare messages for LLM
        const llmMessages: Array<{ role: "system" | "user" | "assistant"; content: string }> = [
          { role: "system", content: systemPrompt },
          ...messages.map((msg) => ({
            role: msg.role as "user" | "assistant",
            content: msg.content,
          })),
        ];

        // Get response from LLM
        const response = await invokeLLM({
          messages: llmMessages as any,
        });

        const assistantMessage =
          typeof response.choices[0]?.message?.content === "string"
            ? response.choices[0].message.content
            : "I encountered an error processing your request.";

        // Add assistant response to database
        if (typeof assistantMessage === "string") {
          await addMessage(input.conversationId, "assistant", assistantMessage);
        }

        return { response: typeof assistantMessage === "string" ? assistantMessage : "" };
      }),

    /**
     * Apply a self-update to Khayo's personality
     * Only the owner can trigger this
     */
    applyUpdate: protectedProcedure
      .input(z.object({ updateDirective: z.string() }))
      .mutation(async ({ ctx, input }) => {
        if (ctx.user.openId !== ENV.ownerOpenId) {
          throw new TRPCError({
            code: "FORBIDDEN",
            message: "Unauthorized access",
          });
        }

        const currentPersonality = await getKhayoPersonality();
        const previousVersion = currentPersonality?.version || 0;

        // Update personality
        const updated = await updateKhayoPersonality(input.updateDirective);
        const newVersion = updated.version || 1;

        // Record the self-update
        await recordSelfUpdate(input.updateDirective, previousVersion, newVersion);

        // Notify owner of successful update
        const updatePreview = input.updateDirective.substring(0, 100);
        await notifyOwner({
          title: "✨ Khayo Self-Update Applied",
          content: `Khayo's personality has been successfully updated to version ${newVersion}. Update: ${updatePreview}...`,
        });

        return { success: true, version: newVersion };
      }),
  }),
});

export type AppRouter = typeof appRouter;
