import sharp from 'sharp';
import { uploadFile, deleteFile, getPreviewUrl } from './minio';
import { getNocoDbConfiguration, Table, createTableUrl } from './nocodb';
import type { Member } from '~/utils/types';
import type { EntityResponse } from './nocodb';

interface ThumbnailSizes {
  small: { width: 64, height: 64 };
  medium: { width: 200, height: 200 };
}

const THUMBNAIL_SIZES: ThumbnailSizes = {
  small: { width: 64, height: 64 },   // For header avatar
  medium: { width: 200, height: 200 } // For profile cards and profile page
};

/**
 * Upload profile image with automatic thumbnail generation
 */
export const uploadProfileImage = async (
  memberId: string, 
  buffer: Buffer, 
  originalName: string
): Promise<string> => {
  if (!memberId) {
    throw new Error('Member ID is required for profile image upload');
  }

  try {
    // Validate image format
    const metadata = await sharp(buffer).metadata();
    if (!metadata.format || !['jpeg', 'jpg', 'png', 'webp'].includes(metadata.format)) {
      throw new Error('Invalid image format. Only JPEG, PNG, and WebP are supported.');
    }

    // Ensure minimum dimensions
    if (!metadata.width || !metadata.height || metadata.width < 100 || metadata.height < 100) {
      throw new Error('Image must be at least 100x100 pixels.');
    }

    const basePath = `profile-images/${memberId}`;
    const timestamp = Date.now();
    
    // Process original image (convert to JPEG for consistency)
    const processedBuffer = await sharp(buffer)
      .jpeg({ quality: 90, mozjpeg: true })
      .toBuffer();
    
    const originalPath = `${basePath}/profile.jpg`;
    
    // Generate thumbnails
    const thumbnails: Record<string, Buffer> = {};
    for (const [sizeName, dimensions] of Object.entries(THUMBNAIL_SIZES)) {
      thumbnails[sizeName] = await sharp(buffer)
        .resize(dimensions.width, dimensions.height, {
          fit: 'cover',
          position: 'center'
        })
        .jpeg({ quality: 85 })
        .toBuffer();
    }

    // Upload original image
    await uploadFile(originalPath, processedBuffer, 'image/jpeg');
    console.log(`✅ Uploaded profile image: ${originalPath}`);

    // Upload thumbnails
    for (const [sizeName, thumbnailBuffer] of Object.entries(thumbnails)) {
      const thumbnailPath = `${basePath}/profile_${sizeName}.jpg`;
      await uploadFile(thumbnailPath, thumbnailBuffer, 'image/jpeg');
      console.log(`✅ Generated ${sizeName} thumbnail: ${thumbnailPath}`);
    }

    return originalPath;
  } catch (error) {
    console.error('Failed to upload profile image:', error);
    throw error;
  }
};

/**
 * Delete profile image and all associated thumbnails
 */
export const deleteProfileImage = async (memberId: string): Promise<void> => {
  if (!memberId) {
    throw new Error('Member ID is required for profile image deletion');
  }

  try {
    const basePath = `profile-images/${memberId}`;
    
    // Delete original image
    try {
      await deleteFile(`${basePath}/profile.jpg`);
      console.log(`🗑️ Deleted profile image: ${basePath}/profile.jpg`);
    } catch (error) {
      console.warn('Original profile image not found or already deleted');
    }
    
    // Delete thumbnails
    for (const sizeName of Object.keys(THUMBNAIL_SIZES)) {
      try {
        await deleteFile(`${basePath}/profile_${sizeName}.jpg`);
        console.log(`🗑️ Deleted ${sizeName} thumbnail: ${basePath}/profile_${sizeName}.jpg`);
      } catch (error) {
        console.warn(`${sizeName} thumbnail not found or already deleted`);
      }
    }
  } catch (error) {
    console.error('Failed to delete profile image:', error);
    throw error;
  }
};

/**
 * Get profile image URL for display
 */
export const getProfileImageUrl = async (
  memberId: string, 
  size: 'original' | 'small' | 'medium' = 'original'
): Promise<string | null> => {
  if (!memberId) {
    return null;
  }

  try {
    const basePath = `profile-images/${memberId}`;
    let imagePath: string;

    if (size === 'original') {
      imagePath = `${basePath}/profile.jpg`;
    } else {
      imagePath = `${basePath}/profile_${size}.jpg`;
    }

    // Generate presigned URL
    const url = await getPreviewUrl(imagePath, 'image/jpeg');
    return url;
  } catch (error) {
    console.warn(`Profile image not found for member ${memberId}, size ${size}`);
    return null;
  }
};

