using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

namespace AxCopilot.Services;

internal sealed class Cp4dTokenService
{
	private static readonly HttpClient _http = new HttpClient
	{
		Timeout = TimeSpan.FromSeconds(15.0)
	};

	private static readonly Dictionary<string, (string Token, DateTime Expiry)> _cache = new Dictionary<string, (string, DateTime)>();

	private static readonly object _lock = new object();

	public static async Task<string?> GetTokenAsync(string cp4dUrl, string username, string password, CancellationToken ct = default(CancellationToken))
	{
		if (string.IsNullOrWhiteSpace(cp4dUrl) || string.IsNullOrWhiteSpace(username))
		{
			return null;
		}
		string cacheKey = cp4dUrl + "|" + username;
		lock (_lock)
		{
			if (_cache.TryGetValue(cacheKey, out var cached) && cached.Expiry > DateTime.UtcNow.AddMinutes(1.0))
			{
				return cached.Token;
			}
		}
		try
		{
			string tokenUrl = cp4dUrl.TrimEnd('/') + "/icp4d-api/v1/authorize";
			var body = new { username, password };
			using HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, tokenUrl)
			{
				Content = JsonContent.Create(body)
			};
			using HttpResponseMessage resp = await _http.SendAsync(req, ct);
			if (!resp.IsSuccessStatusCode)
			{
				string errBody = await resp.Content.ReadAsStringAsync(ct);
				LogService.Warn($"CP4D 토큰 발급 실패: {resp.StatusCode} - {errBody}");
				return null;
			}
			using JsonDocument doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync(ct));
			if (!doc.RootElement.TryGetProperty("token", out var tokenProp))
			{
				LogService.Warn("CP4D 응답에 token 필드가 없습니다.");
				return null;
			}
			string token = tokenProp.GetString();
			if (string.IsNullOrEmpty(token))
			{
				return null;
			}
			DateTime expiry = DateTime.UtcNow.AddHours(11.0);
			if (doc.RootElement.TryGetProperty("accessTokenExpiry", out var expiryProp) && expiryProp.TryGetInt64(out var expiryMs))
			{
				expiry = DateTimeOffset.FromUnixTimeMilliseconds(expiryMs).UtcDateTime;
			}
			lock (_lock)
			{
				_cache[cacheKey] = (token, expiry);
			}
			LogService.Info($"CP4D 토큰 발급 완료: {cp4dUrl} (만료: {expiry:yyyy-MM-dd HH:mm} UTC)");
			return token;
		}
		catch (Exception ex)
		{
			LogService.Error("CP4D 토큰 발급 오류: " + ex.Message);
			return null;
		}
	}

	public static void InvalidateToken(string cp4dUrl, string username)
	{
		string key = cp4dUrl + "|" + username;
		lock (_lock)
		{
			_cache.Remove(key);
		}
	}

	public static void ClearAllTokens()
	{
		lock (_lock)
		{
			_cache.Clear();
		}
	}
}
