// Controllers/AuthController.cs
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Dashboard.Services;
using Dashboard.Data;
using System.Text.Json;
using System.Net.Http.Headers;

namespace Dashboard.Controllers
{
    [ApiController]
    [Route("api/auth")]
    public class AuthController : ControllerBase
    {
        private readonly IUserService _userService;
        private readonly ILogger<AuthController> _logger;
        private readonly IConfiguration _configuration;
        private readonly HttpClient _httpClient;

        public AuthController(IUserService userService, ILogger<AuthController> logger, IConfiguration configuration, HttpClient httpClient)
        {
            _userService = userService;
            _logger = logger;
            _configuration = configuration;
            _httpClient = httpClient;
        }

        // نقطه پایانی برای آغاز ورود اولیه با اسکوپ‌های پایه
        [HttpGet("google-login-basic")]
        [AllowAnonymous]
        public IActionResult GoogleLoginBasic()
        {
            var properties = new AuthenticationProperties
            {
                RedirectUri = "http://localhost:3000/"
            };

            _logger.LogInformation("Initiating GoogleBasic login challenge.");
            return Challenge(properties, "GoogleBasic");
        }

        // نقطه پایانی برای افزایش دسترسی‌ها (درخواست اسکوپ‌های اضافی)
        [Authorize]
        [HttpGet("google-grant-additional-scopes")]
        public IActionResult GoogleGrantAdditionalScopes()
        {
            var properties = new AuthenticationProperties
            {
                RedirectUri = "http://localhost:3000/"
            };

            properties.SetParameter("prompt", "consent");

            _logger.LogInformation("Initiating GoogleFull access challenge for user {Email}.", User.FindFirst(ClaimTypes.Email)?.Value);
            return Challenge(properties, "GoogleFull");
        }

        // Endpoint to get current user info (authenticated via cookie)
        [Authorize]
        [HttpGet("user")]
        public async Task<IActionResult> GetCurrentUser()
        {
            var googleId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var userEmail = User.FindFirst(ClaimTypes.Email)?.Value;

            if (string.IsNullOrEmpty(googleId) || string.IsNullOrEmpty(userEmail))
            {
                _logger.LogWarning("GetCurrentUser: User not authenticated or claims missing. GoogleId: {GoogleId}, Email: {Email}", googleId, userEmail);
                return Unauthorized("User not authenticated or claims missing.");
            }

            var user = await _userService.GetUserByGoogleIdAsync(googleId);
            if (user == null)
            {
                _logger.LogWarning("GetCurrentUser: User with GoogleId {GoogleId} not found in database after authentication.", googleId);
                return NotFound("User not found in database.");
            }

            // Check if tokens need refreshing
            if (!string.IsNullOrEmpty(user.RefreshToken) && user.TokenExpiry < DateTime.UtcNow.AddMinutes(5))
            {
                await RefreshUserTokensAsync(user);
                user = await _userService.GetUserByGoogleIdAsync(googleId); // Get updated user
            }

            return Ok(new
            {
                user.GoogleId,
                FullName = user.Name,
                user.Email,
                userid = user.Id,  // به جای UserId
                ProfilePictureUrl = user.ProfilePicture,
                HasAccessToken = !string.IsNullOrEmpty(user.AccessToken) && !string.IsNullOrEmpty(user.RefreshToken),
                HasRefreshToken = !string.IsNullOrEmpty(user.RefreshToken),
                TokenExpiresAt = user.TokenExpiry
            });





        }

        // **جدید**: API برای دسترسی N8N به توکن‌ها
        [Authorize]
        [HttpGet("google-tokens")]
        public async Task<IActionResult> GetGoogleTokens()
        {
            var googleId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var user = await _userService.GetUserByGoogleIdAsync(googleId);

            if (user == null || string.IsNullOrEmpty(user.AccessToken))
            {
                return BadRequest(new { error = "User doesn't have Google access tokens" });
            }

            // چک کردن انقضای توکن و refresh کردن در صورت نیاز
            if (user.TokenExpiry < DateTime.UtcNow.AddMinutes(5))
            {
                var refreshed = await RefreshUserTokensAsync(user);
                if (!refreshed)
                {
                    return BadRequest(new { error = "Failed to refresh tokens" });
                }
                user = await _userService.GetUserByGoogleIdAsync(googleId); // Get updated user
            }

            return Ok(new
            {
                AccessToken = user.AccessToken,
                RefreshToken = user.RefreshToken,
                ExpiresAt = user.TokenExpiry,
                GoogleId = user.GoogleId,
                Email = user.Email
            });
        }

