import PocketBase from 'pocketbase';
import { v4 as uuidv4 } from 'uuid'; // Import uuid

const pbUrl = import.meta.env.VITE_POCKETBASE_URL;

if (!pbUrl) {
  console.error('Missing VITE_POCKETBASE_URL environment variable');
  throw new Error('Missing VITE_POCKETBASE_URL environment variable');
}

const pb = new PocketBase(pbUrl);

// Disable auto-cancellation to prevent issues with concurrent requests
pb.autoCancellation(false);

// --- Media Types Definition ---
// Define the available media types and their display labels
export const mediaTypes = {
  movie: { label: 'Фильм' },
  tv: { label: 'Сериал' },
  game: { label: 'Игра' },
  anime: { label: 'Аниме' },
  // Add other types here if needed
};


// --- XP and Level Calculation ---

// Simple function to calculate level based on XP
// This is a basic example, you might want a more complex formula or lookup table
export const calculateLevel = (xp) => {
    if (xp < 50) return 1;
    if (xp < 150) return 2;
    if (xp < 300) return 3;
    if (xp < 500) return 4;
    if (xp < 800) return 5;
    if (xp < 1200) return 6;
    if (xp < 1700) return 7;
    if (xp < 2300) return 8;
    if (xp < 3000) return 9;
    if (xp < 4000) return 10;
    // Add more levels as needed
    return 10 + Math.floor((xp - 4000) / 1000); // Example: +1 level every 1000 XP after level 10
};

// Function to get the XP required for the next level
export const getXpForNextLevel = (currentLevel) => {
    // This should correspond to the thresholds in calculateLevel
    // For level N, the next level is N+1. We need the minimum XP for level N+1.
    switch (currentLevel) {
        case 1: return 50;
        case 2: return 150;
        case 3: return 300;
        case 4: return 500;
        case 5: return 800;
        case 6: return 1200;
        case 7: return 1700;
        case 8: return 2300;
        case 9: return 3000;
        case 10: return 4000;
        default:
            // For levels > 10, each level requires 1000 XP more than the start of the previous level range
            // Level N (N > 10) starts at 4000 + (N - 10) * 1000
            return 4000 + (currentLevel - 10) * 1000;
    }
};

// Function to get the XP required for the current level (the starting point)
export const getXpForCurrentLevel = (currentLevel) => {
     if (currentLevel <= 1) return 0; // Level 1 starts at 0 XP
     // For levels > 1, the start XP is the XP needed for the current level
     return getXpForNextLevel(currentLevel - 1);
};


// --- Auth Functions ---

// PocketBase uses a single sign-up function for users
export const signUp = async (login, password, email = null) => {
  try {
    const formData = new FormData();
    formData.append('login', login);
    formData.append('username', login);
    formData.append('email', email || '');
    formData.append('password', password);
    formData.append('passwordConfirm', password);
    formData.append('emailVisibility', 'false');
    formData.append('role', 'user');
    formData.append('is_critic', 'false');
    formData.append('description', '');
    formData.append('review_count', '0');
    formData.append('average_rating', '0');
    formData.append('xp', '0');
    formData.append('level', '1');
    formData.append('showcase', '[]');

    const record = await pb.collection('users').create(formData);
    pb.authStore.clear();
    const authData = await pb.collection('users').authWithPassword(login, password);
    return { user: authData.record, profile: authData.record };

  } catch (error) {
    console.error('PocketBase: Ошибка при регистрации:', error);
    throw error;
  }
};

export const signIn = async (login, password) => {
  try {
    const authData = await pb.collection('users').authWithPassword(login, password);
    return authData.record;
  } catch (error) {
    console.error('PocketBase: Ошибка входа:', error);
    if (error.response && error.response.data) {
      if (error.response.data.message) {
        if (error.response.data.message.includes('Invalid login credentials')) {
          throw new Error('Неверный логин или пароль');
        }
        if (error.response.data.message.includes('Failed to authenticate')) {
          throw new Error('Неверный логин или пароль');
        }
        throw new Error(error.response.data.message);
      }
    }
    throw new Error('Произошла ошибка при входе. Пожалуйста, попробуйте позже.');
  }
};

export const signOut = async () => {
  try {
    pb.authStore.clear();
  } catch (error) {
    console.error('PocketBase: Ошибка выхода:', error);
    throw error;
  }
};

export const getCurrentUser = () => {
  return pb.authStore.isValid ? pb.authStore.model : null;
};

// New function to request password reset
export const requestPasswordReset = async (email) => {
  try {
    await pb.collection('users').requestPasswordReset(email);
    return true;
  } catch (error) {
    console.error('PocketBase: Ошибка при запроса сброса пароля:', error);
    throw error;
  }
};


// --- User Functions (PocketBase 'users' collection) ---
export const getUserProfile = async (userId) => {
  try {
    const record = await pb.collection('users').getOne(userId, {
      expand: 'showcase,showcase.media_id,showcase.season_id'
    });
    return record;
  } catch (error) {
    console.error('[PocketBase] Ошибка загрузки профиля:', error);
    throw error;
  }
};

// New function to get user profile by username
export const getUserProfileByUsername = async (username) => {
  try {
    const userRecord = await pb.collection('users').getFirstListItem(`username="${username}"`, {
      expand: 'showcase,showcase.media_id,showcase.season_id'
    });
    return userRecord;
  } catch (error) {
    console.error('[PocketBase] Профиль не найден:', username);
    throw error;
  }
};

export const getUserProfileByLogin = async (login) => {
    try {
        const records = await pb.collection('users').getList(1, 1, {
            filter: `login = "${login}"`,
            expand: 'showcase,showcase.media_id,showcase.season_id'
        });
        return records.items[0] || null;
    } catch (error) {
        console.error('Error fetching user profile by login:', error);
        throw error;
    }
};

