import { router, protectedProcedure } from "../_core/trpc.ts";
import { z } from "zod";
import { getDb } from "../db.ts";
import { transactions, users } from "../../drizzle/schema.ts";
import { eq } from "drizzle-orm";
import { TRPCError } from "@trpc/server";

const CASHAPP_SERVICE_FEE = 5; // $5 flat fee
const MIN_REDEMPTION = 5;
const MAX_REDEMPTION = 500;

/**
 * CashApp Redemption Router
 * Handles sweep coin to cash redemption via CashApp
 */
export const cashappRedemptionRouter = router({
  /**
   * Initiate CashApp redemption
   */
  initiate: protectedProcedure
    .input(
      z.object({
        amount: z.number().min(MIN_REDEMPTION).max(MAX_REDEMPTION),
        cashappTag: z.string().min(1).max(50), // $username format
        phoneNumber: z.string().optional(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      const userId = ctx.user.id;

      // Verify user has sufficient balance
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });
      
      const user = await db
        .select()
        .from(users)
        .where(eq(users.id, userId))
        .then((rows: any) => rows[0]);

      if (!user) {
        throw new TRPCError({
          code: "NOT_FOUND",
          message: "User not found",
        });
      }

      const totalCost = input.amount + CASHAPP_SERVICE_FEE;

      if ((user.scBalance ?? 0) < totalCost) {
        throw new TRPCError({
          code: "BAD_REQUEST",
          message: `Insufficient balance. Need ${totalCost} SC (${input.amount} + $${CASHAPP_SERVICE_FEE} fee)`,
        });
      }

      // Create redemption transaction
      await db.insert(transactions).values({
        userId,
        type: "sc_redeem" as any,
        currency: "SC",
        amount: input.amount.toFixed(2),
        balanceBefore: (user.scBalance ?? 0).toString(),
        balanceAfter: ((user.scBalance ?? 0) - totalCost).toFixed(2),
        metadata: {
          method: "cashapp",
          cashappTag: input.cashappTag,
          phoneNumber: input.phoneNumber,
          serviceFee: CASHAPP_SERVICE_FEE,
          totalDeducted: totalCost,
        },
        description: `CashApp redemption: $${input.amount} (+ $${CASHAPP_SERVICE_FEE} fee)`,
      });

      return {
        transactionId: Math.floor(Math.random() * 1000000),
        amount: input.amount,
        serviceFee: CASHAPP_SERVICE_FEE,
        totalDeducted: totalCost,
        status: "pending",
        estimatedTime: "1-3 business days",
      };
    }),

  /**
   * Get redemption history
   */
  getHistory: protectedProcedure
    .input(
      z.object({
        limit: z.number().default(20),
        offset: z.number().default(0),
      })
    )
    .query(async ({ ctx, input }) => {
      const userId = ctx.user.id;
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });

      const redemptions = await db
        .select()
        .from(transactions)
        .where(
          (t: any) => eq(t.userId, userId)
        )
        .orderBy((t: any) => t.createdAt)
        .limit(input.limit)
        .offset(input.offset);

      return redemptions.map((t: any) => ({
        id: t.id,
        amount: t.amount,
        status: "pending",
        serviceFee: (t.metadata as any)?.serviceFee || CASHAPP_SERVICE_FEE,
        cashappTag: (t.metadata as any)?.cashappTag,
        createdAt: t.createdAt,
        completedAt: t.createdAt,
      }));
    }),

  /**
   * Get redemption details
   */
  getDetails: protectedProcedure
    .input(z.object({ transactionId: z.number() }))
    .query(async ({ ctx, input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });
      
      const rows = await db
        .select()
        .from(transactions)
        .where(eq(transactions.id, input.transactionId));
      const transaction = rows[0];

      if (!transaction || transaction.userId !== ctx.user.id) {
        throw new TRPCError({
          code: "NOT_FOUND",
          message: "Transaction not found",
        });
      }

      return {
        id: transaction.id,
        amount: parseFloat(transaction.amount as any),
        status: "pending",
        serviceFee: (transaction.metadata as any)?.serviceFee || CASHAPP_SERVICE_FEE,
        totalDeducted: (transaction.metadata as any)?.totalDeducted,
        cashappTag: (transaction.metadata as any)?.cashappTag,
        createdAt: transaction.createdAt,
        completedAt: transaction.createdAt,
        description: transaction.description,
      };
    }),

  /**
   * Check CashApp tag availability (mock)
   */
  validateCashappTag: protectedProcedure
    .input(z.object({ tag: z.string() }))
    .query(async ({ input }) => {
      // In production, validate against actual CashApp API
      const isValid = /^\$[a-zA-Z0-9]{1,20}$/.test(input.tag);

      return {
        valid: isValid,
        message: isValid ? "Valid CashApp tag" : "Invalid CashApp tag format ($username)",
      };
    }),

  /**
   * Get redemption limits
   */
  getLimits: protectedProcedure.query(async ({ ctx }) => {
    const userId = ctx.user.id;
    const db = await getDb();
    if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });

    // Get user's total redemptions this month
    const thisMonth = new Date();
    thisMonth.setDate(1);

    const monthlyRedemptions = await db
      .select()
      .from(transactions)
      .where(
        (t: any) => eq(t.userId, userId)
      );

    const monthlyTotal = monthlyRedemptions.reduce((sum: number, t: any) => sum + t.amount, 0);

    return {
      minRedemption: MIN_REDEMPTION,
      maxRedemption: MAX_REDEMPTION,
      serviceFee: CASHAPP_SERVICE_FEE,
      monthlyLimit: 5000,
      monthlyUsed: monthlyTotal,
      monthlyRemaining: 5000 - monthlyTotal,
      canRedeem: monthlyTotal < 5000,
    };
  }),
});
