import { IsString, IsEmail, IsBoolean, IsOptional, IsArray, MinLength, IsNumber, IsEnum } from 'class-validator';

// ==================== TYPES AND ENUMS ====================

export type PartnerStatus = 
  | 'ACTIVE'
  | 'INACTIVE'

export type PartnerCategory =
  | 'E_COMMERCE'
  | 'GAMING'
  | 'ENTERTAINMENT'
  | 'UTILITIES'
  | 'DIGITAL_CONTENT'
  | 'SERVICES'
  | 'OTHER';

// ==================== CALLBACK CONFIGURATION ====================

export interface CallbackConfiguration {
  headerEnrichment?: {
    url?: string;
    method?: 'GET' | 'POST';
    headers?: { [key: string]: string };
  };
  subscription?: {
    onCreate?: string;
    onRenew?: string;
    onCancel?: string;
    onExpire?: string;
  };
  payment?: {
    onSuccess?: string;
    onFailure?: string;
    onRefund?: string;
  };
  authentication?: {
    onSuccess?: string;
    onFailure?: string;
  };
}

export class CallbackConfigurationImpl implements CallbackConfiguration {
  headerEnrichment?: {
    url?: string;
    method?: 'GET' | 'POST';
    headers?: { [key: string]: string };
  } = {};
  
  subscription?: {
    onCreate?: string;
    onRenew?: string;
    onCancel?: string;
    onExpire?: string;
  } = {};
  
  payment?: {
    onSuccess?: string;
    onFailure?: string;
    onRefund?: string;
  } = {};
  
  authentication?: {
    onSuccess?: string;
    onFailure?: string;
  } = {};