        // **جدید**: ساخت Google Sheet برای کاربر
        [Authorize]
        [HttpPost("create-sheet")]
        public async Task<IActionResult> CreateGoogleSheet([FromBody] CreateSheetRequest request)
        {
            var googleId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var user = await _userService.GetUserByGoogleIdAsync(googleId);

            if (user == null || string.IsNullOrEmpty(user.AccessToken))
            {
                return BadRequest(new { error = "User doesn't have Google access tokens" });
            }

            // چک کردن انقضای توکن
            if (user.TokenExpiry < DateTime.UtcNow.AddMinutes(5))
            {
                var refreshed = await RefreshUserTokensAsync(user);
                if (!refreshed)
                {
                    return BadRequest(new { error = "Failed to refresh tokens" });
                }
                user = await _userService.GetUserByGoogleIdAsync(googleId);
            }

            try
            {
                var sheetData = new
                {
                    properties = new
                    {
                        title = request.Title ?? "New Sheet"
                    },
                    sheets = new[]
                    {
                        new
                        {
                            properties = new
                            {
                                title = request.SheetName ?? "Sheet1",
                                gridProperties = new
                                {
                                    rowCount = 100,
                                    columnCount = 26
                                }
                            }
                        }
                    }
                };

                var json = JsonSerializer.Serialize(sheetData);
                var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");

                _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", user.AccessToken);

                var response = await _httpClient.PostAsync("https://sheets.googleapis.com/v4/spreadsheets", content);

                if (response.IsSuccessStatusCode)
                {
                    var responseContent = await response.Content.ReadAsStringAsync();
                    var result = JsonSerializer.Deserialize<JsonElement>(responseContent);

                    var spreadsheetId = result.GetProperty("spreadsheetId").GetString();
                    var spreadsheetUrl = result.GetProperty("spreadsheetUrl").GetString();

                    _logger.LogInformation("Created Google Sheet for user {Email}: {SpreadsheetId}", user.Email, spreadsheetId);

                    return Ok(new
                    {
                        SpreadsheetId = spreadsheetId,
                        SpreadsheetUrl = spreadsheetUrl,
                        Title = request.Title ?? "New Sheet"
                    });
                }
                else
                {
                    var errorContent = await response.Content.ReadAsStringAsync();
                    _logger.LogError("Failed to create Google Sheet for user {Email}: {Error}", user.Email, errorContent);
                    return BadRequest(new { error = "Failed to create Google Sheet", details = errorContent });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating Google Sheet for user {Email}", user.Email);
                return StatusCode(500, new { error = "Internal server error" });
            }
        }

        // **جدید**: اضافه کردن داده به Sheet
        [Authorize]
        [HttpPost("add-to-sheet")]
        public async Task<IActionResult> AddDataToSheet([FromBody] AddDataToSheetRequest request)
        {
            var googleId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var user = await _userService.GetUserByGoogleIdAsync(googleId);

            if (user == null || string.IsNullOrEmpty(user.AccessToken))
            {
                return BadRequest(new { error = "User doesn't have Google access tokens" });
            }

            // چک کردن انقضای توکن
            if (user.TokenExpiry < DateTime.UtcNow.AddMinutes(5))
            {
                var refreshed = await RefreshUserTokensAsync(user);
                if (!refreshed)
                {
                    return BadRequest(new { error = "Failed to refresh tokens" });
                }
                user = await _userService.GetUserByGoogleIdAsync(googleId);
            }

            try
            {
                var updateData = new
                {
                    range = request.Range ?? "A1",
                    majorDimension = "ROWS",
                    values = request.Values
                };

                var json = JsonSerializer.Serialize(updateData);
                var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");

                _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", user.AccessToken);

                var url = $"https://sheets.googleapis.com/v4/spreadsheets/{request.SpreadsheetId}/values/{request.Range}?valueInputOption=USER_ENTERED";
                var response = await _httpClient.PutAsync(url, content);

                if (response.IsSuccessStatusCode)
                {
                    var responseContent = await response.Content.ReadAsStringAsync();
                    _logger.LogInformation("Added data to Google Sheet {SpreadsheetId} for user {Email}", request.SpreadsheetId, user.Email);
                    return Ok(new { message = "Data added successfully", response = responseContent });
                }
                else
                {
                    var errorContent = await response.Content.ReadAsStringAsync();
                    _logger.LogError("Failed to add data to Google Sheet {SpreadsheetId} for user {Email}: {Error}", request.SpreadsheetId, user.Email, errorContent);
                    return BadRequest(new { error = "Failed to add data to Google Sheet", details = errorContent });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error adding data to Google Sheet {SpreadsheetId} for user {Email}", request.SpreadsheetId, user.Email);
                return StatusCode(500, new { error = "Internal server error" });
            }
        }

        // **جدید**: Token Refresh Logic
        private async Task<bool> RefreshUserTokensAsync(Dashboard.Models.User user)
        {
            if (string.IsNullOrEmpty(user.RefreshToken))
            {
                _logger.LogWarning("No refresh token available for user {Email}", user.Email);
                return false;
            }

            try
            {
                var refreshData = new Dictionary<string, string>
                {
                    {"client_id", _configuration["Google:ClientId"]},
                    {"client_secret", _configuration["Google:ClientSecret"]},
                    {"refresh_token", user.RefreshToken},
                    {"grant_type", "refresh_token"}
                };

                var content = new FormUrlEncodedContent(refreshData);
                var response = await _httpClient.PostAsync("https://oauth2.googleapis.com/token", content);

                if (response.IsSuccessStatusCode)
                {
                    var responseContent = await response.Content.ReadAsStringAsync();
                    var tokenResponse = JsonSerializer.Deserialize<JsonElement>(responseContent);

                    var newAccessToken = tokenResponse.GetProperty("access_token").GetString();
                    var expiresInSeconds = tokenResponse.GetProperty("expires_in").GetInt32();
                    var newExpiresAt = DateTime.UtcNow.AddSeconds(expiresInSeconds);

                    await _userService.UpdateUserTokensAsync(user.GoogleId, newAccessToken, null, newExpiresAt);

                    _logger.LogInformation("Refreshed tokens for user {Email}", user.Email);
                    return true;
                }
                else
                {
                    _logger.LogError("Failed to refresh tokens for user {Email}: {StatusCode}", user.Email, response.StatusCode);
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error refreshing tokens for user {Email}", user.Email);
                return false;
            }
        }

        // Endpoint to handle logout
        [Authorize]
        [HttpGet("logout")]
        public async Task<IActionResult> Logout()
        {
            _logger.LogInformation("Logging out user {Email}.", User.FindFirst(ClaimTypes.Email)?.Value);
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            HttpContext.SignOutAsync();
            return Ok(new { success = true });

            //return Redirect("http://localhost:3000/");
        }

        // Error handling endpoint
        [HttpGet("error")]
        [AllowAnonymous]
        public IActionResult AuthError()
        {
            _logger.LogError("Authentication error occurred during Google sign-in.");
            return Redirect("http://localhost:3000/auth-error");
        }

        [HttpGet("callback")]
        public IActionResult LoginCallback()
        {
            return Redirect("http://localhost:3000/dashboard");
        }
    }

    // **جدید**: Request Models
    public class CreateSheetRequest
    {
        public string? Title { get; set; }
        public string? SheetName { get; set; }
    }

    public class AddDataToSheetRequest
    {
        public string SpreadsheetId { get; set; } = string.Empty;
        public string? Range { get; set; }
        public object[][] Values { get; set; } = Array.Empty<object[]>();
    }
}