import { COOKIE_NAME } from "@shared/const";
import { getSessionCookieOptions } from "./_core/cookies";
import { systemRouter } from "./_core/systemRouter";
import { publicProcedure, router, adminProcedure } from "./_core/trpc";
import { createContactSubmission, getContactSubmissions, getContactSubmissionById, updateContactSubmissionStatus, getContactSubmissionStats } from "./db";
import { notifyOwner } from "./_core/notification";
import { z } from "zod";
import crypto from "crypto";

// Simple server-side CAPTCHA store (in-memory, short-lived)
const captchaStore = new Map<string, { answer: number; expiresAt: number }>();

// Clean up expired CAPTCHAs every 5 minutes
setInterval(() => {
  const now = Date.now();
  captchaStore.forEach((value, key) => {
    if (value.expiresAt < now) captchaStore.delete(key);
  });
}, 5 * 60 * 1000);

function generateCaptcha() {
  const a = Math.floor(Math.random() * 20) + 1;
  const b = Math.floor(Math.random() * 20) + 1;
  const ops = [
    { symbol: "+", fn: (x: number, y: number) => x + y },
    { symbol: "-", fn: (x: number, y: number) => x - y },
  ];
  // Ensure subtraction doesn't go negative
  const op = ops[Math.floor(Math.random() * ops.length)];
  const num1 = op.symbol === "-" ? Math.max(a, b) : a;
  const num2 = op.symbol === "-" ? Math.min(a, b) : b;
  const answer = op.fn(num1, num2);
  const question = `${num1} ${op.symbol} ${num2} = ?`;
  const id = crypto.randomUUID();

  captchaStore.set(id, { answer, expiresAt: Date.now() + 5 * 60 * 1000 }); // 5 min expiry
  return { id, question };
}

function verifyCaptcha(id: string, answer: number): boolean {
  const entry = captchaStore.get(id);
  if (!entry) return false;
  if (entry.expiresAt < Date.now()) {
    captchaStore.delete(id);
    return false;
  }
  const isCorrect = entry.answer === answer;
  captchaStore.delete(id); // One-time use
  return isCorrect;
}

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

  captcha: router({
    generate: publicProcedure.query(() => {
      return generateCaptcha();
    }),
  }),

  contact: router({
    submit: publicProcedure
      .input(
        z.object({
          name: z.string().min(1, "Name is required").max(255),
          email: z.string().email("Invalid email address").max(320),
          company: z.string().max(255).optional(),
          industry: z.string().max(100).optional(),
          message: z.string().min(1, "Message is required").max(5000),
          captchaId: z.string().min(1, "CAPTCHA is required"),
          captchaAnswer: z.number({ message: "Please enter a number" }),
        })
      )
      .mutation(async ({ input }) => {
        // Verify CAPTCHA first
        const captchaValid = verifyCaptcha(input.captchaId, input.captchaAnswer);
        if (!captchaValid) {
          throw new Error("Incorrect CAPTCHA answer. Please try again.");
        }

        // Store in database
        await createContactSubmission({
          name: input.name,
          email: input.email,
          company: input.company ?? null,
          industry: input.industry ?? null,
          message: input.message,
        });

        // Send notification to the owner
        const notificationContent = [
          `**New Contact Form Submission**`,
          ``,
          `**Name:** ${input.name}`,
          `**Email:** ${input.email}`,
          input.company ? `**Company:** ${input.company}` : null,
          input.industry ? `**Industry:** ${input.industry}` : null,
          ``,
          `**Message:**`,
          input.message,
          ``,
          `---`,
          `*Please reply to ${input.email} to follow up on this inquiry.*`,
        ]
          .filter(Boolean)
          .join("\n");

        try {
          await notifyOwner({
            title: `New Inquiry from ${input.name}${input.company ? ` (${input.company})` : ""}`,
            content: notificationContent,
          });
        } catch (error) {
          // Log but don't fail the submission if notification fails
          console.warn("[Contact] Failed to send owner notification:", error);
        }

        return { success: true } as const;
      }),
  }),

  // Admin endpoints for managing contact submissions
  admin: router({
    submissions: router({
      list: adminProcedure
        .input(
          z.object({
            status: z.string().optional(),
            limit: z.number().min(1).max(100).optional(),
            offset: z.number().min(0).optional(),
          }).optional()
        )
        .query(async ({ input }) => {
          const submissions = await getContactSubmissions({
            status: input?.status,
            limit: input?.limit ?? 50,
            offset: input?.offset ?? 0,
          });
          return submissions;
        }),

      getById: adminProcedure
        .input(z.object({ id: z.number() }))
        .query(async ({ input }) => {
          const submission = await getContactSubmissionById(input.id);
          if (!submission) {
            throw new Error("Submission not found");
          }
          return submission;
        }),

      updateStatus: adminProcedure
        .input(
          z.object({
            id: z.number(),
            status: z.enum(["new", "read", "replied", "archived"]),
          })
        )
        .mutation(async ({ input }) => {
          return updateContactSubmissionStatus(input.id, input.status);
        }),

      stats: adminProcedure.query(async () => {
        return getContactSubmissionStats();
      }),
    }),
  }),
});

export type AppRouter = typeof appRouter;
