using System;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Npgsql;

namespace Hc900Crawler.Infrastructure.Csv
{
    public class AssetLoader
    {
        private readonly string _connectionString;
        private readonly ILogger<AssetLoader> _logger;

        public AssetLoader(IConfiguration configuration, ILogger<AssetLoader> logger)
        {
            _connectionString = configuration.GetConnectionString("DefaultConnection")
                ?? throw new InvalidOperationException("DefaultConnection 연결 문자열이 설정되지 않았습니다.");
            _logger = logger;
        }

        public async Task<int> ImportFullMapAsync(string csvPath, bool truncate = false)
        {
            _logger.LogInformation("[AssetLoader] CSV 데이터 로드 시작: {Path}", csvPath);

            if (!File.Exists(csvPath))
            {
                _logger.LogError("[AssetLoader] CSV 파일을 찾을 수 없음: {Path}", csvPath);
                return 0;
            }

            // CSV 파일 읽기 (첫 줄 헤더 제외)
            var lines = await File.ReadAllLinesAsync(csvPath);
            _logger.LogInformation("[AssetLoader] 총 {Count}개 라인 처리 시작", lines.Length - 1);

            using var conn = new NpgsqlConnection(_connectionString);
            await conn.OpenAsync();

            if (truncate)
            {
                using var cmd = new NpgsqlCommand("TRUNCATE TABLE raw_node_map", conn);
                await cmd.ExecuteNonQueryAsync();
                _logger.LogInformation("[AssetLoader] raw_node_map 테이블 초기화 완료");
            }

            // PostgreSQL Binary Copy 시작
            // level, class, name, node_id, data_type 총 5개 필드
            using (var writer = conn.BeginBinaryImport("COPY raw_node_map (level, class, name, node_id, data_type) FROM STDIN (FORMAT BINARY)"))
            {
                int count = 0;
                for (int i = 1; i < lines.Length; i++) // i=1 부터 시작하여 헤더 스킵
                {
                    var line = lines[i];
                    if (string.IsNullOrWhiteSpace(line)) continue;

                    var cols = line.Split(',');
                    if (cols.Length < 4) continue; // 최소 4개 필드(NodeId까지)는 있어야 함

                    try
                    {
                        writer.StartRow();
                        // 1. Level (int)
                        writer.Write(int.Parse(cols[0]), NpgsqlTypes.NpgsqlDbType.Integer);
                        // 2. Class (string)
                        writer.Write(cols[1], NpgsqlTypes.NpgsqlDbType.Text);
                        // 3. Name (string)
                        writer.Write(cols[2], NpgsqlTypes.NpgsqlDbType.Text);
                        // 4. NodeId (string)
                        writer.Write(cols[3], NpgsqlTypes.NpgsqlDbType.Text);

                        // 5. DataType (데이터가 없으면 "Unknown" 처리)
                        string dataType = cols.Length > 4 ? cols[4].Trim() : "Unknown";
                        writer.Write(dataType, NpgsqlTypes.NpgsqlDbType.Text);

                        count++;
                        if (count % 50000 == 0)
                            _logger.LogInformation("[AssetLoader] 진행: {Count}개 처리 중", count);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "[AssetLoader] 라인 {Line} 처리 실패", i + 1);
                    }
                }
                await writer.CompleteAsync();
                _logger.LogInformation("[AssetLoader] 총 {Count}개 노드 로드 완료", count);
                return count;
            }
        }
    }
}
