/**
 * Final Support Systems Tests
 * Tests for compliance/KYC, email/SMS notifications, and player support
 */

import { describe, it, expect, beforeEach } from 'vitest';
import {
  createKYCProfile,
  addIdentityDocument,
  verifyIdentityDocument,
  approveKYCProfile,
  rejectKYCProfile,
  performAMLCheck,
  updateAMLCheckStatus,
  setDepositLimit,
  setLossLimit,
  activateSelfExclusion,
  activateCoolOff,
  canPlayerDeposit,
  canPlayerPlay,
  createComplianceEvent,
  generateComplianceReport,
  calculateRiskLevel,
  isKYCExpired,
  createResponsibleGamblingSettings: createRGSettings,
  type KYCProfile,
  type ResponsibleGamblingSettings,
} from './complianceKYCSystem';
import {
  createEmailNotification,
  createSMSNotification,
  createNotificationPreferences,
  updateNotificationPreferences,
  EMAIL_TEMPLATES,
  SMS_TEMPLATES,
  createNotificationBatch,
  calculateNotificationStats,
  unsubscribeFromNotifications,
  type EmailNotification,
  type SMSNotification,
  type NotificationPreferences,
} from './emailSMSNotifications';
import {
  createSupportTicket,
  addTicketMessage,
  assignTicketToAgent,
  updateTicketStatus,
  createDispute,
  respondToDispute,
  resolveDispute,
  createRefundRequest,
  approveRefund,
  rejectRefund,
  processRefund,
  createSupportAgent,
  calculateSupportMetrics,
  generateSupportReport,
  type SupportTicket,
  type Dispute,
  type RefundRequest,
} from './playerSupportDashboard';

