/**
 * Batch Withdrawal Router
 * tRPC procedures for batch processing withdrawals
 */

import { router, adminProcedure } from "../_core/trpc.ts";
import { z } from "zod";
import { TRPCError } from "@trpc/server";
import { sendEmailNotification } from "../emailNotificationService.ts";
import { recordWithdrawalEvent } from "../realtimeMonitoringService.ts";
import { getWebSocketAdminService } from "../websocketAdminService.ts";

export const batchWithdrawalRouter = router({
  /**
   * Batch approve withdrawals
   */
  batchApproveWithdrawals: adminProcedure
    .input(
      z.object({
        withdrawalIds: z.array(z.string()).min(1, "At least one withdrawal required"),
        notes: z.string().optional(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        const results = {
          approved: 0,
          failed: 0,
          errors: [] as string[],
        };

        for (const withdrawalId of input.withdrawalIds) {
          try {
            // TODO: Fetch withdrawal from database
            const withdrawal = {
              id: withdrawalId,
              playerId: 123,
              playerName: "John Doe",
              playerEmail: "john@example.com",
              amount: 500,
              currency: "SC" as const,
              method: "bank_transfer" as const,
              status: "pending" as const,
              requestedAt: new Date(),
              kycVerified: true,
            };

            if (withdrawal.status !== "pending") {
              results.errors.push(`${withdrawalId}: Not in pending status`);
              results.failed++;
              continue;
            }

            if (!withdrawal.kycVerified) {
              results.errors.push(`${withdrawalId}: KYC not verified`);
              results.failed++;
              continue;
            }

            // Update withdrawal status
            // TODO: Save to database

            // Send email notification
            await sendEmailNotification(
              "withdrawal_approved",
              withdrawal.playerEmail,
              withdrawal.playerName,
              {
                playerName: withdrawal.playerName,
                amount: withdrawal.amount,
                currency: withdrawal.currency,
                method: withdrawal.method,
                withdrawalId: withdrawal.id,
              }
            );

            // Record event
            recordWithdrawalEvent(
              "withdrawal_approved",
              withdrawal.playerId,
              withdrawal.playerName,
              withdrawal.amount,
              withdrawal.currency,
              withdrawal.id
            );

            results.approved++;
          } catch (error) {
            results.errors.push(`${withdrawalId}: ${(error as Error).message}`);
            results.failed++;
          }
        }

        // Broadcast to admins
        const wsService = getWebSocketAdminService();
        wsService.broadcast({
          type: 'batch_approval_completed',
          timestamp: new Date(),
          data: {
            approved: results.approved,
            failed: results.failed,
            total: input.withdrawalIds.length,
          },
        });

        return {
          success: results.failed === 0,
          ...results,
        };
      } catch (error) {
        throw new TRPCError({
          code: "INTERNAL_SERVER_ERROR",
          message: (error as Error).message,
        });
      }
    }),

  /**
   * Batch reject withdrawals
   */
  batchRejectWithdrawals: adminProcedure
    .input(
      z.object({
        withdrawalIds: z.array(z.string()).min(1, "At least one withdrawal required"),
        reason: z.string().min(10, "Reason must be at least 10 characters"),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        const results = {
          rejected: 0,
          failed: 0,
          errors: [] as string[],
        };

        for (const withdrawalId of input.withdrawalIds) {
          try {
            // TODO: Fetch withdrawal from database
            const withdrawal = {
              id: withdrawalId,
              playerId: 123,
              playerName: "John Doe",
              playerEmail: "john@example.com",
              amount: 500,
              currency: "SC" as const,
              method: "bank_transfer" as const,
              status: "pending" as const,
              requestedAt: new Date(),
              kycVerified: true,
            };

            if (withdrawal.status !== "pending") {
              results.errors.push(`${withdrawalId}: Not in pending status`);
              results.failed++;
              continue;
            }

            // Update withdrawal status
            // TODO: Save to database

            // Send email notification
            await sendEmailNotification(
              "withdrawal_rejected",
              withdrawal.playerEmail,
              withdrawal.playerName,
              {
                playerName: withdrawal.playerName,
                amount: withdrawal.amount,
                currency: withdrawal.currency,
                reason: input.reason,
                withdrawalId: withdrawal.id,
              }
            );

            // Record event
            recordWithdrawalEvent(
              "withdrawal_rejected",
              withdrawal.playerId,
              withdrawal.playerName,
              withdrawal.amount,
              withdrawal.currency,
              withdrawal.id
            );

            results.rejected++;
          } catch (error) {
            results.errors.push(`${withdrawalId}: ${(error as Error).message}`);
            results.failed++;
          }
        }

        // Broadcast to admins
        const wsService = getWebSocketAdminService();
        wsService.broadcast({
          type: 'batch_rejection_completed',
          timestamp: new Date(),
          data: {
            rejected: results.rejected,
            failed: results.failed,
            total: input.withdrawalIds.length,
          },
        });

        return {
          success: results.failed === 0,
          ...results,
        };
      } catch (error) {
        throw new TRPCError({
          code: "INTERNAL_SERVER_ERROR",
          message: (error as Error).message,
        });
      }
    }),

  /**
   * Export withdrawals as CSV
   */
  exportWithdrawalsCSV: adminProcedure
    .input(
      z.object({
        status: z.enum(["pending", "approved", "processing", "completed", "rejected", "failed"]).optional(),
        startDate: z.date().optional(),
        endDate: z.date().optional(),
      })
    )
    .query(async ({ input, ctx }) => {
      try {
        // TODO: Fetch withdrawals from database based on filters

        const withdrawals = [
          {
            id: "w_001",
            playerId: 123,
            playerName: "John Doe",
            playerEmail: "john@example.com",
            amount: 500,
            currency: "SC",
            method: "bank_transfer",
            status: "pending",
            requestedAt: new Date(),
          },
        ];

        // Generate CSV
        const headers = [
          "ID",
          "Player ID",
          "Player Name",
          "Email",
          "Amount",
          "Currency",
          "Method",
          "Status",
          "Requested At",
        ];

        const rows = withdrawals.map((w) => [
          w.id,
          w.playerId,
          w.playerName,
          w.playerEmail,
          w.amount,
          w.currency,
          w.method,
          w.status,
          w.requestedAt.toISOString(),
        ]);

        const csv = [
          headers.join(","),
          ...rows.map((row) => row.map((cell) => `"${cell}"`).join(",")),
        ].join("\n");

        return {
          success: true,
          csv,
          filename: `withdrawals_${new Date().toISOString().split("T")[0]}.csv`,
          count: withdrawals.length,
        };
      } catch (error) {
        throw new TRPCError({
          code: "INTERNAL_SERVER_ERROR",
          message: (error as Error).message,
        });
      }
    }),

  /**
   * Get batch processing status
   */
  getBatchStatus: adminProcedure
    .input(z.object({ batchId: z.string() }))
    .query(async ({ input, ctx }) => {
      // TODO: Fetch batch status from database
      return {
        batchId: input.batchId,
        status: "completed",
        totalWithdrawals: 50,
        processed: 50,
        approved: 45,
        rejected: 5,
        failed: 0,
        startedAt: new Date(Date.now() - 3600000),
        completedAt: new Date(),
        duration: "5 minutes",
      };
    }),
});
