using DBMigration.Models;
using DBMigration.Services;

namespace DBMigration.Forms
{
    public partial class MainForm : Form
    {
        private readonly DatabaseService _databaseService;
        private readonly MigrationService _migrationService;
        private ConnectionInfo? _sourceConnection;
        private ConnectionInfo? _targetConnection;
        private List<DatabaseObject>? _databaseObjects;
        private readonly CancellationTokenSource _cancellationTokenSource;

        public MainForm()
        {
            InitializeComponent();
            _databaseService = new DatabaseService();
            _migrationService = new MigrationService();
            _cancellationTokenSource = new CancellationTokenSource();
            _databaseObjects = new List<DatabaseObject>();
        }

        private async void btnConnectSource_Click(object sender, EventArgs e)
        {
            using (var form = new ConnectionForm())
            {
                if (form.ShowDialog() == DialogResult.OK)
                {
                    _sourceConnection = form.ConnectionInfo;
                    await LoadDatabaseObjectsAsync();
                }
            }
        }

        private async Task LoadDatabaseObjectsAsync()
        {
            try
            {
                btnConnectSource.Enabled = false;
                treeObjects.Nodes.Clear();
                
                // 테이블, 뷰, 프로시저 노드 생성
                var tableNode = treeObjects.Nodes.Add("Tables");
                var viewNode = treeObjects.Nodes.Add("Views");
                var procNode = treeObjects.Nodes.Add("Stored Procedures");
                
                // 테이블 로드
                tableNode.Nodes.Add("Loading...");
                treeObjects.ExpandAll();
                await LoadTablesAsync(tableNode);
                
                // 뷰 로드
                viewNode.Nodes.Add("Loading...");
                await LoadViewsAsync(viewNode);
                
                // 프로시저 로드
                procNode.Nodes.Add("Loading...");
                await LoadProceduresAsync(procNode);

                btnConnectSource.Enabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"데이터베이스 객체 로드 중 오류 발생: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
                btnConnectSource.Enabled = true;
            }
        }

        private async Task LoadTablesAsync(TreeNode parentNode)
        {
            try
            {
                parentNode.Nodes.Clear();
                parentNode.Nodes.Add("Loading...");
                
                await foreach (var table in _databaseService.GetTables(_sourceConnection!))
                {
                    if (_cancellationTokenSource.Token.IsCancellationRequested)
                        return;

                    var node = new TreeNode($"{table.Schema}.{table.Name}")
                    {
                        Tag = table,
                        Checked = table.IsSelected
                    };
                    
                    parentNode.Nodes.Add(node);
                    await Task.Yield();
                }
            }
            catch (Exception ex)
            {
                parentNode.Nodes.Clear();
                parentNode.Nodes.Add($"Error: {ex.Message}");
            }
        }

        private async Task LoadViewsAsync(TreeNode parentNode)
        {
            try
            {
                parentNode.Nodes.Clear();
                parentNode.Nodes.Add("Loading...");
                
                await foreach (var view in _databaseService.GetViews(_sourceConnection!))
                {
                    if (_cancellationTokenSource.Token.IsCancellationRequested)
                        return;

                    var node = new TreeNode($"{view.Schema}.{view.Name}")
                    {
                        Tag = view,
                        Checked = view.IsSelected
                    };
                    
                    parentNode.Nodes.Add(node);
                    await Task.Yield();
                }
            }
            catch (Exception ex)
            {
                parentNode.Nodes.Clear();
                parentNode.Nodes.Add($"Error: {ex.Message}");
            }
        }

        private async Task LoadProceduresAsync(TreeNode parentNode)
        {
            try
            {
                parentNode.Nodes.Clear();
                parentNode.Nodes.Add("Loading...");
                
                await foreach (var proc in _databaseService.GetProcedures(_sourceConnection!))
                {
                    if (_cancellationTokenSource.Token.IsCancellationRequested)
                        return;

                    var node = new TreeNode($"{proc.Schema}.{proc.Name}")
                    {
                        Tag = proc,
                        Checked = proc.IsSelected
                    };
                    
                    parentNode.Nodes.Add(node);
                    await Task.Yield();
                }
            }
            catch (Exception ex)
            {
                parentNode.Nodes.Clear();
                parentNode.Nodes.Add($"Error: {ex.Message}");
            }
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            _cancellationTokenSource.Cancel();
            base.OnFormClosing(e);
        }

        private void btnMigrate_Click(object sender, EventArgs e)
        {
            if (_targetConnection == null)
            {
                MessageBox.Show("대상 데이터베이스 연결 정보를 먼저 설정하세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            var selectedObjects = _databaseObjects.Where(o => o.IsSelected).ToList();
            if (selectedObjects.Count == 0)
            {
                MessageBox.Show("마이그레이션할 객체를 선택하세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            using (var form = new ProgressForm(selectedObjects, _sourceConnection, _targetConnection))
            {
                form.ShowDialog();
            }
        }
    }
}
