using Opc.Ua;
using System.Security.Cryptography.X509Certificates;
using OpcPks.Core.Models;

namespace OpcPks.Core.Services
{
    public class CertificateGenerator
    {
        private readonly string _pfxPath;
        private readonly string _ownCertPath;

        public CertificateGenerator(string baseDataPath)
        {
            // 경로 설정 (현재 tree 구조 반영)
            _pfxPath = Path.Combine(baseDataPath, "pki/own/private/OpcTestClient.pfx");
            _ownCertPath = Path.Combine(baseDataPath, "pki/own/certs/OpcTestClient.der");
        }

        public async Task<bool> CreateHoneywellCertificateAsync(CertRequestModel model)
        {
            try
            {
                // 1. [중요] 기존 인증서 백업
                BackupExistingCertificate();

                Console.WriteLine("🔐 하니웰 맞춤형 인증서 생성을 시작합니다...");

                // SAN 리스트 구축 (localhost 기본 포함)
                var subjectAlternativeNames = new List<string> { "localhost", "127.0.0.1" };
                
                // Primary 정보 (FTE Yellow/Green)
                if (!string.IsNullOrEmpty(model.PrimaryHostName))
                {
                    subjectAlternativeNames.Add(model.PrimaryHostName);
                    subjectAlternativeNames.Add($"{model.PrimaryHostName}A");
                }
                if (!string.IsNullOrEmpty(model.PrimaryIpA)) subjectAlternativeNames.Add(model.PrimaryIpA);
                if (!string.IsNullOrEmpty(model.PrimaryIpB)) subjectAlternativeNames.Add(model.PrimaryIpB);

                // Secondary 정보 (Redundant 선택 시)
                if (model.IsRedundant)
                {
                    if (!string.IsNullOrEmpty(model.SecondaryHostName))
                    {
                        subjectAlternativeNames.Add(model.SecondaryHostName);
                        subjectAlternativeNames.Add($"{model.SecondaryHostName}B");
                    }
                    if (!string.IsNullOrEmpty(model.SecondaryIpA)) subjectAlternativeNames.Add(model.SecondaryIpA);
                    if (!string.IsNullOrEmpty(model.SecondaryIpB)) subjectAlternativeNames.Add(model.SecondaryIpB);
                }

                // 2. 인증서 생성 (KeySize 2048, 하니웰 규격)
                // var certificate = CertificateFactory.CreateCertificate(
                //     model.ApplicationName,
                //     model.ApplicationName,
                //     null,
                //     subjectAlternativeNames,
                //     null,
                //     2048,
                //     DateTime.UtcNow.AddDays(-1),
                //     model.ValidityYears * 12,
                //     null
                // );

                // 2. 인증서 생성 (로그에 표시된 15개 인자 서명 순서 엄격 준수)
                ushort keySize = 2048;
                ushort lifetimeInMonths = (ushort)(model.ValidityYears * 12);

                var certificate = CertificateFactory.CreateCertificate(
                    "Directory",                                // 1. storeType (string)
                    Path.GetDirectoryName(_pfxPath),            // 2. storePath (string)
                    null,                                       // 3. password (string)
                    $"urn:localhost:{model.ApplicationName}",   // 4. applicationUri (string)
                    model.ApplicationName,                      // 5. applicationName (string)
                    model.ApplicationName,                      // 6. subjectName (string)
                    subjectAlternativeNames,                    // 7. domainNames (IList<string>)
                    keySize,                                    // 8. keySize (ushort)
                    DateTime.UtcNow.AddDays(-1),                // 9. startTime (DateTime)
                    lifetimeInMonths,                           // 10. lifetimeInMonths (ushort)
                    (ushort)256,                                // 11. hashSizeInBits (ushort)
                    false,                                      // 12. isCA (bool)
                    null,                                       // 13. issuer (X509Certificate2)
                    null,                                       // 14. privateKey (byte[])
                    0                                           // 15. hashAlgorithm (int)
                );


                // 3. 파일 저장
                Directory.CreateDirectory(Path.GetDirectoryName(_pfxPath)!);
                Directory.CreateDirectory(Path.GetDirectoryName(_ownCertPath)!);

                // PFX (개인키 포함) 저장
                byte[] pfxBytes = certificate.Export(X509ContentType.Pfx, "");
                await File.WriteAllBytesAsync(_pfxPath, pfxBytes);

                // DER (공개키만) 저장 - 하니웰 서버에 수동으로 신뢰 등록할 때 필요할 수 있음
                byte[] derBytes = certificate.Export(X509ContentType.Cert);
                await File.WriteAllBytesAsync(_ownCertPath, derBytes);

                Console.WriteLine($"✅ 새 인증서 생성 완료 및 백업 성공.");
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"❌ 인증서 생성 실패: {ex.Message}");
                return false;
            }
        }

        private void BackupExistingCertificate()
        {
            if (File.Exists(_pfxPath))
            {
                string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
                string backupPath = _pfxPath + "." + timestamp + ".bak";
                File.Copy(_pfxPath, backupPath, true);
                Console.WriteLine($"📦 기존 인증서 백업됨: {Path.GetFileName(backupPath)}");
            }
        }
    }
}