/**
 * Update member profile image URL in NocoDB
 */
export const updateMemberProfileImageUrl = async (
  memberId: string, 
  imagePath: string, 
  originalName: string
): Promise<void> => {
  try {
    // Find member by member_id using existing pattern
    const response = await $fetch<EntityResponse<Member>>(createTableUrl(Table.Members), {
      headers: {
        "xc-token": getNocoDbConfiguration().token,
      },
      params: {
        where: `(member_id,eq,${memberId})`,
        limit: 1,
      },
    });

    if (!response.list || response.list.length === 0) {
      throw new Error(`Member not found with ID: ${memberId}`);
    }

    const member = response.list[0];
    
    // Update profile image fields using PATCH method
    const updateData = {
      Id: parseInt(member.Id),
      profile_image_url: imagePath,
      profile_image_updated_at: new Date().toISOString(),
      profile_image_original_name: originalName
    };

    await $fetch(createTableUrl(Table.Members), {
      method: "PATCH",
      headers: {
        "xc-token": getNocoDbConfiguration().token,
        "Content-Type": "application/json"
      },
      body: updateData
    });

    console.log(`✅ Updated profile image URL for member ${memberId}`);
  } catch (error) {
    console.error('Failed to update member profile image URL:', error);
    throw error;
  }
};

/**
 * Remove member profile image URL from NocoDB
 */
export const removeMemberProfileImageUrl = async (memberId: string): Promise<void> => {
  try {
    // Find member by member_id using existing pattern
    const response = await $fetch<EntityResponse<Member>>(createTableUrl(Table.Members), {
      headers: {
        "xc-token": getNocoDbConfiguration().token,
      },
      params: {
        where: `(member_id,eq,${memberId})`,
        limit: 1,
      },
    });

    if (!response.list || response.list.length === 0) {
      throw new Error(`Member not found with ID: ${memberId}`);
    }

    const member = response.list[0];
    
    // Clear profile image fields using PATCH method
    const updateData = {
      Id: parseInt(member.Id),
      profile_image_url: null,
      profile_image_updated_at: new Date().toISOString(),
      profile_image_original_name: null
    };

    await $fetch(createTableUrl(Table.Members), {
      method: "PATCH",
      headers: {
        "xc-token": getNocoDbConfiguration().token,
        "Content-Type": "application/json"
      },
      body: updateData
    });

    console.log(`✅ Removed profile image URL for member ${memberId}`);
  } catch (error) {
    console.error('Failed to remove member profile image URL:', error);
    throw error;
  }
};

/**
 * Validate image file before processing
 */
export const validateImageFile = (buffer: Buffer, filename: string): void => {
  // Check file size (5MB max)
  const maxSize = 5 * 1024 * 1024;
  if (buffer.length > maxSize) {
    throw new Error('Image file size must be less than 5MB');
  }

  // Check file extension
  const allowedExtensions = ['.jpg', '.jpeg', '.png', '.webp'];
  const extension = filename.toLowerCase().substring(filename.lastIndexOf('.'));
  if (!allowedExtensions.includes(extension)) {
    throw new Error('Only JPEG, PNG, and WebP image files are allowed');
  }
};

/**
 * Generate user initials from name (fallback for missing profile images)
 */
export const generateInitials = (firstName?: string, lastName?: string, fullName?: string): string => {
  if (firstName && lastName) {
    return `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase();
  }
  
  if (fullName) {
    const names = fullName.trim().split(' ');
    if (names.length >= 2) {
      return `${names[0].charAt(0)}${names[names.length - 1].charAt(0)}`.toUpperCase();
    }
    return names[0].charAt(0).toUpperCase();
  }
  
  return '?';
};

/**
 * Generate background color for initials based on name
 */
export const generateAvatarColor = (name: string): string => {
  const colors = [
    '#f44336', '#e91e63', '#9c27b0', '#673ab7',
    '#3f51b5', '#2196f3', '#03a9f4', '#00bcd4',
    '#009688', '#4caf50', '#8bc34a', '#cddc39',
    '#ff9800', '#ff5722', '#795548', '#607d8b'
  ];
  
  let hash = 0;
  for (let i = 0; i < name.length; i++) {
    hash = name.charCodeAt(i) + ((hash << 5) - hash);
  }
  
  const index = Math.abs(hash) % colors.length;
  return colors[index];
};
