using Microsoft.Extensions.Logging;
using RealCV.Application.Interfaces;
using RealCV.Application.Models;
using RealCV.Infrastructure.Clients;

namespace RealCV.Infrastructure.Services;

public sealed class GitHubVerifierService : IGitHubVerifierService
{
    private readonly GitHubApiClient _gitHubClient;
    private readonly ILogger<GitHubVerifierService> _logger;

    // Map common skill names to GitHub languages
    private static readonly Dictionary<string, string[]> SkillToLanguageMap = new(StringComparer.OrdinalIgnoreCase)
    {
        ["JavaScript"] = ["JavaScript", "TypeScript"],
        ["TypeScript"] = ["TypeScript"],
        ["Python"] = ["Python"],
        ["Java"] = ["Java", "Kotlin"],
        ["C#"] = ["C#"],
        [".NET"] = ["C#", "F#"],
        ["React"] = ["JavaScript", "TypeScript"],
        ["Angular"] = ["TypeScript", "JavaScript"],
        ["Vue"] = ["JavaScript", "TypeScript", "Vue"],
        ["Node.js"] = ["JavaScript", "TypeScript"],
        ["Go"] = ["Go"],
        ["Golang"] = ["Go"],
        ["Rust"] = ["Rust"],
        ["Ruby"] = ["Ruby"],
        ["PHP"] = ["PHP"],
        ["Swift"] = ["Swift"],
        ["Kotlin"] = ["Kotlin"],
        ["C++"] = ["C++", "C"],
        ["C"] = ["C"],
        ["Scala"] = ["Scala"],
        ["R"] = ["R"],
        ["SQL"] = ["PLSQL", "TSQL"],
        ["Shell"] = ["Shell", "Bash", "PowerShell"],
        ["DevOps"] = ["Shell", "Dockerfile", "HCL"],
        ["Docker"] = ["Dockerfile"],
        ["Terraform"] = ["HCL"],
        ["Mobile"] = ["Swift", "Kotlin", "Dart", "Java"],
        ["iOS"] = ["Swift", "Objective-C"],
        ["Android"] = ["Kotlin", "Java"],
        ["Flutter"] = ["Dart"],
        ["Machine Learning"] = ["Python", "Jupyter Notebook", "R"],
        ["Data Science"] = ["Python", "Jupyter Notebook", "R"],
    };

    public GitHubVerifierService(
        GitHubApiClient gitHubClient,
        ILogger<GitHubVerifierService> logger)
    {
        _gitHubClient = gitHubClient;
        _logger = logger;
    }