export const updateUserProfile = async (userId, profileData) => {
  try {
    const record = await pb.collection('users').update(userId, profileData);
    return record;
  } catch (error) {
    console.error('PocketBase: Ошибка обновления профиля:', error);
    if (error.response && error.response.data) {
      console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};

// New function to update the user's showcase reviews
export const updateUserShowcase = async (userId, reviewIds) => {
    if (!userId) {
        console.warn('PocketBase: updateUserShowcase called with undefined userId');
        return null;
    }
    if (!Array.isArray(reviewIds) || reviewIds.length > 3) {
        console.error('PocketBase: updateUserShowcase called with invalid reviewIds array (must be array <= 3)');
        throw new Error('Invalid reviewIds array');
    }
    try {
        const updatedUser = await pb.collection('users').update(userId, {
            showcase: reviewIds // Pass the array of review IDs
        });
        return updatedUser;
    } catch (error) {
        console.error('PocketBase: Ошибка обновления витрины пользователя:', error);
        if (error.response && error.response.data) {
            console.error('PocketBase: Response data:', error.response.data);
        }
        throw error;
    }
};

// New function to list users ranked by review count
export const listUsersRankedByReviews = async (limit = 20) => {
    try {
        const records = await pb.collection('users').getList(1, limit, {
            sort: '-review_count',
            filter: 'review_count > 0', // Only include users with at least one review
        });
        return records.items;
    } catch (error) {
        console.error('PocketBase: Ошибка получения списка пользователей по рецензиям:', error);
        throw error;
    }
};

// New function to list users ranked by level
export const listUsersRankedByLevel = async (limit = 20) => {
    try {
        const records = await pb.collection('users').getList(1, limit, {
            sort: '-level,-xp', // Sort by level first, then XP
            filter: 'level > 1 || xp > 0', // Only include users above level 1 or with some XP
        });
        return records.items;
    } catch (error) {
        console.error('PocketBase: Ошибка получения списка пользователей по уровню:', error);
        throw error;
    }
};


// --- Media Functions (PocketBase 'media' collection) ---

// Placeholder/Example validation function - adjust based on your actual media schema
// Now accepts characteristics as an object { key: label }
export const validateMediaData = (formData, characteristics) => {
    const errors = [];
  if (!formData.get('title')) {
        errors.push('Название обязательно.');
    }
  if (!formData.get('type')) {
        errors.push('Тип медиа обязателен.');
    }
  if (!formData.get('progress_type')) { // Validate new field
        errors.push('Тип прогресса обязателен.');
    }
    // Add more validation rules as needed based on your schema

    // Validate characteristic count (min 6, max 8) using the passed object
  const charCount = Object.keys(characteristics).length;
    if (charCount < 6 || charCount > 8) {
         errors.push(`Должно быть от 6 до 8 характеристик (сейчас: ${charCount}).`);
    }

    // Validate that characteristic keys are not empty
  for (const key in characteristics) {
        if (!key.trim()) {
            errors.push('Ключ характеристики не может быть пустым.');
            break; // Stop checking keys after finding one empty
        }
    }

  // Validate position and scale values if they exist
  const posterPosition = formData.get('poster_position');
  const backdropPosition = formData.get('backdrop_position');
  const posterScale = formData.get('poster_scale');
  const backdropScale = formData.get('backdrop_scale');

  if (posterPosition) {
    try {
      const position = JSON.parse(posterPosition);
      if (typeof position.x !== 'number' || typeof position.y !== 'number' ||
          position.x < 0 || position.x > 100 || position.y < 0 || position.y > 100) {
        errors.push('Некорректные значения позиции постера');
      }
    } catch (e) {
      errors.push('Некорректный формат позиции постера');
    }
  }

  if (backdropPosition) {
    try {
      const position = JSON.parse(backdropPosition);
      if (typeof position.x !== 'number' || typeof position.y !== 'number' ||
          position.x < 0 || position.x > 100 || position.y < 0 || position.y > 100) {
        errors.push('Некорректные значения позиции баннера');
      }
    } catch (e) {
      errors.push('Некорректный формат позиции баннера');
    }
  }

  if (posterScale && (isNaN(posterScale) || posterScale < 0.5 || posterScale > 2)) {
    errors.push('Некорректное значение масштаба постера');
  }

  if (backdropScale && (isNaN(backdropScale) || backdropScale < 0.5 || backdropScale > 2)) {
    errors.push('Некорректное значение масштаба баннера');
  }

    return errors;
};

// Placeholder/Example formatting function - adjust based on your actual media schema
// This function is less critical if you're building FormData correctly in the component
// but can be used for final checks or transformations.
export const formatMediaData = (formData) => {
  const data = {
    title: formData.get('title'),
    path: formData.get('path'),
    type: formData.get('type'),
    overview: formData.get('overview'),
    is_published: formData.get('is_published') === 'true',
    is_popular: formData.get('is_popular') === 'true',
    progress_type: formData.get('progress_type'),
    release_date: formData.get('release_date'),
    characteristics: formData.get('characteristics'),
    tmdb_id: formData.get('tmdb_id'),
    tmdb_type: formData.get('tmdb_type')
  };

  // Add position and scale data if they exist
  const posterPosition = formData.get('poster_position');
  const backdropPosition = formData.get('backdrop_position');
  const posterScale = formData.get('poster_scale');
  const backdropScale = formData.get('backdrop_scale');

  if (posterPosition) {
    data.poster_position = posterPosition;
  }
  if (backdropPosition) {
    data.backdrop_position = backdropPosition;
  }
  if (posterScale) {
    data.poster_scale = parseFloat(posterScale);
  }
  if (backdropScale) {
    data.backdrop_scale = parseFloat(backdropScale);
  }

  return data;
};


// createMedia using FormData
export const createMedia = async (mediaData) => {
  try {
    const record = await pb.collection('media').create(mediaData);
    return record;
  } catch (error) {
    console.error('PocketBase: Ошибка создания медиа:', error);
    if (error.response && error.response.data) {
      console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};

// Assuming 'path' is a field in your PocketBase 'media' collection
export const getMediaByPath = async (path) => {
  try {
    const records = await pb.collection('media').getList(1, 1, {
      filter: `path = "${path}"`,
    });

    if (records.items.length > 0) {
       const item = records.items[0];
       return item; // Return the media item with stored stats
    } else {
      return null;
    }
  } catch (error) {
    if (error.status === 404) { // List returns 200 with empty items, getOne returns 404
        return null;
    }
    throw error;
  }
};


export const getMediaById = async (id) => {
  try {
    const record = await pb.collection('media').getOne(id);
    return record; // Return the media item with stored stats

  } catch (error) {
    if (error.status === 404) {
        return null;
    }
    throw error;
  }
};

// listMedia using PocketBase pagination and relations
// Added isPopular filter option
// Added 'published' filter option for admin/critic
export const listMedia = async (
    type = null,
    page = 1,
    limit = 20,
    user = null,
    isPopular = false,
    published = true,
    sort = '-created',
    filterString = ''
) => {
  try {
        let filter = [];

        // Базовые фильтры
        if (published) {
            filter.push('is_published = true');
        }
        
    if (type) {
            filter.push(`type = "${type}"`);
    }

    if (isPopular) {
            filter.push('is_popular = true');
    }

        // Добавляем пользовательские фильтры
        if (filterString) {
            filter.push(`(${filterString})`);
        }

        // Объединяем все фильтры
        const finalFilter = filter.join(' && ');

        const response = await pb.collection('media').getList(page, limit, {
            filter: finalFilter,
            sort: sort,
            expand: 'created_by'
        });

    return {
            data: response.items,
            count: response.totalItems,
            totalPages: response.totalPages
    };
  } catch (error) {
    throw error;
  }
};

// New function to list popular media
export const listPopularMedia = async (limit = 10, user = null) => {
    return listMedia(null, 1, limit, user, true, true); // Ensure popular media is also published
};


// updateMedia using FormData
export const updateMedia = async (id, mediaData) => {
  try {
    const record = await pb.collection('media').update(id, mediaData);
    return record;
  } catch (error) {
    console.error('PocketBase: Ошибка обновления медиа:', error);
    if (error.response && error.response.data) {
      console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};

export const deleteMedia = async (id) => {
  try {
    await pb.collection('media').delete(id);
    return { success: true }; // Indicate success
  } catch (error) {
    console.error('PocketBase: Ошибка удаления медиа:', error);
    throw error;
  }
};

// This function is now primarily for PocketBase backend hooks/triggers
// The frontend will rely on the stored average_rating and review_count
// Generalized function to update rating stats for any collection (media or seasons)
// MODIFIED: If collectionName is 'media', fetch ALL reviews related to this media_id,
// regardless of whether they have a season_id or not.
export const updateRatingStats = async (collectionName, recordId) => {
  if (!recordId) {
     return;
  }
  try {
    let reviewsRecords;
    let filterField;

    if (collectionName === 'media') {
        // For media, fetch ALL reviews where media_id matches
        filterField = 'media_id';
        reviewsRecords = await pb.collection('reviews').getList(1, 500, { // Fetch up to 500 reviews, adjust limit if needed
            filter: `${filterField} = "${recordId}"`,
            fields: 'ratings' // Only fetch the ratings field
        });
    } else if (collectionName === 'seasons') {
        // For seasons, fetch reviews where season_id matches
        filterField = 'season_id';
         reviewsRecords = await pb.collection('reviews').getList(1, 500, { // Fetch up to 500 reviews, adjust limit if needed
            filter: `${filterField} = "${recordId}"`,
            fields: 'ratings' // Only fetch the ratings field
        });
    } else {
        return;
    }


    const reviews = reviewsRecords.items;
    const reviewCount = reviews.length;
    let totalApplicableRating = 0;
    let applicableReviewCount = 0; // Count reviews that have at least one applicable rating

    reviews.forEach(review => {
        let reviewTotal = 0;
        let reviewApplicableCount = 0;

        // Ensure review.ratings is an object before iterating
        if (review.ratings && typeof review.ratings === 'object') {
            // Iterate over values and sum them up directly, assuming { [key]: number } structure
            Object.values(review.ratings).forEach(ratingValue => {
                // Only include numeric values
                if (typeof ratingValue === 'number') {
                    reviewTotal += ratingValue;
                    reviewApplicableCount += 1;
                }
            });
        }

        // Only include this review in the overall average if it has at least one applicable rating
        if (reviewApplicableCount > 0) {
            totalApplicableRating += (reviewTotal / reviewApplicableCount); // Add the average of applicable ratings for this review
            applicableReviewCount += 1; // Count this review as applicable
        }
    });


    let averageRating = 0;
    if (applicableReviewCount > 0) {
      averageRating = totalApplicableRating / applicableReviewCount;
    }

    // Update the record in the specified collection with the new stats
    const updatedRecord = await pb.collection(collectionName).update(recordId, {
      average_rating: parseFloat(averageRating.toFixed(2)),
      review_count: reviewCount // review_count is the total number of reviews, regardless of N/A
    });

    return updatedRecord;

  } catch (error) {
    console.error(`PocketBase: Ошибка обновления среднего рейтинга ${collectionName}:`, error);
    if (error.response && error.response.data) {
      console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};


// --- User Review Stats Update ---
const updateUserReviewStats = async (userId) => {
   if (!userId) {
      return;
   }
   try {
      // Fetch all reviews by this user
      const reviewsRecords = await pb.collection('reviews').getList(1, 500, { // Fetch up to 500 reviews by user
         filter: `user_id = "${userId}"`,
         fields: 'ratings' // Only fetch the ratings field
      });

      const reviews = reviewsRecords.items;
      const reviewCount = reviews.length;
      let totalApplicableRating = 0;
      let applicableReviewCount = 0; // Count reviews that have at least one applicable rating

      reviews.forEach(review => {
          let reviewTotal = 0;
          let reviewApplicableCount = 0;

          // Ensure review.ratings is an object before iterating
          if (review.ratings && typeof review.ratings === 'object') {
              // Iterate over values and sum them up directly, assuming { [key]: number } structure
              Object.values(review.ratings).forEach(ratingValue => {
                  // Only include numeric values
                  if (typeof ratingValue === 'number') {
                      reviewTotal += ratingValue;
                      reviewApplicableCount += 1;
                  }
              });
          }

          // Only include this review in the overall user average if it has at least one applicable rating
          if (reviewApplicableCount > 0) {
              totalApplicableRating += (reviewTotal / reviewApplicableCount); // Add the average of applicable ratings for this review
              applicableReviewCount += 1; // Count this review as applicable
          }
      });


      let averageRating = 0;
      if (applicableReviewCount > 0) {
         averageRating = totalApplicableRating / applicableReviewCount;
      }

      // Update the user record with the new stats
      const updatedUser = await pb.collection('users').update(userId, {
         average_rating: parseFloat(averageRating.toFixed(2)),
         review_count: reviewCount // review_count is the total number of reviews by the user
      });

      return updatedUser;

   } catch (error) {
      console.error('PocketBase: Ошибка обновления статистики обзоров пользователя:', error);
      if (error.response && error.response.data) {
        console.error('PocketBase: Response data:', error.response.data);
    }
      throw error;
   }
};


// --- Review Functions (PocketBase 'reviews' collection) ---
export const getLatestReviews = async (limit = 10) => {
  try {
    const records = await pb.collection('reviews').getList(1, limit, {
      sort: '-created',
      expand: 'user_id,media_id,season_id' // Use the actual relation field names
    });

    return records.items;

  } catch (error) {
    throw error;
  }
};


// Modified to potentially filter by media_id OR season_id
export const getReviewsByMediaId = async (mediaId, seasonId = null, getAllReviews = false) => {
  try {
        let filter = `media_id = "${mediaId}"`;
        
        // Если не запрашиваем все рецензии и указан сезон, добавляем фильтр по сезону
        if (!getAllReviews && seasonId) {
            filter += ` && season_id = "${seasonId}"`;
        }
        
        const records = await pb.collection('reviews').getList(1, 100, {
      filter: filter,
      sort: '-created',
            expand: 'user_id,media_id,season_id'
    });

    return records.items;
  } catch (error) {
    throw error;
  }
};

// New function to get reviews by user ID
export const getReviewsByUserId = async (userId) => {
  try {
    const records = await pb.collection('reviews').getList(1, 500, { // Fetch up to 500 reviews, adjust limit as needed
      filter: `user_id = "${userId}"`,
      sort: '-created',
      expand: 'media_id,user_id,season_id' // Use the actual relation field names
    });

    return records.items;

  } catch (error) {
    throw error;
  }
};


// Modified to potentially get user review for media OR season
export const getUserReviewForMedia = async (userId, mediaId, seasonId = null) => {
  try {
    let filter = `user_id = "${userId}" && media_id = "${mediaId}"`;
     if (seasonId) {
        filter += ` && season_id = "${seasonId}"`; // Filter for a specific season
    } else {
        filter += ` && season_id = null`; // Filter for overall media review (no season)
    }

    // Fetch a single review filtered by user_id and media_id (and optionally season_id), EXPANDING user_id, media_id, and season_id
    const records = await pb.collection('reviews').getList(1, 1, {
      filter: filter,
      expand: 'user_id,media_id,season_id' // Use the actual relation field names
    });

    if (records.items.length > 0) {
      const item = records.items[0];
       // The item now contains the expanded data in the 'expand' field
       // No need for manual fetching and mapping
       return item;
    } else {
      return null;
    }
  } catch (error) {
    throw error;
  }
};

// Fixed XP amount for creating a review
const REVIEW_XP_REWARD = 25;

// Modified to accept season_id
export const createReview = async (reviewData) => {
  try {
    // Add the current user's ID to the review data
    const currentUser = pb.authStore.model;
    if (!currentUser) {
        throw new Error('User not authenticated to create a review.');
    }

    // Calculate overall_rating from the ratings object, EXCLUDING N/A
    let calculatedOverallRating = 0;
    let applicableRatingCount = 0;
    if (reviewData.ratings && typeof reviewData.ratings === 'object') {
        // Iterate over values and sum them up directly, assuming { [key]: number } structure
        Object.values(reviewData.ratings).forEach(ratingValue => {
             // Only include numeric values
             if (typeof ratingValue === 'number') {
                calculatedOverallRating += ratingValue;
                applicableRatingCount += 1;
            }
        });
    }

    if (applicableRatingCount > 0) {
        calculatedOverallRating = calculatedOverallRating / applicableRatingCount;
    } else {
        // If no applicable ratings, set overall to 0
        calculatedOverallRating = 0;
    }


    const dataToSend = {
        ...reviewData,
        user_id: currentUser.id, // Add the user_id
        overall_rating: parseFloat(calculatedOverallRating.toFixed(2)), // Add calculated overall_rating
        // media_id, season_id, content, ratings, has_spoilers, progress fields are expected in reviewData
    };

    // PocketBase create
    const record = await pb.collection('reviews').create(dataToSend);

    // --- Level and XP Logic ---
    // Fetch the user's current XP and level
    const userRecord = await pb.collection('users').getOne(currentUser.id);
    const currentXP = userRecord.xp || 0;
    const newXP = currentXP + REVIEW_XP_REWARD;
    const newLevel = calculateLevel(newXP);

    // Update the user's XP and level
    await pb.collection('users').update(currentUser.id, {
        xp: newXP,
        level: newLevel
    });
    // --- End Level and XP Logic ---


    // After creating a review, update the average rating and review count for the associated media OR season
    if (reviewData.season_id) {
        await updateRatingStats('seasons', reviewData.season_id);
        // Also update the parent media's stats based on ALL reviews (including season reviews)
        await updateRatingStats('media', reviewData.media_id);
    } else if (reviewData.media_id) {
        // If it's an overall media review, just update the media stats
        await updateRatingStats('media', reviewData.media_id);
    }


    // After creating a review, update the user's review stats (average rating and review count)
    // This also implicitly updates the user state in AuthContext via authStore.onChange
    await updateUserReviewStats(currentUser.id);


    return record;
  } catch (error) {
    console.error('PocketBase: Ошибка создания обзора:', error);
    if (error.response && error.response.data) {
      console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};

// Modified to accept season_id in reviewData
export const updateReview = async (reviewId, reviewData) => {
  try {
    // Calculate overall_rating from the ratings object if it's being updated
    let calculatedOverallRating = undefined; // Use undefined so it's not included if ratings isn't in reviewData
    if (reviewData.ratings && typeof reviewData.ratings === 'object') {
        let totalApplicableRating = 0;
        let applicableRatingCount = 0;
        // Iterate over values and sum them up directly, assuming { [key]: number } structure
        Object.values(reviewData.ratings).forEach(ratingValue => {
             // Only include numeric values
             if (typeof ratingValue === 'number') {
                totalApplicableRating += ratingValue; // Corrected variable name
                applicableRatingCount += 1;
            }
        });

        if (applicableRatingCount > 0) {
            calculatedOverallRating = parseFloat((totalApplicableRating / applicableRatingCount).toFixed(2));
        } else {
             // If no applicable ratings, set overall to 0
             calculatedOverallRating = 0;
        }
    }

    const dataToSend = {
        ...reviewData,
        // Only include overall_rating if it was calculated (i.e., ratings was provided)
        ...(calculatedOverallRating !== undefined && { overall_rating: calculatedOverallRating }),
        // media_id, season_id, content, ratings, has_spoilers, progress fields are expected in reviewData
    };


    // PocketBase update requires the record ID
    const record = await pb.collection('reviews').update(reviewId, dataToSend);

    // After updating a review, update the average rating and review count for the associated media OR season
    // Need media_id/season_id from reviewData or fetch the review first
    const mediaIdToUpdate = reviewData.media_id || record.media_id;
    const seasonIdToUpdate = reviewData.season_id || record.season_id;

    if (seasonIdToUpdate) {
        await updateRatingStats('seasons', seasonIdToUpdate);
        // Also update the parent media's stats based on ALL reviews (including season reviews)
        if (mediaIdToUpdate) {
            await updateRatingStats('media', mediaIdToUpdate);
        }
    } else if (mediaIdToUpdate) {
        // If it's an overall media review, just update the media stats
        await updateRatingStats('media', mediaIdToUpdate);
    }


    // After updating a review, update the user's review stats (average rating and review count)
    // XP and Level are NOT updated on review update, only on creation.
    const userIdToUpdate = reviewData.user_id || record.user_id; // Use user_id from update data or the updated record
     if (userIdToUpdate) {
       await updateUserReviewStats(userIdToUpdate);
    }


    return record;
  } catch (error) {
    console.error('PocketBase: Ошибка обновления обзора:', error);
    if (error.response && error.response.data) {
      console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};

// Modified to accept mediaId (optional, for convenience)
export const deleteReview = async (reviewId, mediaId = null) => {
  try {
    // Get the review first to get the user_id, media_id, and season_id before deleting
    const reviewToDelete = await pb.collection('reviews').getOne(reviewId);
    const userIdToUpdate = reviewToDelete?.user_id;
    const mediaIdToUpdate = mediaId || reviewToDelete?.media_id;
    const seasonIdToUpdate = reviewToDelete?.season_id;


    // PocketBase delete requires the record ID
    await pb.collection('reviews').delete(reviewId);

    // After deleting a review, update the average rating and review count for the associated media OR season
    if (seasonIdToUpdate) {
        await updateRatingStats('seasons', seasonIdToUpdate);
        // Also update the parent media's stats based on ALL reviews (including season reviews)
        if (mediaIdToUpdate) {
            await updateRatingStats('media', mediaIdToUpdate);
        }
    } else if (mediaIdToUpdate) {
       // If it was an overall media review, just update the media stats
       await updateRatingStats('media', mediaIdToUpdate);
    }

    // After deleting a review, update the user's review stats (average rating and review count)
    // XP and Level are NOT decreased on review deletion in this basic implementation.
     if (userIdToUpdate) {
       await updateUserReviewStats(userIdToUpdate);
    }


    return true; // Indicate success
  } catch (error) {
    throw error;
  }
};


// --- Achievement Functions ---

/**
 * Fetches all achievements.
 * @returns {Promise<Array<object>>} List of achievement records.
 */
export const getAllAchievements = async () => {
  try {
    const records = await pb.collection('achievements').getFullList({
      sort: 'created', // Or sort by xp_reward, etc.
    });
    return records;
  } catch (error) {
    throw error;
  }
};

/**
 * Fetches achievements for a specific user.
 * @param {string} userId - The ID of the user.
 * @returns {Promise<Array<object>>} List of user_achievement records with expanded achievement data.
 */
export const getUserAchievements = async (userId) => {
  if (!userId) {
    return [];
  }
  try {
    // Fetch user_achievements records, expanding the 'achievement_id' relation
    const records = await pb.collection('user_achievements').getList(1, 500, {
      filter: `user_id = "${userId}"`,
      sort: '-awarded_at',
      expand: 'achievement_id'
    });

    // Преобразуем данные, чтобы использовать достижение напрямую
    return records.items.map(item => ({
      ...item.expand.achievement_id,
      awarded_at: item.awarded_at
    }));

  } catch (error) {
    console.error('Error fetching user achievements:', error);
    return [];
  }
};

/**
 * Awards an achievement to a user (typically called from admin panel).
 * @param {string} userId - The ID of the user to award.
 * @param {string} achievementId - The ID of the achievement to award.
 * @param {string} [awardedByUserId] - The ID of the admin/moderator awarding it (optional).
 * @returns {Promise<object>} The created user_achievement record.
 */
export const awardAchievement = async (userId, achievementId, awardedByUserId = null) => {
  if (!userId || !achievementId) {
    throw new Error('Missing userId or achievementId');
  }
  try {
    // Check if the user already has this achievement to prevent duplicates
    const existing = await pb.collection('user_achievements').getList(1, 1, {
        filter: `user_id = "${userId}" && achievement_id = "${achievementId}"`
    });

    if (existing.items.length > 0) {
        return existing.items[0]; // Return the existing record
    }


    // Create the user_achievement record
    const userAchievementRecord = await pb.collection('user_achievements').create({
      user_id: userId,
      achievement_id: achievementId,
      awarded_by: awardedByUserId, // Can be null
      awarded_at: new Date().toISOString(), // Set current time
    });


    // Fetch the achievement details to get the XP reward
    const achievement = await pb.collection('achievements').getOne(achievementId);
    const xpReward = achievement.xp_reward || 0;

    // Fetch the user's current XP and level
    const userRecord = await pb.collection('users').getOne(userId);
    const currentXP = userRecord.xp || 0;
    const newXP = currentXP + xpReward;
    const newLevel = calculateLevel(newXP);

    // Update the user's XP and level
    await pb.collection('users').update(userId, {
        xp: newXP,
        level: newLevel
    });


    return userAchievementRecord;

  } catch (error) {
    console.error('PocketBase: Ошибка при выдаче достижения:', error);
    if (error.response && error.response.data) {
      console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};


// --- PocketBase File Upload Functions ---

/**
 * Uploads a file to a PocketBase collection record.
 * @param {File} file - The file to upload.
 * @param {string} collectionName - The name of the collection ('users', 'media', etc.).
 * @param {string} recordId - The ID of the record to attach the file to.
 * @param {string} fieldName - The name of the file field in the collection ('profile_picture', 'banner_picture', etc.).
 * @returns {Promise<object>} The updated record object.
 * @throws {Error} If the upload fails.
 */
export const uploadFile = async (file, collectionName, recordId, fieldName) => {
  if (!file) {
    return null; // Or throw an error if file is required
  }

  try {
    // PocketBase file upload is part of updating the record using FormData
    const formData = new FormData();
    formData.append(fieldName, file);

    // Use update to add/replace the file
    const record = await pb.collection(collectionName).update(recordId, formData);

    return record;

  } catch (error) {
    console.error(`PocketBase: Caught error during ${fieldName} upload process:`, error);
    if (error.response && error.response.data) {
      console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};

/**
 * Deletes a file from a PocketBase collection record by setting the field to null.
 * @param {string} collectionName - The name of the collection ('users', 'media', etc.).
 * @param {string} recordId - The ID of the record the file is attached to.
 * @param {string} fieldName - The name of the file field ('profile_picture', 'banner_picture', etc.).
 * @returns {Promise<object>} The updated record object.
 * @throws {Error} If the update fails.
 */
export const deleteFile = async (collectionName, recordId, fieldName) => {
   try {
      // To delete a file in PocketBase, you update the record and set the file field to null
      // The JS SDK update method with { fieldName: null } handles this correctly.
      const updateData = {
         [fieldName]: null, // Set the field to null
      };

      const record = await pb.collection(collectionName).update(recordId, updateData);

      return record;

   } catch (error) {
      console.error(`PocketBase: Caught error during ${fieldName} deletion process:`, error);
      if (error.response && error.response.data) {
        console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};

/**
 * Gets the public URL for a file stored in PocketBase.
 * @param {object} record - The PocketBase record object.
 * @param {string} fieldName - The name of the file field ('profile_picture', 'banner_picture', etc.).
 * @param {object} [options] - Optional options for the URL (e.g., thumb).
 * @returns {string|null} The public URL of the file, or null if the field is empty or record is null.
 */
export const getFileUrl = (record, fieldName, options = {}) => {
  if (!record || !record[fieldName]) {
    return null;
  }
  // PocketBase SDK provides a helper to get the file URL
  try {
     // Use pb.getFileUrl with the record, the filename (which is stored in record[fieldName]), and options
     // The fieldName itself holds the filename(s)
     return pb.getFileUrl(record, record[fieldName], options);
  } catch (e) {
     return null;
  }
};

// --- Search Function ---
/**
 * Searches the 'media' collection by title and overview.
 * @param {string} query - The search query string.
 * @returns {Promise<Array<object>>} List of matching media records.
 */
export const searchMedia = async (query) => {
  if (!query || query.trim() === '') {
    return [];
  }
  try {
    // PocketBase search is done using filters
    // We can search in 'title' OR 'overview' fields
    // Using '~' operator for case-insensitive search (should be case-insensitive according to PB docs)
    const records = await pb.collection('media').getList(1, 50, { // Limit results to 50 for quick search
      filter: `title ~ "${query}" || overview ~ "${query}"`, // Case-insensitive search using '~'
      sort: '-created', // Optional: sort results
    });

    return records.items;

  } catch (error) {
    throw error;
  }
};


// --- Seasons Functions (New 'seasons' collection) ---

// NOTE: You will need to manually create a 'seasons' collection in PocketBase
// with the following fields:
// - media_id (relation to 'media', required)
// - season_number (number, required)
// - title (text, optional)
// - overview (text, optional)
// - release_date (date, optional)
// - poster (file, optional)
// - average_rating (number, default 0)
// - review_count (number, default 0)
// - is_published (bool, default false)
// - created_by (relation to 'users', required)
// - created (datetime)
// - updated (datetime)
// Add appropriate RLS policies for the 'seasons' collection.

/**
 * Fetches all seasons for a given media ID.
 * @param {string} mediaId - The ID of the parent media (series/anime).
 * @returns {Promise<Array<object>>} List of season records.
 */
export const getSeasonsByMediaId = async (mediaId, options = {}) => {
    try {
    const filter = `media_id = "${mediaId}"`;
    
    const queryOptions = {
      filter,
      sort: 'season_number',
      ...options // Добавляем переданные опции (например, expand)
    };

    const records = await pb.collection('seasons').getList(1, 100, queryOptions);
    return records.items;
  } catch (err) {
    throw err;
    }
};

/**
 * Fetches a specific season by its ID.
 * @param {string} seasonId - The ID of the season.
 * @returns {Promise<object|null>} The season record or null if not found.
 */
export const getSeasonById = async (seasonId) => {
    if (!seasonId) {
        return null;
    }
    try {
        const record = await pb.collection('seasons').getOne(seasonId);
        return record;
    } catch (error) {
        if (error.status === 404) {
            return null;
        }
        if (error.response && error.response.data) {
            console.error('PocketBase: Response data:', error.response.data);
        }
        throw error;
    }
};

/**
 * Creates a new season record.
 * @param {FormData} seasonData - FormData containing season data (including files).
 * @returns {Promise<object>} The created season record.
 */
export const createSeason = async (seasonData) => {
  try {
    const record = await pb.collection('seasons').create(seasonData);
    return record;
  } catch (error) {
    console.error('PocketBase: Ошибка создания сезона:', error);
    if (error.response && error.response.data) {
      console.error('PocketBase: Response data:', error.response.data);
    }
    throw error;
  }
};

/**
 * Updates an existing season record.
 * @param {string} seasonId - The ID of the season to update.
 * @param {FormData} seasonData - FormData containing updated season data (including files).
 * @returns {Promise<object>} The updated season record.
 */
export const updateSeason = async (seasonId, seasonData) => {
  try {
    const record = await pb.collection('seasons').update(seasonId, seasonData);
    return record;
  } catch (error) {
    console.error('PocketBase: Ошибка обновления сезона:', error);
    if (error.response) {
      console.error('PocketBase: Response status:', error.response.status);
      console.error('PocketBase: Response data:', error.response.data);
    } else {
      console.error('PocketBase: No response data available.');
    }
    throw error;
  }
};

/**
 * Deletes a season record.
 * @param {string} seasonId - The ID of the season to delete.
 * @returns {Promise<boolean>} True if successful.
 */
export const deleteSeason = async (seasonId) => {
  try {
    await pb.collection('seasons').delete(seasonId);
    return true; // Indicate success
  } catch (error) {
    console.error('PocketBase: Ошибка удаления сезона:', error);
    if (error.response) {
      console.error('PocketBase: Response status:', error.response.status);
      console.error('PocketBase: Response data:', error.response.data);
    } else {
      console.error('PocketBase: No response data available.');
    }
    throw error;
  }
};

/**
 * Fetches all seasons with optional filtering.
 * @param {Object} options - Optional parameters for filtering and sorting.
 * @param {string} options.mediaId - Optional media ID to filter seasons.
 * @param {boolean} options.published - Optional filter for published status.
 * @param {string} options.sort - Optional sort field (default: 'season_number').
 * @returns {Promise<Array<object>>} List of season records.
 */
export const getSeasons = async (options = {}) => {
    try {
        let filter = '';
        
        // Build filter string based on options
        if (options.mediaId) {
            filter += `media_id = "${options.mediaId}"`;
        }
        if (options.published !== undefined) {
            if (filter) filter += ' && ';
            filter += `is_published = ${options.published}`;
        }

        const queryOptions = {
            sort: options.sort || 'season_number',
            expand: 'media_id,created_by'
        };

        if (filter) {
            queryOptions.filter = filter;
        }

        const records = await pb.collection('seasons').getFullList(queryOptions);

        return records;
    } catch (error) {
        console.error('PocketBase: Ошибка получения сезонов:', error);
        if (error.response && error.response.data) {
            console.error('PocketBase: Response data:', error.response.data);
        }
        throw error;
    }
};

// Функции для работы с предложениями
export const getSuggestions = async (page = 1, perPage = 20, sort = '-created') => {
  try {
    const records = await pb.collection('suggestions').getList(page, perPage, {
      sort,
      expand: 'user'
    });
    return records.items;
  } catch (error) {
    throw error;
  }
};

export const getSuggestionById = async (id) => {
  try {
    const record = await pb.collection('suggestions').getOne(id, {
      expand: 'user'
    });
    return record;
  } catch (error) {
    throw error;
  }
};

export const createSuggestion = async (data) => {
  try {
    const record = await pb.collection('suggestions').create(data);
    return record;
  } catch (error) {
    throw error;
  }
};

export const updateSuggestion = async (id, data) => {
  try {
    const record = await pb.collection('suggestions').update(id, data);
    return record;
  } catch (error) {
    throw error;
  }
};

export const deleteSuggestion = async (id) => {
  try {
    await pb.collection('suggestions').delete(id);
  } catch (error) {
    throw error;
  }
};

// Функции для работы с пользователями
export const getUsers = async (page = 1, perPage = 20, sort = '-created') => {
  try {
    const records = await pb.collection('users').getList(page, perPage, {
      sort
    });
    
    return records.items;
  } catch (error) {
    throw error;
  }
};

export const updateUser = async (userId, data) => {
  try {
    const record = await pb.collection('users').update(userId, data);
    return record;
  } catch (error) {
    console.error('Error updating user:', error);
    throw error;
  }
};

export const deleteUser = async (userId) => {
  try {
    await pb.collection('users').delete(userId);
    return true;
  } catch (error) {
    console.error('Error deleting user:', error);
    throw error;
  }
};

// Export pb instance if needed elsewhere (e.g., for authStore listener)
export { pb };

export const getMediaCount = async () => {
  try {
    const records = await pb.collection('media').getList(1, 1, {
      fields: 'id'
    });
    return records.totalItems;
  } catch (error) {
    return 0;
  }
};

export const getReviewsCount = async () => {
  try {
    const records = await pb.collection('reviews').getList(1, 1, {
      fields: 'id'
    });
    return records.totalItems;
  } catch (error) {
    return 0;
  }
};

export const getFeaturedMedia = async () => {
  try {
    const records = await pb.collection('media').getList(1, 6, {
      sort: '-rating',
      expand: 'poster'
    });
    return records.items;
  } catch (error) {
    return [];
  }
};

export const getReviewsByLikes = async (limit = 20) => {
    try {
        const records = await pb.collection('reviews').getList(1, 100, {
            expand: 'media_id,user_id'
        });
        
        // Сортируем на клиенте
        const sortedReviews = records.items.sort((a, b) => {
            const aLikes = a.likes?.length || 0;
            const bLikes = b.likes?.length || 0;
            return bLikes - aLikes;
        }).slice(0, limit);

        return sortedReviews;
    } catch (error) {
        throw error;
    }
};

export const getAdminStats = async () => {
  try {
    const stats = {
      users: 0,
      media: 0,
      reviews: 0,
      tickets: 0,
      suggestions: 0
    };

    // Получаем количество пользователей
    try {
      const usersCount = await pb.collection('users').getList(1, 1, {
        fields: 'id'
      });
      stats.users = usersCount.totalItems;
    } catch (error) {
      console.warn('Не удалось получить количество пользователей:', error);
    }

    // Получаем количество медиа
    try {
      const mediaCount = await pb.collection('media').getList(1, 1, {
        fields: 'id'
      });
      stats.media = mediaCount.totalItems;
    } catch (error) {
      console.warn('Не удалось получить количество медиа:', error);
    }

    // Получаем количество обзоров
    try {
      const reviewsCount = await pb.collection('reviews').getList(1, 1, {
        fields: 'id'
      });
      stats.reviews = reviewsCount.totalItems;
    } catch (error) {
      console.warn('Не удалось получить количество обзоров:', error);
    }

    // Получаем количество тикетов
    try {
      const ticketsCount = await pb.collection('support_tickets').getList(1, 1, {
        fields: 'id'
      });
      stats.tickets = ticketsCount.totalItems;
    } catch (error) {
      console.warn('Не удалось получить количество тикетов:', error);
    }

    // Получаем количество предложений
    try {
      const suggestionsCount = await pb.collection('suggestions').getList(1, 1, {
        fields: 'id'
      });
      stats.suggestions = suggestionsCount.totalItems;
    } catch (error) {
      console.warn('Не удалось получить количество предложений:', error);
    }

    return stats;
  } catch (error) {
    throw error;
  }
};

// Функция для создания рецензии через API
export const createReviewViaAPI = async (reviewData) => {
  try {
    // Рассчитываем общую оценку, если она не предоставлена
    if (!reviewData.overall_rating && reviewData.ratings) {
      const ratings = reviewData.ratings;
      const validRatings = Object.values(ratings).filter(value => typeof value === 'number' && !isNaN(value));
      if (validRatings.length > 0) {
        reviewData.overall_rating = parseFloat((validRatings.reduce((sum, value) => sum + value, 0) / validRatings.length).toFixed(2));
      }
    }

    // Убеждаемся, что media_type установлен
    if (!reviewData.media_type && reviewData.media_id) {
      const media = await pb.collection('media').getOne(reviewData.media_id);
      reviewData.media_type = media.type;
    }

    // Устанавливаем progress по умолчанию, если не предоставлен
    if (!reviewData.progress) {
      reviewData.progress = reviewData.media_type === 'game' ? 'completed' : 'watched';
    }

    const record = await pb.collection('reviews').create(reviewData);

    // Обновляем статистику медиа
    if (record.media_id) {
      await updateRatingStats('media', record.media_id);
    }

    return record;
  } catch (error) {
    console.error('Error creating review:', error);
    throw error;
  }
};

// Функции для работы с лайками рецензий
export const likeReview = async (reviewId) => {
  try {
    const currentUser = pb.authStore.model;
    if (!currentUser) {
      throw new Error('User not authenticated');
    }

    const review = await pb.collection('reviews').getOne(reviewId);
    const likes = review.likes || [];
    
    if (!likes.includes(currentUser.id)) {
      likes.push(currentUser.id);
      await pb.collection('reviews').update(reviewId, { likes });
    }

    return true;
  } catch (error) {
    console.error('Error liking review:', error);
    throw error;
  }
};

export const unlikeReview = async (reviewId) => {
  try {
    const currentUser = pb.authStore.model;
    if (!currentUser) {
      throw new Error('User not authenticated');
    }

    const review = await pb.collection('reviews').getOne(reviewId);
    const likes = review.likes || [];
    
    if (likes.includes(currentUser.id)) {
      const updatedLikes = likes.filter(id => id !== currentUser.id);
      await pb.collection('reviews').update(reviewId, { likes: updatedLikes });
    }

    return true;
  } catch (error) {
    console.error('Error unliking review:', error);
    throw error;
  }
};
