/**
 * Compliance & KYC System
 * Identity verification, AML checks, and responsible gambling tools
 */

export type VerificationStatus = 'pending' | 'approved' | 'rejected' | 'expired';
export type DocumentType = 'passport' | 'driver_license' | 'national_id' | 'utility_bill';
export type RiskLevel = 'low' | 'medium' | 'high' | 'critical';
export type ResponsibleGamblingAction = 'deposit_limit' | 'loss_limit' | 'session_limit' | 'self_exclusion' | 'cool_off';

export interface KYCProfile {
  playerId: number;
  firstName: string;
  lastName: string;
  dateOfBirth: Date;
  nationality: string;
  address: {
    street: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
  };
  email: string;
  phone: string;
  verificationStatus: VerificationStatus;
  verifiedAt?: Date;
  expiresAt?: Date;
  documents: IdentityDocument[];
  amlCheckStatus: 'pending' | 'passed' | 'failed' | 'manual_review';
  amlCheckDate?: Date;
  riskLevel: RiskLevel;
  riskFactors: string[];
  createdAt: Date;
  updatedAt: Date;
}

export interface IdentityDocument {
  id: string;
  type: DocumentType;
  documentNumber: string;
  issuingCountry: string;
  expiryDate: Date;
  uploadedAt: Date;
  verificationStatus: 'pending' | 'verified' | 'rejected';
  verificationNotes?: string;
  fileUrl: string;
}

export interface AMLCheck {
  id: string;
  playerId: number;
  checkDate: Date;
  status: 'pending' | 'passed' | 'failed' | 'manual_review';
  matchedLists: string[]; // PEP, OFAC, etc.
  riskScore: number; // 0-100
  details: {
    nameMatch: boolean;
    dateOfBirthMatch: boolean;
    nationalityMatch: boolean;
    addressMatch: boolean;
  };
  reviewedBy?: number;
  reviewedAt?: Date;
  notes?: string;
}

export interface ResponsibleGamblingSettings {
  playerId: number;
  depositLimit?: {
    amount: number;
    period: 'daily' | 'weekly' | 'monthly';
    enabled: boolean;
    currentSpent: number;
    resetDate: Date;
  };
  lossLimit?: {
    amount: number;
    period: 'daily' | 'weekly' | 'monthly';
    enabled: boolean;
    currentLosses: number;
    resetDate: Date;
  };
  sessionLimit?: {
    durationMinutes: number;
    enabled: boolean;
    warningAt: number; // minutes before limit
  };
  selfExclusion?: {
    enabled: boolean;
    startDate: Date;
    endDate: Date;
    reason: string;
  };
  coolOff?: {
    enabled: boolean;
    startDate: Date;
    endDate: Date;
    durationDays: number;
  };
  createdAt: Date;
  updatedAt: Date;
}

export interface ComplianceEvent {
  id: string;
  playerId: number;
  eventType: 'kyc_submitted' | 'kyc_approved' | 'kyc_rejected' | 'aml_check' | 'deposit_limit_set' | 'self_exclusion_activated' | 'verification_expired';
  timestamp: Date;
  details: Record<string, any>;
  reviewedBy?: number;
  notes?: string;
}

export interface ComplianceReport {
  id: string;
  period: 'daily' | 'weekly' | 'monthly';
  startDate: Date;
  endDate: Date;
  totalPlayers: number;
  verifiedPlayers: number;
  pendingVerification: number;
  amlChecksPassed: number;
  amlChecksFailed: number;
  amlChecksManualReview: number;
  highRiskPlayers: number;
  selfExcludedPlayers: number;
  depositLimitedPlayers: number;
  complianceScore: number; // 0-100
}

/**
 * Create KYC profile
 */
export function createKYCProfile(
  playerId: number,
  firstName: string,
  lastName: string,
  dateOfBirth: Date,
  nationality: string,
  address: {
    street: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
  },
  email: string,
  phone: string
): KYCProfile {
  return {
    playerId,
    firstName,
    lastName,
    dateOfBirth,
    nationality,
    address,
    email,
    phone,
    verificationStatus: 'pending',
    documents: [],
    amlCheckStatus: 'pending',
    riskLevel: 'medium',
    riskFactors: [],
    createdAt: new Date(),
    updatedAt: new Date(),
  };
}

/**
 * Add identity document
 */
export function addIdentityDocument(
  profile: KYCProfile,
  type: DocumentType,
  documentNumber: string,
  issuingCountry: string,
  expiryDate: Date,
  fileUrl: string
): IdentityDocument {
  const document: IdentityDocument = {
    id: `doc_${profile.playerId}_${Date.now()}`,
    type,
    documentNumber,
    issuingCountry,
    expiryDate,
    uploadedAt: new Date(),
    verificationStatus: 'pending',
    fileUrl,
  };

  profile.documents.push(document);
  profile.updatedAt = new Date();

  return document;
}

