using iyixiGames.Domain.DTOs.Games;
using iyixiGames.Domain.Entities;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using iyixiGames.AI.Services;
using iyixiGames.Domain.DTOs.Games;
using iyixiGames.Infrastructure.Services; // Add this using directive

namespace iyixiGames.Application.Services
{
    public class GameService : IGameService
    {
        private readonly IGameRepository _gameRepository;
        private readonly ILogger<GameService> _logger;
        private readonly IDeepSeekService _deepSeekService; // Inject DeepSeekService

        public GameService(IGameRepository gameRepository, ILogger<GameService> logger,
            IDeepSeekService deepSeekService)
        {
            _gameRepository = gameRepository;
            _logger = logger;
            _deepSeekService = deepSeekService; // Assign it
        }

        public async Task<GameResponse?> GetGameByIdAsync(string id)
        {
            _logger.LogInformation("Attempting to retrieve game, ID: {GameId}", id);
            var game = await _gameRepository.GetByIdAsync(id);
            if (game == null)
            {
                _logger.LogWarning("Game not found, ID: {GameId}", id);
                return null;
            }

            return MapToGameResponse(game);
        }

        public async Task<IEnumerable<GameResponse>> GetAllGamesAsync()
        {
            _logger.LogInformation("Attempting to retrieve all games list.");
            var games = await _gameRepository.GetAllAsync();
            return games.Select(MapToGameResponse).ToList();
        }