    public async Task<GitHubVerificationResult> VerifyProfileAsync(string username)
    {
        try
        {
            _logger.LogInformation("Verifying GitHub profile: {Username}", username);

            var user = await _gitHubClient.GetUserAsync(username);

            if (user == null)
            {
                return new GitHubVerificationResult
                {
                    ClaimedUsername = username,
                    IsVerified = false,
                    VerificationNotes = "GitHub profile not found"
                };
            }

            // Get repositories for language analysis
            var repos = await _gitHubClient.GetUserReposAsync(username);

            // Analyze languages
            var languageStats = new Dictionary<string, int>();
            foreach (var repo in repos.Where(r => !r.Fork && !string.IsNullOrEmpty(r.Language)))
            {
                if (!languageStats.ContainsKey(repo.Language!))
                    languageStats[repo.Language!] = 0;
                languageStats[repo.Language!]++;
            }

            // Calculate flags
            var flags = new List<GitHubVerificationFlag>();

            // Check account age
            var accountAge = DateTime.UtcNow - user.CreatedAt;
            if (accountAge.TotalDays < 90)
            {
                flags.Add(new GitHubVerificationFlag
                {
                    Type = "NewAccount",
                    Severity = "Info",
                    Message = "Account created less than 90 days ago",
                    ScoreImpact = -5
                });
            }

            // Check for empty profile
            if (user.PublicRepos == 0)
            {
                flags.Add(new GitHubVerificationFlag
                {
                    Type = "NoRepos",
                    Severity = "Warning",
                    Message = "No public repositories",
                    ScoreImpact = -10
                });
            }

            return new GitHubVerificationResult
            {
                ClaimedUsername = username,
                IsVerified = true,
                ProfileName = user.Name,
                ProfileUrl = user.HtmlUrl,
                Bio = user.Bio,
                Company = user.Company,
                Location = user.Location,
                AccountCreated = user.CreatedAt != default
                    ? DateOnly.FromDateTime(user.CreatedAt)
                    : null,
                PublicRepos = user.PublicRepos,
                Followers = user.Followers,
                Following = user.Following,
                LanguageStats = languageStats,
                VerificationNotes = BuildVerificationSummary(user, repos),
                Flags = flags
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error verifying GitHub profile: {Username}", username);
            return new GitHubVerificationResult
            {
                ClaimedUsername = username,
                IsVerified = false,
                VerificationNotes = $"Error during verification: {ex.Message}"
            };
        }
    }

    public async Task<GitHubVerificationResult> VerifySkillsAsync(
        string username,
        List<string> claimedSkills)
    {
        var result = await VerifyProfileAsync(username);

        if (!result.IsVerified)
            return result;

        var skillVerifications = new List<SkillVerification>();

        foreach (var skill in claimedSkills)
        {
            var verified = false;
            var repoCount = 0;

            // Check if the skill matches a known language directly
            if (result.LanguageStats.TryGetValue(skill, out var count))
            {
                verified = true;
                repoCount = count;
            }
            else if (SkillToLanguageMap.TryGetValue(skill, out var mappedLanguages))
            {
                // Check if any mapped language exists in the user's repos
                foreach (var lang in mappedLanguages)
                {
                    if (result.LanguageStats.TryGetValue(lang, out var langCount))
                    {
                        verified = true;
                        repoCount += langCount;
                    }
                }
            }

            skillVerifications.Add(new SkillVerification
            {
                ClaimedSkill = skill,
                IsVerified = verified,
                RepoCount = repoCount,
                Notes = verified
                    ? $"Found in {repoCount} repositories"
                    : "No repositories found using this skill"
            });
        }

        var verifiedCount = skillVerifications.Count(sv => sv.IsVerified);
        var totalCount = skillVerifications.Count;
        var percentage = totalCount > 0 ? (verifiedCount * 100) / totalCount : 0;

        return result with
        {
            SkillVerifications = skillVerifications,
            VerificationNotes = $"Skills verified: {verifiedCount}/{totalCount} ({percentage}%)"
        };
    }

    public async Task<List<GitHubProfileSearchResult>> SearchProfilesAsync(string name)
    {
        try
        {
            var searchResponse = await _gitHubClient.SearchUsersAsync(name);

            if (searchResponse?.Items == null)
            {
                return [];
            }

            var results = new List<GitHubProfileSearchResult>();

            foreach (var item in searchResponse.Items.Take(10))
            {
                if (string.IsNullOrEmpty(item.Login))
                    continue;

                // Get full profile details
                var user = await _gitHubClient.GetUserAsync(item.Login);

                results.Add(new GitHubProfileSearchResult
                {
                    Username = item.Login,
                    Name = user?.Name,
                    AvatarUrl = item.AvatarUrl,
                    Bio = user?.Bio,
                    PublicRepos = user?.PublicRepos ?? 0,
                    Followers = user?.Followers ?? 0
                });
            }

            return results;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error searching GitHub profiles: {Name}", name);
            return [];
        }
    }

    private static string BuildVerificationSummary(GitHubUser user, List<GitHubRepo> repos)
    {
        var parts = new List<string>
        {
            $"Account created: {user.CreatedAt:yyyy-MM-dd}",
            $"Public repos: {user.PublicRepos}",
            $"Followers: {user.Followers}"
        };

        var totalStars = repos.Sum(r => r.StargazersCount);
        if (totalStars > 0)
        {
            parts.Add($"Total stars: {totalStars}");
        }

        var topLanguages = repos
            .Where(r => !r.Fork && !string.IsNullOrEmpty(r.Language))
            .GroupBy(r => r.Language)
            .OrderByDescending(g => g.Count())
            .Take(3)
            .Select(g => g.Key);

        if (topLanguages.Any())
        {
            parts.Add($"Top languages: {string.Join(", ", topLanguages)}");
        }

        return string.Join(" | ", parts);
    }
}
