using Microsoft.AspNetCore.Mvc;
using Auth.Services.DatabaseService;
using System.Web.Http;
using Auth.Entities;
using System.Text;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens;

namespace Auth.Controllers {
    [ApiController]
    [Route("api/oauth/")]
    public class OAuthController : MistoxControllerBase {

        public OAuthController(DatabaseService db) : base(db) { }

        /*

        private string GenerateCodeChallenge(string codeVerifier) {
            using var sha256 = SHA256.Create();
            var bytes = sha256.ComputeHash(Encoding.ASCII.GetBytes(codeVerifier));
            return Base64UrlEncode(bytes);
        }

        private string Base64UrlEncode(byte[] input) {
            return Convert.ToBase64String(input)
                .TrimEnd('=')
                .Replace('+', '-')
                .Replace('/', '_');
        }

        [HttpGet("authorize")]
        public async Task<ActionResult> Authorize([FromQuery] AuthorizationRequest request) {
            try {

                if (request.ResponseType != "code") {
                    return BadRequest("unsupported_code_type");
                }

                string RequestingApp = request.ClientId;

                // Verify login
                // create guid
                // set guid to account
                // save account to database

                return NotFound("User is not logged in");
            } catch (Exception ex) {
                Console.WriteLine("Delete Error: " + ex.Message);
                return NotFound("An internal server error has occured");
            }
        }

        [HttpPost("token")]
        public async Task<ActionResult> Token([FromForm] TokenRequest request) {
            try {

                // Validate Grant Code
                if (request.GrantType != "authorization_code") {
                    return BadRequest(new { error = "unsupported_grant_type" });
                }

                // Validate Required Parameters
                if (string.IsNullOrEmpty(request.Code) || string.IsNullOrEmpty(request.RedirectUri) || string.IsNullOrEmpty(request.CodeVerifier)) {
                    return BadRequest(new { error = "invalid_request" });
                }

                // Check if LoginToken is expired
                var authCode = AuthorizationCodeStore.Get(request.Code);
                if (authCode == null || authCode.IsExpired) {
                    return BadRequest(new { error = "invalid_grant" });
                }

                // Verify redirect_uri matches
                if (!string.Equals(authCode.RedirectUri, request.RedirectUri, StringComparison.Ordinal)) {
                    return BadRequest(new { error = "invalid_grant" });
                }

                // 5. Verify code_verifier (PKCE check)
                var expectedChallenge = GenerateCodeChallenge(request.CodeVerifier);
                if (authCode.CodeChallenge != expectedChallenge) {
                    return BadRequest(new { error = "invalid_grant", error_description = "PKCE verification failed" });
                }

                // 6. Optionally verify client_id/client_secret (for confidential clients)
                // ...

                // 7. Issue access token (and refresh token if needed)
                var accessToken = TokenService.GenerateAccessToken(authCode.UserId, authCode.ClientId, authCode.Scope);
                var refreshToken = TokenService.GenerateRefreshToken(authCode.UserId, authCode.ClientId);

                // 8. Invalidate used authorization code (one-time use)
                AuthorizationCodeStore.Remove(request.Code);

                // 9. Return token response
                return Ok(new {
                    access_token = accessToken,
                    token_type = "Bearer",
                    expires_in = 3600,
                    refresh_token = refreshToken
                });

            } catch (Exception ex) {
                Console.WriteLine("Delete Error: " + ex.Message);
                return NotFound("An internal server error has occured");
            }
        }

        [HttpGet("/userinfo")]
        public async Task<IActionResult> UserInfo() {
            Account user = await getLoggedInUser();
            if (user == null) {
                return Unauthorized();
            }

            var claims = new {
                sub = user.ID,
                preferred_username = user.UserName,
                email = user.Email,
                email_verified = user.EmailVerified
            };

            return Ok(claims);
        }

        [HttpGet("/.well-known/openid-configuration")]
        public IActionResult OpenIdConfiguration() {
            var issuer = "https://your-auth-server.com";

            var config = new {
                issuer = issuer,
                authorization_endpoint = $"{issuer}/authorize",
                token_endpoint = $"{issuer}/token",
                userinfo_endpoint = $"{issuer}/userinfo",
                jwks_uri = $"{issuer}/.well-known/jwks.json",
                response_types_supported = new[] { "code", "token", "id_token", "code id_token" },
                subject_types_supported = new[] { "public" },
                id_token_signing_alg_values_supported = new[] { "RS256" },
                scopes_supported = new[] { "openid", "profile", "email" },
                token_endpoint_auth_methods_supported = new[] { "client_secret_basic", "private_key_jwt" },
                claims_supported = new[] { "sub", "name", "preferred_username", "email", "email_verified" }
            };

            return Ok(config);
        }

        [HttpGet("/.well-known/jwks.json")]
        public IActionResult GetJwks() {
            var key = new RsaSecurityKey(rsa) {
                KeyId = "my-key-id-123" // a unique key ID, important for clients
            };

            var parameters = key.Rsa.ExportParameters(false); // export public key only

            var jwk = new JsonWebKey {
                Kid = key.KeyId,
                Kty = "RSA",
                Use = "sig",      // signing
                Alg = SecurityAlgorithms.RsaSha256,
                N = Base64UrlEncoder.Encode(parameters.Modulus),
                E = Base64UrlEncoder.Encode(parameters.Exponent)
            };

            var jwks = new { keys = new[] { jwk } };

            return Ok(jwks);
        }

        */

    }
}
