/**
 * Advanced Player Segmentation tRPC Router
 * AI-powered behavior analysis for hyper-targeted campaigns
 */

import { z } from 'zod';
import { protectedProcedure, publicProcedure, router } from '../_core/trpc.ts';
import {
  analyzePlayerBehavior,
  assignPlayerToSegments,
  generatePredictiveInsights,
  createCohortAnalysis,
  getSegmentRecommendations,
  PREDEFINED_SEGMENTS,
} from '../advancedPlayerSegmentationService.ts';
import { TRPCError } from '@trpc/server';
import { db } from '../db.ts';
import { users, wallets } from '../../drizzle/schema.ts';
import { eq } from 'drizzle-orm';

export const advancedSegmentationRouter = router({
  /**
   * Get all predefined segments
   */
  getPredefinedSegments: publicProcedure.query(async () => {
    return PREDEFINED_SEGMENTS;
  }),

  /**
   * Analyze player behavior
   */
  analyzePlayerBehavior: protectedProcedure.query(async ({ ctx }) => {
    try {
      // Fetch user data
      const user = await db
        .select()
        .from(users)
        .where(eq(users.id, ctx.user.id))
        .limit(1);

      if (user.length === 0) {
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'User not found',
        });
      }

      const userWallet = await db
        .select()
        .from(wallets)
        .where(eq(wallets.userId, ctx.user.id))
        .limit(1);

      // Mock data for analysis (in production, fetch from game_sessions, transactions, etc.)
      const deposits = userWallet.length > 0 ? parseFloat(userWallet[0].gcBalance.toString()) : 0;
      const wagered = deposits * 2; // Mock calculation
      const winnings = wagered * 0.95; // Mock RTP
      const sessions = Math.floor(Math.random() * 100);
      const avgSessionDuration = Math.floor(Math.random() * 120) + 10;
      const lastLogin = new Date(Date.now() - Math.floor(Math.random() * 30) * 24 * 60 * 60 * 1000);
      const firstDeposit = new Date(Date.now() - Math.floor(Math.random() * 365) * 24 * 60 * 60 * 1000);
      const bonusUtilization = Math.floor(Math.random() * 100);
      const referrals = Math.floor(Math.random() * 10);
      const shares = Math.floor(Math.random() * 20);
      const tickets = Math.floor(Math.random() * 5);

      const metrics = await analyzePlayerBehavior(
        ctx.user.id,
        user[0].username,
        deposits,
        wagered,
        winnings,
        sessions,
        avgSessionDuration,
        lastLogin,
        firstDeposit,
        bonusUtilization,
        referrals,
        shares,
        tickets
      );

      return metrics;
    } catch (error) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: error instanceof Error ? error.message : 'Failed to analyze player behavior',
      });
    }
  }),

  /**
   * Get player segments
   */
  getPlayerSegments: protectedProcedure.query(async ({ ctx }) => {
    try {
      // Analyze player behavior first
      const user = await db
        .select()
        .from(users)
        .where(eq(users.id, ctx.user.id))
        .limit(1);

      if (user.length === 0) {
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'User not found',
        });
      }

      const userWallet = await db
        .select()
        .from(wallets)
        .where(eq(wallets.userId, ctx.user.id))
        .limit(1);

      // Mock data
      const deposits = userWallet.length > 0 ? parseFloat(userWallet[0].gcBalance.toString()) : 0;
      const wagered = deposits * 2;
      const winnings = wagered * 0.95;
      const sessions = Math.floor(Math.random() * 100);
      const avgSessionDuration = Math.floor(Math.random() * 120) + 10;
      const lastLogin = new Date(Date.now() - Math.floor(Math.random() * 30) * 24 * 60 * 60 * 1000);
      const firstDeposit = new Date(Date.now() - Math.floor(Math.random() * 365) * 24 * 60 * 60 * 1000);
      const bonusUtilization = Math.floor(Math.random() * 100);
      const referrals = Math.floor(Math.random() * 10);
      const shares = Math.floor(Math.random() * 20);
      const tickets = Math.floor(Math.random() * 5);

      const metrics = await analyzePlayerBehavior(
        ctx.user.id,
        user[0].username,
        deposits,
        wagered,
        winnings,
        sessions,
        avgSessionDuration,
        lastLogin,
        firstDeposit,
        bonusUtilization,
        referrals,
        shares,
        tickets
      );

      // Assign to segments
      const assignments = assignPlayerToSegments(metrics);
      return assignments;
    } catch (error) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: error instanceof Error ? error.message : 'Failed to get player segments',
      });
    }
  }),

  /**
   * Get predictive insights
   */
  getPredictiveInsights: protectedProcedure.query(async ({ ctx }) => {
    try {
      const user = await db
        .select()
        .from(users)
        .where(eq(users.id, ctx.user.id))
        .limit(1);

      if (user.length === 0) {
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'User not found',
        });
      }

      const userWallet = await db
        .select()
        .from(wallets)
        .where(eq(wallets.userId, ctx.user.id))
        .limit(1);

      // Mock data
      const deposits = userWallet.length > 0 ? parseFloat(userWallet[0].gcBalance.toString()) : 0;
      const wagered = deposits * 2;
      const winnings = wagered * 0.95;
      const sessions = Math.floor(Math.random() * 100);
      const avgSessionDuration = Math.floor(Math.random() * 120) + 10;
      const lastLogin = new Date(Date.now() - Math.floor(Math.random() * 30) * 24 * 60 * 60 * 1000);
      const firstDeposit = new Date(Date.now() - Math.floor(Math.random() * 365) * 24 * 60 * 60 * 1000);
      const bonusUtilization = Math.floor(Math.random() * 100);
      const referrals = Math.floor(Math.random() * 10);
      const shares = Math.floor(Math.random() * 20);
      const tickets = Math.floor(Math.random() * 5);

      const metrics = await analyzePlayerBehavior(
        ctx.user.id,
        user[0].username,
        deposits,
        wagered,
        winnings,
        sessions,
        avgSessionDuration,
        lastLogin,
        firstDeposit,
        bonusUtilization,
        referrals,
        shares,
        tickets
      );

      const assignments = assignPlayerToSegments(metrics);
      const insights = generatePredictiveInsights(metrics, assignments);

      return insights;
    } catch (error) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: error instanceof Error ? error.message : 'Failed to generate predictive insights',
      });
    }
  }),

  /**
   * Get segment recommendations
   */
  getSegmentRecommendations: publicProcedure
    .input(z.object({ segmentId: z.string() }))
    .query(async ({ input }) => {
      try {
        const segment = PREDEFINED_SEGMENTS.find((s) => s.id === input.segmentId);
        if (!segment) {
          throw new TRPCError({
            code: 'NOT_FOUND',
            message: 'Segment not found',
          });
        }

        const recommendations = getSegmentRecommendations(segment);
        return recommendations;
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to get recommendations',
        });
      }
    }),

  /**
   * Get cohort analysis
   */
  getCohortAnalysis: publicProcedure
    .input(
      z.object({
        cohortName: z.string(),
        acquisitionDate: z.date(),
      })
    )
    .query(async ({ input }) => {
      try {
        // Mock player metrics for cohort
        const mockMetrics = [];
        for (let i = 0; i < 100; i++) {
          mockMetrics.push(
            await analyzePlayerBehavior(
              i,
              `player_${i}`,
              Math.random() * 5000,
              Math.random() * 10000,
              Math.random() * 9500,
              Math.floor(Math.random() * 100),
              Math.floor(Math.random() * 120) + 10,
              new Date(Date.now() - Math.floor(Math.random() * 30) * 24 * 60 * 60 * 1000),
              input.acquisitionDate,
              Math.floor(Math.random() * 100),
              Math.floor(Math.random() * 10),
              Math.floor(Math.random() * 20),
              Math.floor(Math.random() * 5)
            )
          );
        }

        const cohortAnalysis = createCohortAnalysis(input.cohortName, input.acquisitionDate, mockMetrics);
        return cohortAnalysis;
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: error instanceof Error ? error.message : 'Failed to create cohort analysis',
        });
      }
    }),

  /**
   * Get segment performance
   */
  getSegmentPerformance: publicProcedure.query(async () => {
    try {
      return PREDEFINED_SEGMENTS.map((segment) => ({
        id: segment.id,
        name: segment.name,
        playerCount: segment.playerCount,
        averageLTV: segment.averageLTV,
        churnRate: segment.churnRate,
        engagementScore: segment.engagementScore,
      }));
    } catch (error) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to fetch segment performance',
      });
    }
  }),

  /**
   * Get campaign templates for segment
   */
  getCampaignTemplates: publicProcedure
    .input(z.object({ segmentId: z.string() }))
    .query(async ({ input }) => {
      try {
        const segment = PREDEFINED_SEGMENTS.find((s) => s.id === input.segmentId);
        if (!segment) {
          throw new TRPCError({
            code: 'NOT_FOUND',
            message: 'Segment not found',
          });
        }

        return segment.campaignTemplates;
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to fetch campaign templates',
        });
      }
    }),

  /**
   * Get recommended actions for segment
   */
  getRecommendedActions: publicProcedure
    .input(z.object({ segmentId: z.string() }))
    .query(async ({ input }) => {
      try {
        const segment = PREDEFINED_SEGMENTS.find((s) => s.id === input.segmentId);
        if (!segment) {
          throw new TRPCError({
            code: 'NOT_FOUND',
            message: 'Segment not found',
          });
        }

        return segment.recommendedActions;
      } catch (error) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to fetch recommended actions',
        });
      }
    }),
});