  constructor(partial?: Partial<CallbackConfiguration>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

// ==================== CORE PARTNER MODELS ====================

export class PartnerAddress {
  @IsString()
  street: string = '';

  @IsString()
  city: string = '';

  @IsString()
  state: string = '';

  @IsString()
  postalCode: string = '';

  @IsString()
  country: string = '';

  constructor(partial?: Partial<PartnerAddress>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class TechnicalContact {
  @IsString()
  name: string = '';

  @IsEmail()
  email: string = '';

  @IsString()
  phone: string = '';

  constructor(partial?: Partial<TechnicalContact>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class PartnerStats {
  @IsNumber()
  totalTransactions: number = 0;

  @IsNumber()
  totalRevenue: number = 0;

  @IsNumber()
  successRate: number = 0;

  @IsNumber()
  refundRate: number = 0;

  @IsNumber()
  averageAmount: number = 0;

  @IsNumber()
  todayTransactions: number = 0;

  @IsNumber()
  todayRevenue: number = 0;

  @IsNumber()
  activeProducts: number = 0;

  lastTransactionDate?: Date;

  constructor(partial?: Partial<PartnerStats>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class Partner {
  id: string = '';
  name: string = '';
  legalName: string = '';
  email: string = '';
  phone: string = '';
  website: string = '';
  
  @IsEnum(['ACTIVE', 'INACTIVE'])
  status: PartnerStatus = 'ACTIVE';
  
  @IsEnum(['E_COMMERCE', 'GAMING', 'ENTERTAINMENT', 'UTILITIES', 'DIGITAL_CONTENT', 'SERVICES', 'OTHER'])
  category: PartnerCategory = 'OTHER';
  
  country: string = '';
  currency: string = '';
  timezone: string = '';
  
  // Configuration technique
  apiKey: string = '';
  secretKey: string = '';
  webhookUrl: string = '';

  callbacks: CallbackConfiguration = new CallbackConfigurationImpl();
  
  // Limites et commissions
  @IsNumber()
  commissionRate: number = 0;
  
  @IsNumber()
  dailyLimit: number = 0;
  
  @IsNumber()
  transactionLimit: number = 0;
  
  @IsNumber()
  minAmount: number = 0;
  
  @IsNumber()
  maxAmount: number = 0;
  
  // Adresse
  address: PartnerAddress = new PartnerAddress();
  
  // Contact technique
  technicalContact: TechnicalContact = new TechnicalContact();
  
  // Statistiques
  stats: PartnerStats = new PartnerStats();
  
  // Métadonnées
  createdAt: Date = new Date();
  updatedAt: Date = new Date();
  createdBy: string = '';

  constructor(partial?: Partial<Partner>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

// ==================== PARTNER DTOs ====================

export class CreatePartnerDto {
  @IsString()
  name: string = '';

  @IsString()
  legalName: string = '';

  @IsEmail()
  email: string = '';

  @IsString()
  phone: string = '';

  @IsOptional()
  @IsString()
  website: string = '';

  @IsEnum(['E_COMMERCE', 'GAMING', 'ENTERTAINMENT', 'UTILITIES', 'DIGITAL_CONTENT', 'SERVICES', 'OTHER'])
  category: PartnerCategory = 'OTHER';

  @IsString()
  country: string = '';

  @IsString()
  currency: string = '';

  @IsString()
  timezone: string = '';

  @IsNumber()
  commissionRate: number = 0;

  @IsNumber()
  dailyLimit: number = 0;

  @IsNumber()
  transactionLimit: number = 0;

  @IsNumber()
  minAmount: number = 0;

  @IsNumber()
  maxAmount: number = 0;

  @IsOptional()
  address?: PartnerAddress;

  @IsOptional()
  technicalContact?: TechnicalContact;

  constructor(partial?: Partial<CreatePartnerDto>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class UpdatePartnerDto {
  @IsOptional()
  @IsString()
  name?: string;

  @IsOptional()
  @IsString()
  legalName?: string;

  @IsOptional()
  @IsEmail()
  email?: string;

  @IsOptional()
  @IsString()
  phone?: string;

  @IsOptional()
  @IsString()
  website?: string;

  @IsOptional()
  @IsEnum(['ACTIVE', 'INACTIVE', 'SUSPENDED', 'PENDING_VERIFICATION', 'BLOCKED'])
  status?: PartnerStatus;

  @IsOptional()
  @IsEnum(['E_COMMERCE', 'GAMING', 'ENTERTAINMENT', 'UTILITIES', 'DIGITAL_CONTENT', 'SERVICES', 'OTHER'])
  category?: PartnerCategory;

  @IsOptional()
  @IsNumber()
  commissionRate?: number;

  @IsOptional()
  @IsNumber()
  dailyLimit?: number;

  @IsOptional()
  @IsNumber()
  transactionLimit?: number;

  @IsOptional()
  @IsNumber()
  minAmount?: number;

  @IsOptional()
  @IsNumber()
  maxAmount?: number;

  @IsOptional()
  address?: PartnerAddress;

  @IsOptional()
  technicalContact?: TechnicalContact;

  constructor(partial?: Partial<UpdatePartnerDto>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class UpdateCallbacksDto {
  @IsOptional()
  callbacks?: CallbackConfiguration;

  constructor(partial?: Partial<UpdateCallbacksDto>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

// ==================== QUERY AND PAGINATION ====================

export class PartnerQuery {
  @IsOptional()
  page: number = 1;

  @IsOptional()
  limit: number = 10;

  @IsOptional()
  @IsString()
  search?: string;

  @IsOptional()
  @IsEnum(['ACTIVE', 'INACTIVE', 'SUSPENDED', 'PENDING_VERIFICATION', 'BLOCKED'])
  status?: PartnerStatus;

  @IsOptional()
  @IsEnum(['E_COMMERCE', 'GAMING', 'ENTERTAINMENT', 'UTILITIES', 'DIGITAL_CONTENT', 'SERVICES', 'OTHER'])
  category?: PartnerCategory;

  @IsOptional()
  @IsString()
  country?: string;

  @IsOptional()
  @IsString()
  sortBy?: string;

  @IsOptional()
  @IsEnum(['asc', 'desc'])
  sortOrder: 'asc' | 'desc' = 'desc';

  constructor(partial?: Partial<PartnerQuery>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class PaginatedPartners {
  data: Partner[] = [];
  total: number = 0;
  page: number = 1;
  limit: number = 10;
  totalPages: number = 0;

  constructor(data: Partner[] = [], total: number = 0, page: number = 1, limit: number = 10) {
    this.data = data;
    this.total = total;
    this.page = page;
    this.limit = limit;
    this.totalPages = Math.ceil(total / limit) || 0;
  }
}

// ==================== API RESPONSES ====================

export class ApiResponse<T> {
  success: boolean = false;
  data?: T = undefined;
  error?: string = '';
  message?: string = '';

  constructor(partial?: Partial<ApiResponse<T>>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class ApiKeyResponse {
  apiKey: string = '';
  secretKey: string = '';
  partnerId: string = '';
  createdAt: Date = new Date();

  constructor(partial?: Partial<ApiKeyResponse>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

// ==================== PARTNER FORM DATA ====================

export interface PartnerFormData {
  companyInfo: {
    name: string;
    legalName: string;
    taxId: string;
    address: string;
    country: string;
  };
  contactInfo: {
    email: string;
    phone: string;
    firstName: string;
    lastName: string;
  };
  paymentConfig: {
    supportedOperators: string[];
    defaultCurrency: string;
    maxTransactionAmount: number;
  };
  webhookConfig: CallbackConfiguration;
}

export class PartnerFormDataImpl implements PartnerFormData {
  companyInfo: {
    name: string;
    legalName: string;
    taxId: string;
    address: string;
    country: string;
  } = {
    name: '',
    legalName: '',
    taxId: '',
    address: '',
    country: 'CIV'
  };
  
  contactInfo: {
    email: string;
    phone: string;
    firstName: string;
    lastName: string;
  } = {
    email: '',
    phone: '',
    firstName: '',
    lastName: ''
  };
  
  paymentConfig: {
    supportedOperators: string[];
    defaultCurrency: string;
    maxTransactionAmount: number;
  } = {
    supportedOperators: [],
    defaultCurrency: 'XOF',
    maxTransactionAmount: 50000
  };
  
  webhookConfig: CallbackConfiguration = new CallbackConfigurationImpl();

  constructor(partial?: Partial<PartnerFormData>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

// ==================== PARTNER PRODUCT ====================

export class PartnerProduct {
  id: string = '';
  partnerId: string = '';
  
  @IsString()
  name: string = '';

  @IsString()
  description: string = '';

  @IsNumber()
  price: number = 0;

  @IsString()
  currency: string = '';

  @IsString()
  category: string = '';

  @IsEnum(['ACTIVE', 'INACTIVE', 'SUSPENDED'])
  status: 'ACTIVE' | 'INACTIVE' | 'SUSPENDED' = 'ACTIVE';

  createdAt: Date = new Date();
  updatedAt: Date = new Date();

  constructor(partial?: Partial<PartnerProduct>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}