/**
 * Verify identity document
 */
export function verifyIdentityDocument(
  document: IdentityDocument,
  approved: boolean,
  notes?: string
): void {
  document.verificationStatus = approved ? 'verified' : 'rejected';
  document.verificationNotes = notes;
}

/**
 * Approve KYC profile
 */
export function approveKYCProfile(profile: KYCProfile, approvedBy: number): void {
  profile.verificationStatus = 'approved';
  profile.verifiedAt = new Date();
  profile.expiresAt = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000); // 1 year
  profile.updatedAt = new Date();
}

/**
 * Reject KYC profile
 */
export function rejectKYCProfile(profile: KYCProfile, reason: string): void {
  profile.verificationStatus = 'rejected';
  profile.updatedAt = new Date();
}

/**
 * Perform AML check
 */
export function performAMLCheck(
  playerId: number,
  firstName: string,
  lastName: string,
  dateOfBirth: Date,
  nationality: string
): AMLCheck {
  // Simplified AML check (in production, would integrate with real AML services)
  const riskFactors: string[] = [];
  let riskScore = 0;

  // Check against PEP lists (simplified)
  const isPEP = Math.random() < 0.01; // 1% false positive rate
  if (isPEP) {
    riskFactors.push('Possible PEP match');
    riskScore += 40;
  }

  // Check against OFAC lists (simplified)
  const isOFAC = Math.random() < 0.005; // 0.5% false positive rate
  if (isOFAC) {
    riskFactors.push('Possible OFAC match');
    riskScore += 50;
  }

  // Age check
  const age = new Date().getFullYear() - dateOfBirth.getFullYear();
  if (age < 25) {
    riskFactors.push('Young account');
    riskScore += 5;
  }

  // High-risk countries
  const highRiskCountries = ['KP', 'IR', 'SY', 'CU'];
  if (highRiskCountries.includes(nationality)) {
    riskFactors.push('High-risk jurisdiction');
    riskScore += 30;
  }

  const status = riskScore > 50 ? 'manual_review' : riskScore > 20 ? 'failed' : 'passed';

  return {
    id: `aml_${playerId}_${Date.now()}`,
    playerId,
    checkDate: new Date(),
    status: status as 'pending' | 'passed' | 'failed' | 'manual_review',
    matchedLists: riskFactors,
    riskScore: Math.min(100, riskScore),
    details: {
      nameMatch: false,
      dateOfBirthMatch: false,
      nationalityMatch: false,
      addressMatch: false,
    },
  };
}

/**
 * Update AML check status
 */
export function updateAMLCheckStatus(
  amlCheck: AMLCheck,
  status: 'passed' | 'failed' | 'manual_review',
  reviewedBy: number,
  notes?: string
): void {
  amlCheck.status = status;
  amlCheck.reviewedBy = reviewedBy;
  amlCheck.reviewedAt = new Date();
  amlCheck.notes = notes;
}

/**
 * Set deposit limit
 */
export function setDepositLimit(
  settings: ResponsibleGamblingSettings,
  amount: number,
  period: 'daily' | 'weekly' | 'monthly'
): void {
  settings.depositLimit = {
    amount,
    period,
    enabled: true,
    currentSpent: 0,
    resetDate: calculateResetDate(period),
  };
  settings.updatedAt = new Date();
}

/**
 * Set loss limit
 */
export function setLossLimit(
  settings: ResponsibleGamblingSettings,
  amount: number,
  period: 'daily' | 'weekly' | 'monthly'
): void {
  settings.lossLimit = {
    amount,
    period,
    enabled: true,
    currentLosses: 0,
    resetDate: calculateResetDate(period),
  };
  settings.updatedAt = new Date();
}

/**
 * Set session limit
 */
export function setSessionLimit(
  settings: ResponsibleGamblingSettings,
  durationMinutes: number,
  warningAt: number
): void {
  settings.sessionLimit = {
    durationMinutes,
    enabled: true,
    warningAt,
  };
  settings.updatedAt = new Date();
}

/**
 * Activate self-exclusion
 */
export function activateSelfExclusion(
  settings: ResponsibleGamblingSettings,
  durationDays: number,
  reason: string
): void {
  const startDate = new Date();
  const endDate = new Date(startDate.getTime() + durationDays * 24 * 60 * 60 * 1000);

  settings.selfExclusion = {
    enabled: true,
    startDate,
    endDate,
    reason,
  };
  settings.updatedAt = new Date();
}

/**
 * Activate cool-off period
 */
export function activateCoolOff(
  settings: ResponsibleGamblingSettings,
  durationDays: number
): void {
  const startDate = new Date();
  const endDate = new Date(startDate.getTime() + durationDays * 24 * 60 * 60 * 1000);

  settings.coolOff = {
    enabled: true,
    startDate,
    endDate,
    durationDays,
  };
  settings.updatedAt = new Date();
}

/**
 * Calculate reset date for limits
 */