        public async Task<GameResponse> CreateGameAsync(CreateGameRequest request)
        {
            _logger.LogInformation("Attempting to create new game, Name: {GameName}, Path: {GamePath}", request.Name,
                request.Path);

            if (await _gameRepository.NameExistsAsync(request.Name))
            {
                _logger.LogWarning("Game creation failed: Game name '{GameName}' already exists.", request.Name);
                throw new InvalidOperationException($"Game name '{request.Name}' already exists.");
            }

            if (await _gameRepository.PathExistsAsync(request.Path))
            {
                _logger.LogWarning("Game creation failed: Game path '{GamePath}' already exists.", request.Path);
                throw new InvalidOperationException($"Game path '{request.Path}' already exists.");
            }

            var game = new Game
            {
                Name = request.Name,
                Path = request.Path.Trim().ToLower(),
                Description = request.Description?.Trim(), // New: Assign description
                Category = request.Category,
                Popularity = request.Popularity,
                AvgRating = request.AvgRating,
                ReleaseDate = request.ReleaseDate.Date,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            await _gameRepository.AddAsync(game);
            _logger.LogInformation("Game '{GameName}' (ID: {GameId}) created successfully.", game.Name, game.Id);
            return MapToGameResponse(game);
        }

        public async Task<List<GameResponse>> BatchCreateGamesAsync(BatchCreateGamesRequest request)
        {
            _logger.LogInformation("Attempting to batch create games.");
            var createdGames = new List<GameResponse>();
            var gamesToAdd = new List<Game>();
            var errors = new List<string>();

            var gamePaths = request.GamePathsText
                .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(p => p.Trim().ToLower())
                .Where(p => !string.IsNullOrWhiteSpace(p))
                .Distinct()
                .ToList();

            var pathRegex = new Regex(@"^[a-zA-Z0-9_-]+$");

            foreach (var path in gamePaths)
            {
                if (!pathRegex.IsMatch(path))
                {
                    errors.Add($"路径 '{path}' 无效，只能包含字母、数字、下划线和连字符。");
                    continue;
                }

                if (await _gameRepository.PathExistsAsync(path))
                {
                    errors.Add($"路径 '{path}' 已存在，跳过创建。");
                    continue;
                }

                string defaultName = $"Game-{path}";
                if (await _gameRepository.NameExistsAsync(defaultName))
                {
                    errors.Add($"默认名称 '{defaultName}' (来自路径 '{path}') 已存在，请手动创建或修改。");
                    continue;
                }

                gamesToAdd.Add(new Game
                {
                    Name = defaultName,
                    Path = path,
                    Description = null, // Default to null for batch creation
                    Category = "未知",
                    Popularity = 0,
                    AvgRating = 0.0,
                    ReleaseDate = DateTime.UtcNow.Date,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                });
            }

            if (gamesToAdd.Any())
            {
                await _gameRepository.AddRangeAsync(gamesToAdd);
                createdGames.AddRange(gamesToAdd.Select(MapToGameResponse));
                _logger.LogInformation("Successfully batch created {Count} games.", createdGames.Count);
            }

            if (errors.Any())
            {
                _logger.LogWarning("Errors occurred during batch game creation: {Errors}", string.Join("; ", errors));
            }

            return createdGames;
        }

        public async Task<GameResponse?> UpdateGameAsync(string id, UpdateGameRequest request)
        {
            _logger.LogInformation("Attempting to update game, ID: {GameId}", id);
            var game = await _gameRepository.GetByIdAsync(id);
            if (game == null)
            {
                _logger.LogWarning("Game update failed: Game not found, ID: {GameId}", id);
                return null;
            }

            if (!string.IsNullOrEmpty(request.Name) && request.Name != game.Name)
            {
                if (await _gameRepository.NameExistsAsync(request.Name))
                {
                    _logger.LogWarning(
                        "Game update failed: Game name '{GameName}' already exists and does not belong to the current game.",
                        request.Name);
                    throw new InvalidOperationException($"游戏名称 '{request.Name}' 已被其他游戏使用。");
                }

                game.Name = request.Name;
            }

            if (!string.IsNullOrEmpty(request.Path) && request.Path != game.Path)
            {
                string newPath = request.Path.Trim().ToLower();
                if (await _gameRepository.PathExistsAsync(newPath))
                {
                    _logger.LogWarning(
                        "Game update failed: Game path '{GamePath}' already exists and does not belong to the current game.",
                        newPath);
                    throw new InvalidOperationException($"游戏路径 '{newPath}' 已被其他游戏使用。");
                }

                game.Path = newPath;
            }

            // New: Update description if provided
            if (request.Description != null) // Allow setting to empty string or null
            {
                game.Description = request.Description.Trim();
            }

            if (!string.IsNullOrEmpty(request.Category)) game.Category = request.Category;
            if (request.Popularity.HasValue) game.Popularity = request.Popularity.Value;
            if (request.AvgRating.HasValue) game.AvgRating = request.AvgRating.Value;
            if (request.ReleaseDate.HasValue) game.ReleaseDate = request.ReleaseDate.Value.Date;

            game.UpdatedAt = DateTime.UtcNow;

            await _gameRepository.UpdateAsync(game);
            _logger.LogInformation("Game '{GameId}' updated successfully.", id);
            return MapToGameResponse(game);
        }

        public async Task<bool> DeleteGameAsync(string id)
        {
            _logger.LogInformation("Attempting to delete game, ID: {GameId}", id);
            var exists = await _gameRepository.ExistsAsync(id);
            if (!exists)
            {
                _logger.LogWarning("Game deletion failed: Game not found, ID: {GameId}", id);
                return false;
            }

            await _gameRepository.DeleteAsync(id);
            _logger.LogInformation("Game '{GameId}' deleted successfully.", id);
            return true;
        }

        /// <summary>
        /// Generates a game description using DeepSeek AI.
        /// </summary>
        /// <param name="gameName">The name of the game to describe.</param>
        /// <returns>A generated description string or null if generation fails.</returns>
        public async Task<string?> GenerateGameDescriptionAsync(string gameName)
        {
            if (string.IsNullOrWhiteSpace(gameName))
            {
                _logger.LogWarning("Cannot generate description for an empty game name.");
                return null;
            }

            _logger.LogInformation("Requesting DeepSeek to generate description for game: {GameName}", gameName);
            // Craft a prompt for DeepSeek
            /*
             {
                 "model": "deepseek-chat",
                 "messages": [
                   {
                     "role": "system",
                     "content": "你是一个专业的游戏信息生成助手，根据用户提供的文件夹名称，生成对应的游戏名称、描述、类别、流行度、评分、发布时间、创建时间和更新时间。输出必须严格遵循给定的格式。"
                   },
                   {
                     "role": "user",
                     "content": "文件夹名称：Cyber_Shadows_2022"
                   }
                 ],
                 "temperature": 0.7,
                 "max_tokens": 500
               }
             */
            string prompt = $"使用美式英文，请为一款名为 '{gameName}' 的小游戏写一段简短的介绍，要求内容生动有趣，长度在80字以内，不需要标题。";

            try
            {
                var generatedText = await _deepSeekService.GetTextResponseAsync(prompt);
                if (!string.IsNullOrWhiteSpace(generatedText))
                {
                    _logger.LogInformation("Successfully generated description for '{GameName}'.", gameName);
                    return generatedText.Trim();
                }

                _logger.LogWarning("DeepSeek generated an empty or whitespace description for '{GameName}'.", gameName);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to generate description for '{GameName}' using DeepSeek.", gameName);
            }

            return null;
        }

        // 根据传入的小游戏的文件夹名称生成小游戏的全部信息
        public async Task<Game?> GenerateGameInfoFromPathAsync(string gamePath)
        {
            // 判断传入的值是否为空
            if (string.IsNullOrWhiteSpace(gamePath))
            {
                _logger.LogWarning("传入的小游戏文件夹名称为空。");
                return null;
            }

            // Craft a prompt for DeepSeek
            var prompt =
                $"{{\n  \"model\": \"list\",\n  \"messages\": [\n    {{\n      \"role\": \"system\",\n      " +
                $"\"content\": \"你是一个专业的游戏信息生成助手，根据用户提供的文件夹名称，生成对应的游戏的：Name、Path、Description、Category、Popularity(int)、AvgRating(float)、ReleaseDate、CreatedAt、UpdatedAt。输出必须严格遵循给定的格式。" +
                $"\"\n    }},\n    {{\n      \"role\": \"user\",\n      \"content\": \"文件夹名称：{gamePath}\"\n    }}\n  ],\n  \"temperature\": 0.7,\n  \"max_tokens\": 500\n}}";
            try
            {
                var generatedDescription = await _deepSeekService.GetTextResponseAsync(prompt);
                
                if (!string.IsNullOrWhiteSpace(generatedDescription))
                {
                    _logger.LogInformation($"Generated Description: {generatedDescription}");
                    /*
                     ```json
                       {
                         "Name": "Sprout Safe",
                         "Path": "Sprout-Safe",
                         "Description": "Sprout Safe is a charming gardening simulation game where players nurture and protect their plants from various threats. With a mix of strategy and relaxation, the game offers a unique blend of farming and tower defense mechanics.",
                         "Category": "Simulation, Strategy",
                         "Popularity": "Medium",
                         "AvgRating": 4.2,
                         "ReleaseDate": "2022-05-15",
                         "CreatedAt": "2022-05-15T00:00:00Z",
                         "UpdatedAt": "2023-01-20T00:00:00Z"
                       }
                       ```
                     */
                    // 只保留 generatedDescription 值的{}的内容
                    generatedDescription = generatedDescription.Replace("```json","");
                    generatedDescription = generatedDescription.Replace("```","");
                    generatedDescription = generatedDescription.Trim();
                    // 将 generatedDescription 转化为 Game
                    var options = new JsonSerializerOptions
                    {
                        PropertyNameCaseInsensitive = true,
                        // 如果你的 JSON 中包含不在 Game 模型中的额外字段，可以忽略它们
                        // 例如，DeepSeek 可能返回一些你不需要的字段
                        // UnknownAction = JsonUnknownAction.Ignore
                    };
                    var game = JsonSerializer.Deserialize<Game>(generatedDescription, options);
                    return game;
                    // return generatedDescription;
                }
                _logger.LogError($"Error generating description: {gamePath}");
            }
            catch (Exception e)
            {
                _logger.LogError(e, "An error occurred while processing the request.");
            }
            return null;
        }

        // --- Private Helper Method ---
        private GameResponse MapToGameResponse(Game game)
        {
            return new GameResponse
            {
                Id = game.Id,
                Name = game.Name,
                Path = game.Path,
                Description = game.Description, // New: Map description
                Category = game.Category?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(c => c.Trim()).ToList() ?? new List<string>(),
                Popularity = game.Popularity,
                AvgRating = game.AvgRating,
                ReleaseDate = game.ReleaseDate,
                CreatedAt = game.CreatedAt,
                UpdatedAt = game.UpdatedAt
            };
        }
    }
}