describe('Final Support Systems', () => {
  describe('Compliance & KYC System', () => {
    let kycProfile: KYCProfile;

    beforeEach(() => {
      kycProfile = createKYCProfile(
        1,
        'John',
        'Doe',
        new Date('1990-01-15'),
        'US',
        {
          street: '123 Main St',
          city: 'New York',
          state: 'NY',
          postalCode: '10001',
          country: 'United States',
        },
        'john@example.com',
        '+1234567890'
      );
    });

    it('should create KYC profile', () => {
      expect(kycProfile.firstName).toBe('John');
      expect(kycProfile.verificationStatus).toBe('pending');
    });

    it('should add identity document', () => {
      const doc = addIdentityDocument(
        kycProfile,
        'passport',
        'ABC123456',
        'US',
        new Date('2030-01-01'),
        'https://example.com/doc.pdf'
      );

      expect(kycProfile.documents).toHaveLength(1);
      expect(doc.type).toBe('passport');
    });

    it('should verify identity document', () => {
      const doc = addIdentityDocument(
        kycProfile,
        'passport',
        'ABC123456',
        'US',
        new Date('2030-01-01'),
        'https://example.com/doc.pdf'
      );

      verifyIdentityDocument(doc, true);

      expect(doc.verificationStatus).toBe('verified');
    });

    it('should approve KYC profile', () => {
      approveKYCProfile(kycProfile, 1);

      expect(kycProfile.verificationStatus).toBe('approved');
      expect(kycProfile.verifiedAt).toBeDefined();
      expect(kycProfile.expiresAt).toBeDefined();
    });

    it('should reject KYC profile', () => {
      rejectKYCProfile(kycProfile, 'Document verification failed');

      expect(kycProfile.verificationStatus).toBe('rejected');
    });

    it('should perform AML check', () => {
      const amlCheck = performAMLCheck(1, 'John', 'Doe', new Date('1990-01-15'), 'US');

      expect(amlCheck.playerId).toBe(1);
      expect(amlCheck.status).toBeDefined();
      expect(amlCheck.riskScore).toBeGreaterThanOrEqual(0);
    });

    it('should set deposit limit', () => {
      const rgSettings = createRGSettings(1);
      setDepositLimit(rgSettings, 1000, 'daily');

      expect(rgSettings.depositLimit).toBeDefined();
      expect(rgSettings.depositLimit?.amount).toBe(1000);
      expect(rgSettings.depositLimit?.enabled).toBe(true);
    });

    it('should check if player can deposit', () => {
      const rgSettings = createRGSettings(1);
      setDepositLimit(rgSettings, 1000, 'daily');

      expect(canPlayerDeposit(rgSettings, 500)).toBe(true);
      expect(canPlayerDeposit(rgSettings, 1500)).toBe(false);
    });

    it('should activate self-exclusion', () => {
      const rgSettings = createRGSettings(1);
      activateSelfExclusion(rgSettings, 30, 'Personal reasons');

      expect(rgSettings.selfExclusion?.enabled).toBe(true);
      expect(canPlayerPlay(rgSettings)).toBe(false);
    });

    it('should check KYC expiration', () => {
      approveKYCProfile(kycProfile, 1);
      expect(isKYCExpired(kycProfile)).toBe(false);
    });
  });

  describe('Email & SMS Notifications', () => {
    let emailNotif: EmailNotification;
    let smsNotif: SMSNotification;
    let prefs: NotificationPreferences;

    beforeEach(() => {
      emailNotif = createEmailNotification(
        1,
        'john@example.com',
        'welcome',
        'Welcome to CoinKrazy!',
        'Welcome to our platform'
      );

      smsNotif = createSMSNotification(1, '+1234567890', 'welcome', 'Welcome to CoinKrazy!');

      prefs = createNotificationPreferences(1);
    });

    it('should create email notification', () => {
      expect(emailNotif.email).toBe('john@example.com');
      expect(emailNotif.status).toBe('pending');
    });

    it('should create SMS notification', () => {
      expect(smsNotif.phoneNumber).toBe('+1234567890');
      expect(smsNotif.status).toBe('pending');
    });

    it('should create notification preferences', () => {
      expect(prefs.emailNotifications).toBe(true);
      expect(prefs.smsNotifications).toBe(true);
    });

    it('should update notification preferences', () => {
      updateNotificationPreferences(prefs, { marketingEmails: false });

      expect(prefs.marketingEmails).toBe(false);
    });

    it('should have email templates', () => {
      expect(EMAIL_TEMPLATES.welcome).toBeDefined();
      expect(EMAIL_TEMPLATES.deposit_confirmation).toBeDefined();
    });

    it('should have SMS templates', () => {
      expect(SMS_TEMPLATES.welcome).toBeDefined();
      expect(SMS_TEMPLATES.bonus_awarded).toBeDefined();
    });

    it('should create notification batch', () => {
      const batch = createNotificationBatch([emailNotif, smsNotif]);

      expect(batch.notifications).toHaveLength(2);
      expect(batch.status).toBe('pending');
    });

    it('should unsubscribe from notifications', () => {
      unsubscribeFromNotifications(prefs, 'email');

      expect(prefs.emailNotifications).toBe(false);
      expect(prefs.smsNotifications).toBe(true);
    });
  });

  describe('Player Support Dashboard', () => {
    let ticket: SupportTicket;
    let dispute: Dispute;
    let refund: RefundRequest;

    beforeEach(() => {
      ticket = createSupportTicket(
        1,
        'john@example.com',
        'John Doe',
        'payment',
        'Deposit not received',
        'I deposited $100 but it was not credited to my account',
        'high'
      );

      dispute = createDispute(
        1,
        ticket.id,
        'Incorrect payout',
        100,
        'I won $100 but only received $50',
        []
      );

      refund = createRefundRequest(
        1,
        100,
        'Accidental deposit',
        'txn_12345',
        'original_payment'
      );
    });

    it('should create support ticket', () => {
      expect(ticket.playerId).toBe(1);
      expect(ticket.status).toBe('open');
      expect(ticket.priority).toBe('high');
    });

    it('should add message to ticket', () => {
      addTicketMessage(ticket, 1, 'John Doe', 'player', 'I need help with my deposit');

      expect(ticket.messages).toHaveLength(1);
      expect(ticket.messages[0].senderRole).toBe('player');
    });

    it('should assign ticket to agent', () => {
      assignTicketToAgent(ticket, 100);

      expect(ticket.assignedTo).toBe(100);
      expect(ticket.status).toBe('in_progress');
    });

    it('should update ticket status', () => {
      updateTicketStatus(ticket, 'resolved', 'Issue resolved - deposit credited');

      expect(ticket.status).toBe('resolved');
      expect(ticket.resolvedAt).toBeDefined();
    });

    it('should create dispute', () => {
      expect(dispute.playerId).toBe(1);
      expect(dispute.status).toBe('open');
      expect(dispute.amount).toBe(100);
    });

    it('should respond to dispute', () => {
      respondToDispute(dispute, 'I have evidence of the payout', ['https://example.com/screenshot.png']);

      expect(dispute.playerResponse).toBeDefined();
      expect(dispute.status).toBe('player_responded');
    });

    it('should resolve dispute', () => {
      resolveDispute(dispute, 'upheld', 'Player evidence confirms the issue', 1);

      expect(dispute.decision).toBe('upheld');
      expect(dispute.status).toBe('resolved');
    });

    it('should create refund request', () => {
      expect(refund.playerId).toBe(1);
      expect(refund.status).toBe('pending');
      expect(refund.amount).toBe(100);
    });

    it('should approve refund', () => {
      approveRefund(refund, 1);

      expect(refund.status).toBe('approved');
      expect(refund.approvedBy).toBe(1);
    });

    it('should process refund', () => {
      approveRefund(refund, 1);
      processRefund(refund);

      expect(refund.status).toBe('processed');
      expect(refund.processedAt).toBeDefined();
    });

    it('should reject refund', () => {
      rejectRefund(refund, 'Refund window expired');

      expect(refund.status).toBe('rejected');
      expect(refund.failureReason).toBe('Refund window expired');
    });

    it('should create support agent', () => {
      const agent = createSupportAgent(1, 'Alice', 'alice@support.com', 'support_agent', ['en', 'es'], [
        'payment',
        'technical',
      ]);

      expect(agent.name).toBe('Alice');
      expect(agent.languages).toContain('es');
    });

    it('should calculate support metrics', () => {
      const metrics = calculateSupportMetrics([ticket], [refund], [dispute]);

      expect(metrics.totalTickets).toBe(1);
      expect(metrics.openTickets).toBe(1);
      expect(metrics.disputesOpen).toBe(1);
    });

    it('should generate support report', () => {
      const startDate = new Date();
      const endDate = new Date();

      const report = generateSupportReport(
        'daily',
        startDate,
        endDate,
        [ticket],
        [refund],
        [dispute],
        []
      );

      expect(report.period).toBe('daily');
      expect(report.metrics).toBeDefined();
      expect(report.topIssues).toBeDefined();
    });
  });

  describe('Cross-System Integration', () => {
    it('should integrate KYC with support', () => {
      const kycProfile = createKYCProfile(
        1,
        'John',
        'Doe',
        new Date('1990-01-15'),
        'US',
        {
          street: '123 Main St',
          city: 'New York',
          state: 'NY',
          postalCode: '10001',
          country: 'United States',
        },
        'john@example.com',
        '+1234567890'
      );

      const ticket = createSupportTicket(1, kycProfile.email, kycProfile.firstName, 'kyc', 'KYC Issue', 'Cannot verify');

      expect(ticket.playerEmail).toBe(kycProfile.email);
    });

    it('should integrate notifications with support', () => {
      const ticket = createSupportTicket(1, 'john@example.com', 'John', 'payment', 'Deposit Issue', 'Not received');

      const emailNotif = createEmailNotification(
        1,
        'john@example.com',
        'account_alert',
        'Support Ticket Created',
        `Your support ticket ${ticket.id} has been created`
      );

      expect(emailNotif.playerId).toBe(ticket.playerId);
    });
  });
});

/**
 * Helper function to create responsible gambling settings
 */
function createRGSettings(playerId: number): ResponsibleGamblingSettings {
  return {
    playerId,
    createdAt: new Date(),
    updatedAt: new Date(),
  };
}
