/**
 * AvatarService - Gestión de Avatares de Usuario
 *
 * Manejo de imágenes de perfil: upload, resize, storage.
 * Integración con StorageService para almacenamiento.
 *
 * @module Profiles
 */

import { DataSource } from 'typeorm';
import * as crypto from 'crypto';

interface ServiceContext {
  tenantId: string;
  userId?: string;
}

/* eslint-disable @typescript-eslint/no-unused-vars */

/**
 * Avatar metadata stored with user
 */
export interface AvatarInfo {
  avatarUrl: string | null;
  avatarKey: string | null;
  avatarThumbnailUrl: string | null;
  avatarUpdatedAt: Date | null;
}

export interface UploadAvatarDto {
  userId: string;
  fileBuffer: Buffer;
  mimeType: string;
  originalName: string;
}

export interface AvatarOptions {
  maxSizeBytes?: number;
  allowedMimeTypes?: string[];
  thumbnailSize?: number;
  defaultAvatar?: string;
}

const DEFAULT_OPTIONS: AvatarOptions = {
  maxSizeBytes: 5 * 1024 * 1024, // 5MB
  allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
  thumbnailSize: 150,
  defaultAvatar: '/assets/default-avatar.png',
};

export class AvatarService {
  private options: AvatarOptions;

  constructor(_dataSource: DataSource, options: AvatarOptions = {}) {
    this.options = { ...DEFAULT_OPTIONS, ...options };
  }

  /**
   * Validate avatar file before upload
   */
  validateFile(fileBuffer: Buffer, mimeType: string): { valid: boolean; error?: string } {
    // Check size
    if (fileBuffer.length > (this.options.maxSizeBytes || 5 * 1024 * 1024)) {
      return {
        valid: false,
        error: `File size exceeds maximum of ${Math.round((this.options.maxSizeBytes || 5 * 1024 * 1024) / 1024 / 1024)}MB`,
      };
    }

    // Check mime type
    if (!this.options.allowedMimeTypes?.includes(mimeType)) {
      return {
        valid: false,
        error: `File type ${mimeType} is not allowed. Allowed types: ${this.options.allowedMimeTypes?.join(', ')}`,
      };
    }

    return { valid: true };
  }

  /**
   * Generate avatar storage key
   */
  generateAvatarKey(userId: string): string {
    const timestamp = Date.now();
    const random = crypto.randomBytes(4).toString('hex');
    return `avatars/${userId}/${timestamp}_${random}`;
  }

  /**
   * Upload avatar for a user
   * Returns storage key and URLs
   */
  async uploadAvatar(_ctx: ServiceContext, dto: UploadAvatarDto): Promise<AvatarUploadResult> {
    // Validate file
    const validation = this.validateFile(dto.fileBuffer, dto.mimeType);
    if (!validation.valid) {
      throw new Error(validation.error);
    }

    // Generate storage key
    const avatarKey = this.generateAvatarKey(dto.userId);
    const extension = this.getExtensionFromMimeType(dto.mimeType);
    const fullKey = `${avatarKey}.${extension}`;
    const thumbnailKey = `${avatarKey}_thumb.${extension}`;

    // In a real implementation, this would:
    // 1. Upload to storage (S3, GCS, local, etc.)
    // 2. Generate thumbnail
    // 3. Return URLs
    // For now, we return placeholder URLs based on the key

    const baseUrl = process.env.STORAGE_BASE_URL || '/api/storage';
    const avatarUrl = `${baseUrl}/${fullKey}`;
    const thumbnailUrl = `${baseUrl}/${thumbnailKey}`;

    return {
      avatarKey: fullKey,
      avatarUrl,
      thumbnailUrl,
      sizeBytes: dto.fileBuffer.length,
      mimeType: dto.mimeType,
    };
  }

  /**
   * Delete avatar from storage
   */
  async deleteAvatar(_ctx: ServiceContext, avatarKey: string): Promise<boolean> {
    if (!avatarKey) {
      return false;
    }

    // In a real implementation, this would delete from storage
    // For now, just return true to indicate success
    return true;
  }

  /**
   * Get default avatar URL
   */
  getDefaultAvatar(name?: string): string {
    if (name) {
      // Generate initials-based avatar URL using UI Avatars service
      const initials = this.getInitials(name);
      return `https://ui-avatars.com/api/?name=${encodeURIComponent(initials)}&background=random&size=150`;
    }
    return this.options.defaultAvatar || '/assets/default-avatar.png';
  }

  /**
   * Extract initials from name
   */
  private getInitials(name: string): string {
    const parts = name.trim().split(/\s+/);
    if (parts.length === 0) return '?';
    if (parts.length === 1) return parts[0].charAt(0).toUpperCase();
    return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
  }

  /**
   * Get file extension from mime type
   */
  private getExtensionFromMimeType(mimeType: string): string {
    const mimeToExt: Record<string, string> = {
      'image/jpeg': 'jpg',
      'image/png': 'png',
      'image/gif': 'gif',
      'image/webp': 'webp',
    };
    return mimeToExt[mimeType] || 'jpg';
  }

  /**
   * Generate presigned upload URL for client-side upload
   */
  async generateUploadUrl(
    _ctx: ServiceContext,
    userId: string,
    mimeType: string
  ): Promise<{ uploadUrl: string; avatarKey: string; expiresAt: Date }> {
    // Validate mime type
    if (!this.options.allowedMimeTypes?.includes(mimeType)) {
      throw new Error(`File type ${mimeType} is not allowed`);
    }

    const avatarKey = this.generateAvatarKey(userId);
    const extension = this.getExtensionFromMimeType(mimeType);
    const fullKey = `${avatarKey}.${extension}`;

    const expiresAt = new Date();
    expiresAt.setMinutes(expiresAt.getMinutes() + 15);

    // In a real implementation, generate presigned URL from storage provider
    const uploadUrl = `/api/storage/upload?key=${encodeURIComponent(fullKey)}`;

    return {
      uploadUrl,
      avatarKey: fullKey,
      expiresAt,
    };
  }

  /**
   * Complete upload after file is received
   */
  async completeUpload(
    _ctx: ServiceContext,
    _userId: string,
    avatarKey: string
  ): Promise<AvatarInfo> {
    const baseUrl = process.env.STORAGE_BASE_URL || '/api/storage';
    const avatarUrl = `${baseUrl}/${avatarKey}`;
    const thumbnailKey = avatarKey.replace(/\.(\w+)$/, '_thumb.$1');
    const thumbnailUrl = `${baseUrl}/${thumbnailKey}`;

    return {
      avatarUrl,
      avatarKey,
      avatarThumbnailUrl: thumbnailUrl,
      avatarUpdatedAt: new Date(),
    };
  }
}

export interface AvatarUploadResult {
  avatarKey: string;
  avatarUrl: string;
  thumbnailUrl: string;
  sizeBytes: number;
  mimeType: string;
}