function calculateResetDate(period: 'daily' | 'weekly' | 'monthly'): Date {
  const now = new Date();

  if (period === 'daily') {
    return new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
  } else if (period === 'weekly') {
    const nextMonday = new Date(now);
    nextMonday.setDate(now.getDate() + ((1 + 7 - now.getDay()) % 7));
    return nextMonday;
  } else {
    return new Date(now.getFullYear(), now.getMonth() + 1, 1);
  }
}

/**
 * Check if player can deposit
 */
export function canPlayerDeposit(settings: ResponsibleGamblingSettings, depositAmount: number): boolean {
  if (settings.selfExclusion?.enabled) {
    return false;
  }

  if (settings.coolOff?.enabled && new Date() < settings.coolOff.endDate) {
    return false;
  }

  if (settings.depositLimit?.enabled) {
    if (settings.depositLimit.currentSpent + depositAmount > settings.depositLimit.amount) {
      return false;
    }
  }

  return true;
}

/**
 * Check if player can play
 */
export function canPlayerPlay(settings: ResponsibleGamblingSettings): boolean {
  if (settings.selfExclusion?.enabled && new Date() < settings.selfExclusion.endDate) {
    return false;
  }

  if (settings.coolOff?.enabled && new Date() < settings.coolOff.endDate) {
    return false;
  }

  return true;
}

/**
 * Create compliance event
 */
export function createComplianceEvent(
  playerId: number,
  eventType: 'kyc_submitted' | 'kyc_approved' | 'kyc_rejected' | 'aml_check' | 'deposit_limit_set' | 'self_exclusion_activated' | 'verification_expired',
  details: Record<string, any>,
  reviewedBy?: number,
  notes?: string
): ComplianceEvent {
  return {
    id: `comp_${playerId}_${Date.now()}`,
    playerId,
    eventType,
    timestamp: new Date(),
    details,
    reviewedBy,
    notes,
  };
}

/**
 * Generate compliance report
 */
export function generateComplianceReport(
  period: 'daily' | 'weekly' | 'monthly',
  startDate: Date,
  endDate: Date,
  totalPlayers: number,
  verifiedPlayers: number,
  pendingVerification: number,
  amlChecksPassed: number,
  amlChecksFailed: number,
  amlChecksManualReview: number,
  highRiskPlayers: number,
  selfExcludedPlayers: number,
  depositLimitedPlayers: number
): ComplianceReport {
  const totalAMLChecks = amlChecksPassed + amlChecksFailed + amlChecksManualReview;
  const amlPassRate = totalAMLChecks > 0 ? (amlChecksPassed / totalAMLChecks) * 100 : 100;
  const verificationRate = totalPlayers > 0 ? (verifiedPlayers / totalPlayers) * 100 : 0;

  // Compliance score: 100 = perfect compliance
  let complianceScore = 100;
  complianceScore -= (pendingVerification / totalPlayers) * 10; // Pending verifications reduce score
  complianceScore -= (amlChecksFailed / totalAMLChecks) * 20; // Failed AML checks reduce score
  complianceScore -= (highRiskPlayers / totalPlayers) * 15; // High-risk players reduce score

  return {
    id: `report_${Date.now()}`,
    period,
    startDate,
    endDate,
    totalPlayers,
    verifiedPlayers,
    pendingVerification,
    amlChecksPassed,
    amlChecksFailed,
    amlChecksManualReview,
    highRiskPlayers,
    selfExcludedPlayers,
    depositLimitedPlayers,
    complianceScore: Math.max(0, complianceScore),
  };
}

/**
 * Calculate risk level
 */
export function calculateRiskLevel(
  amlCheck: AMLCheck,
  profile: KYCProfile,
  transactionHistory: { largeTransactions: number; rapidWithdrawals: number }
): RiskLevel {
  let riskScore = amlCheck.riskScore;

  // Add points for risk factors
  if (amlCheck.matchedLists.length > 0) {
    riskScore += 20;
  }

  if (transactionHistory.largeTransactions > 5) {
    riskScore += 15;
  }

  if (transactionHistory.rapidWithdrawals > 3) {
    riskScore += 15;
  }

  if (profile.documents.length === 0) {
    riskScore += 10;
  }

  if (riskScore > 75) {
    return 'critical';
  } else if (riskScore > 50) {
    return 'high';
  } else if (riskScore > 25) {
    return 'medium';
  } else {
    return 'low';
  }
}

/**
 * Verify KYC expiration
 */
export function isKYCExpired(profile: KYCProfile): boolean {
  if (!profile.expiresAt) {
    return false;
  }
  return new Date() > profile.expiresAt;
}

/**
 * Renew KYC verification
 */
export function renewKYCVerification(profile: KYCProfile): void {
  profile.verificationStatus = 'pending';
  profile.verifiedAt = undefined;
  profile.expiresAt = undefined;
  profile.updatedAt = new Date();
}
