using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Elfisa.UI.Controls;
using Электронная_Фармация.Classes;
using System.Data.SQLite;

namespace Электронная_Фармация.UserControls
{
    public partial class UCInvoices : UserControl
    {
        private string _initialSourceOrderId;
        private ContextMenuStrip _invoiceMenu;
        private ToolStripMenuItem _exportInvoiceMenuItem;
        private Panel panelToolbar;
        private bool _toolbarReady;

        public UCInvoices()
            : this(null)
        {
        }

        public UCInvoices(string sourceOrderId)
        {
            InitializeComponent();
            _initialSourceOrderId = sourceOrderId;
        }

        public void SetSourceOrderFilter(string sourceOrderId)
        {
            _initialSourceOrderId = sourceOrderId;
            if (IsHandleCreated)
            {
                getDatesFromCalendar();
            }
        }

        void getDatesFromCalendar()
        {
            string dateFrom = dtpDateFrom.Value.ToString("yyyy-MM-dd");
            string dateTo = dtpDateTo.Value.ToString("yyyy-MM-dd");

            string dateFromYear = dtpDateFrom.Value.ToString("yyyy");

            loadInvoicesList(dateFrom, dateTo, dateFromYear);
        }

        string filterAddons = "";

        void loadSuppliers()
        {
            string connectionStringToLocalDB = AppConfig.SqliteConnectionString;

            string qShowMeSuppliersList = @"
select distinct SupplierName
from Invoice
where trim(ifnull(SupplierName, '')) <> ''
order by SupplierName asc";

            using (SQLiteConnection conSuppliers = new SQLiteConnection(connectionStringToLocalDB))
            {
                try
                {
                    conSuppliers.Open();
                    SQLiteCommand cmdShowMeSuppliersList = new SQLiteCommand(qShowMeSuppliersList, conSuppliers);
                    SQLiteDataAdapter daSuppliersList = new SQLiteDataAdapter(cmdShowMeSuppliersList);
                    DataTable tableSuppliers = new DataTable();
                    daSuppliersList.Fill(tableSuppliers);
                    comboSuppliers.DataSource = tableSuppliers;
                    comboSuppliers.DisplayMember = "SupplierName";
                    comboSuppliers.Text = "Поставщик";
                }
                catch(Exception ex)
                {
                    ToastNotification.ShowError($"Ошибка загрузки поставщиков: {ex.Message}");
                }
                finally
                {
                    conSuppliers.Close();
                }
            }
        }

        void loadConsignees()
        {
            string connectionStringToLocalDB = AppConfig.SqliteConnectionString;

            string qShowMeConsigneesList = @"
select distinct ConsigneesName
from Invoice
where trim(ifnull(ConsigneesName, '')) <> ''
order by ConsigneesName asc";

            using (SQLiteConnection conConsignees = new SQLiteConnection(connectionStringToLocalDB))
            {
                try
                {
                    conConsignees.Open();
                    SQLiteCommand cmdShowMeConsigneesList = new SQLiteCommand(qShowMeConsigneesList, conConsignees);
                    SQLiteDataAdapter daConsigneesList = new SQLiteDataAdapter(cmdShowMeConsigneesList);
                    DataTable tableConsignees = new DataTable();
                    daConsigneesList.Fill(tableConsignees);
                    comboConsignees.DataSource = tableConsignees;
                    comboConsignees.DisplayMember = "ConsigneesName";
                    comboConsignees.Text = "Грузополучатель";
                }
                catch (Exception ex)
                {
                    ToastNotification.ShowError($"Ошибка загрузки грузополучателей: {ex.Message}");
                }
                finally
                {
                    conConsignees.Close();
                }
            }
        }

        void loadInvoicesList(string InvoicesDateFrom, string InvoicesDateTo, string dateFromYearFormat)
        {
            string connectionStringToLocalDB = AppConfig.SqliteConnectionString;

            using (SQLiteConnection conInvoices = new SQLiteConnection(connectionStringToLocalDB))
            {
                try
                {
                    conInvoices.Open();
                    var sql = @"
select
    i.[idInvoice] as [ИД накладной],
    i.[InvoiceNumber] as [Номер],
    i.[InvoiceDate] as [Дата],
    ifnull(i.[SupplierName], '') as [Поставщик],
    ifnull(i.[ConsigneesName], '') as [Грузополучатель],
    i.[SourceOrderNumber] as [Номер заказа],
    coalesce(i.[InvoiceSum], i.[SumWithNDS], i.[SumWithoutNDS], 0) as [Сумма],
    coalesce(i.[RefuseSum], 0) as [Сумма отказа]
from [Invoice] i
where date(i.[InvoiceDate]) between date(@dateFrom) and date(@dateTo)";

                    if (txtInvoiceNumber.Text != "" && txtInvoiceNumber.Text != "Номер накладной")
                    {
                        sql += " and i.[InvoiceNumber] like @invoiceNumber";
                    }

                    if (comboSuppliers.Text != "" && comboSuppliers.Text != "Поставщик")
                    {
                        sql += " and ifnull(i.[SupplierName], '') like @supplierName";
                    }

                    if (comboConsignees.Text != "" && comboConsignees.Text != "Грузополучатель")
                    {
                        sql += " and ifnull(i.[ConsigneesName], '') like @consigneeName";
                    }

                    if (!string.IsNullOrWhiteSpace(_initialSourceOrderId))
                    {
                        sql += " and cast(i.[SourceOrderId] as text) = @sourceOrderId";
                    }

                    sql += " order by date(i.[InvoiceDate]) desc, i.[idInvoice] desc;";

                    SQLiteCommand cmdShowInvoicesList = new SQLiteCommand(sql, conInvoices);
                    cmdShowInvoicesList.Parameters.AddWithValue("@dateFrom", InvoicesDateFrom);
                    cmdShowInvoicesList.Parameters.AddWithValue("@dateTo", InvoicesDateTo);
                    if (txtInvoiceNumber.Text != "" && txtInvoiceNumber.Text != "Номер накладной")
                    {
                        cmdShowInvoicesList.Parameters.AddWithValue("@invoiceNumber", $"%{txtInvoiceNumber.Text}%");
                    }

                    if (comboSuppliers.Text != "" && comboSuppliers.Text != "Поставщик")
                    {
                        cmdShowInvoicesList.Parameters.AddWithValue("@supplierName", $"%{comboSuppliers.Text}%");
                    }

                    if (comboConsignees.Text != "" && comboConsignees.Text != "Грузополучатель")
                    {
                        cmdShowInvoicesList.Parameters.AddWithValue("@consigneeName", $"%{comboConsignees.Text}%");
                    }

                    if (!string.IsNullOrWhiteSpace(_initialSourceOrderId))
                    {
                        cmdShowInvoicesList.Parameters.AddWithValue("@sourceOrderId", _initialSourceOrderId);
                    }

                    DataTable tableInvoices = new DataTable();
                    SQLiteDataAdapter daInvoicesList = new SQLiteDataAdapter(cmdShowInvoicesList);
                    daInvoicesList.Fill(tableInvoices);
                    dgvInvoice.DataSource = tableInvoices;

                    if (dgvInvoice.Columns.Count > 0)
                    {
                        dgvInvoice.Columns["ИД накладной"].Visible = false;
                    }
                }
                catch (Exception ex)
                {
                    ToastNotification.ShowError($"Ошибка загрузки накладных: {ex.Message}");
                }
                finally
                {
                    conInvoices.Close();
                }
            }



            loadInvoiceItems(string.Empty);

            //selectInvoice();
        }

        private void UCInvoices_Load(object sender, EventArgs e)
        {
            UiThemeHelper.ApplyToControlTree(this);
            Font = new Font("Segoe UI", 9.75f, FontStyle.Regular);
            InitializeInvoiceContextMenu();
            EnsureInvoiceToolbar();

            button1.Visible = true;
            button1.Text = "Обновить с сервера";
            ModernButtonStyles.ApplyAuto(button1);
            button1.Click -= Button1_SyncClick;
            button1.Click += Button1_SyncClick;

            ModernButtonStyles.ApplyClear(btnClearSuppliers);
            ModernButtonStyles.ApplyClear(btnClearConsignees);
            btnClearSuppliers.Text = "×";
            btnClearConsignees.Text = "×";

            ApplyToolbarLayout();

            loadConsignees();
            loadSuppliers();
            getDatesFromCalendar();
        }

        private async void Button1_SyncClick(object sender, EventArgs e)
        {
            await SyncFromServerAsync();
        }

        private void EnsureInvoiceToolbar()
        {
            if (_toolbarReady)
            {
                return;
            }

            panelToolbar = new Panel
            {
                Name = "panelToolbar",
                Dock = DockStyle.Top,
                Height = 96,
                Padding = new Padding(12, 10, 12, 14),
                Tag = "toolbar"
            };

            var toolbarControls = new Control[]
            {
                button1,
                dtpDateFrom,
                label1,
                dtpDateTo,
                txtInvoiceNumber,
                comboSuppliers,
                btnClearSuppliers,
                comboConsignees,
                btnClearConsignees
            };

            foreach (var control in toolbarControls)
            {
                Controls.Remove(control);
                panelToolbar.Controls.Add(control);
            }

            Controls.Add(panelToolbar);
            panelToolbar.BringToFront();

            PContentInvoice.Dock = DockStyle.Fill;
            PContentInvoice.BringToFront();
            panelToolbar.BringToFront();

            panelToolbar.Resize += (_, __) => ApplyToolbarLayout();
            Resize += (_, __) => ApplyToolbarLayout();
            _toolbarReady = true;
        }

        private void ApplyToolbarLayout()
        {
            if (panelToolbar == null)
            {
                return;
            }

            const int pad = 12;
            const int gap = 8;
            const int clearGap = 4;
            const int controlHeight = 32;
            const int buttonHeight = 34;
            const int rowGap = 10;
            const int refreshWidth = 180;
            const int dateWidth = 112;
            const int clearSize = 32;
            const int invoicePreferred = 200;
            const int invoiceMin = 140;
            const int supplierPreferred = 170;
            const int consigneePreferred = 190;
            const int supplierMin = 130;
            const int consigneeMin = 150;

            var panelWidth = Math.Max(panelToolbar.ClientSize.Width, 360);
            int y = 10;
            int x = pad;

            button1.SetBounds(x, y, refreshWidth, buttonHeight);
            x = button1.Right + gap;

            dtpDateFrom.SetBounds(x, y + 1, dateWidth, controlHeight);
            x = dtpDateFrom.Right + 6;
            label1.AutoSize = true;
            label1.Location = new Point(x, y + 5);
            x = label1.Right + 6;
            dtpDateTo.SetBounds(x, y + 1, dateWidth, controlHeight);
            x = dtpDateTo.Right + gap;

            int invoiceWidth = Math.Max(invoiceMin, Math.Min(invoicePreferred, panelWidth - pad - x));
            if (invoiceWidth < invoiceMin || x + invoiceMin > panelWidth - pad)
            {
                y += buttonHeight + rowGap;
                x = pad;
                invoiceWidth = Math.Max(invoiceMin, Math.Min(invoicePreferred, panelWidth - pad * 2));
            }

            txtInvoiceNumber.SetBounds(x, y + 1, invoiceWidth, controlHeight);

            y += buttonHeight + rowGap;
            x = pad;

            int filtersAvailable = panelWidth - pad * 2 - clearSize * 2 - clearGap * 2 - gap;
            int supplierWidth;
            int consigneeWidth;
            if (filtersAvailable >= supplierPreferred + consigneePreferred)
            {
                supplierWidth = supplierPreferred;
                consigneeWidth = consigneePreferred;
            }
            else
            {
                float scale = filtersAvailable / (float)(supplierPreferred + consigneePreferred);
                supplierWidth = Math.Max(supplierMin, (int)(supplierPreferred * scale));
                consigneeWidth = Math.Max(consigneeMin, filtersAvailable - supplierWidth);
            }

            if (pad + supplierWidth + clearGap + clearSize + gap + consigneeWidth + clearGap + clearSize > panelWidth)
            {
                // Wrap consignee to next row on very narrow widths.
                supplierWidth = Math.Max(supplierMin, panelWidth - pad * 2 - clearGap - clearSize);
                comboSuppliers.SetBounds(x, y + 1, supplierWidth, controlHeight);
                btnClearSuppliers.SetBounds(comboSuppliers.Right + clearGap, y, clearSize, controlHeight);

                y += buttonHeight + rowGap;
                x = pad;
                consigneeWidth = Math.Max(consigneeMin, panelWidth - pad * 2 - clearGap - clearSize);
                comboConsignees.SetBounds(x, y + 1, consigneeWidth, controlHeight);
                btnClearConsignees.SetBounds(comboConsignees.Right + clearGap, y, clearSize, controlHeight);
            }
            else
            {
                comboSuppliers.SetBounds(x, y + 1, supplierWidth, controlHeight);
                btnClearSuppliers.SetBounds(comboSuppliers.Right + clearGap, y, clearSize, controlHeight);
                x = btnClearSuppliers.Right + gap;
                comboConsignees.SetBounds(x, y + 1, consigneeWidth, controlHeight);
                btnClearConsignees.SetBounds(comboConsignees.Right + clearGap, y, clearSize, controlHeight);
            }

            panelToolbar.Height = y + buttonHeight + pad + 4;
            panelToolbar.Padding = new Padding(pad, 10, pad, 14);
        }

        private async Task SyncFromServerAsync()
        {
            button1.Enabled = false;
            UseWaitCursor = true;
            try
            {
                var sync = new InvoiceSyncService();
                int count = await sync.SyncFromServerAsync();
                ToastNotification.ShowSuccess($"Загружено накладных: {count}");
                getDatesFromCalendar();
            }
            catch (Exception ex)
            {
                AppDebugLog.Error("Invoices", "Не удалось загрузить накладные с API", ex);
                ToastNotification.ShowError($"Не удалось загрузить накладные: {ex.Message}");
            }
            finally
            {
                button1.Enabled = true;
                UseWaitCursor = false;
            }
        }

        private void InitializeInvoiceContextMenu()
        {
            if (_invoiceMenu != null)
            {
                return;
            }

            _exportInvoiceMenuItem = new ToolStripMenuItem("Экспортировать в папку");
            _exportInvoiceMenuItem.Click += (_, __) => ExportSelectedInvoice();

            _invoiceMenu = new ContextMenuStrip();
            _invoiceMenu.Items.Add(_exportInvoiceMenuItem);
            _invoiceMenu.Opening += InvoiceMenu_Opening;

            dgvInvoice.ContextMenuStrip = _invoiceMenu;
        }

        private void InvoiceMenu_Opening(object sender, CancelEventArgs e)
        {
            var pt = dgvInvoice.PointToClient(Cursor.Position);
            var hit = dgvInvoice.HitTest(pt.X, pt.Y);
            if (hit.RowIndex < 0 || hit.RowIndex >= dgvInvoice.Rows.Count)
            {
                e.Cancel = true;
                return;
            }

            dgvInvoice.ClearSelection();
            dgvInvoice.Rows[hit.RowIndex].Selected = true;
            if (hit.ColumnIndex >= 0)
            {
                dgvInvoice.CurrentCell = dgvInvoice.Rows[hit.RowIndex].Cells[hit.ColumnIndex];
            }

            _exportInvoiceMenuItem.Enabled = true;
        }


        private void dtpDateTo_Leave(object sender, EventArgs e)
        {
            getDatesFromCalendar();
        }

        private void dtpDateFrom_Leave(object sender, EventArgs e)
        {
            getDatesFromCalendar();
        }

        private void dtpDateTo_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                getDatesFromCalendar();
            }
        }

        private void dtpDateFrom_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                getDatesFromCalendar();
            }
        }


        void selectInvoice()
        {
            if (dgvInvoice.Rows.Count > 0 && dgvInvoice.CurrentCell != null)
            {
                int SelectedInvoiceIndex = dgvInvoice.CurrentCell.RowIndex;
                string SelectedInvoiceId = dgvInvoice.Rows[SelectedInvoiceIndex].Cells["ИД накладной"]?.Value?.ToString() ?? string.Empty;
                loadInvoiceItems(SelectedInvoiceId);
            }
        }

        void loadInvoiceItems(string invoiceId)
        {
            if (dgvInvoice.Rows.Count > 0)
            {
                if (!string.IsNullOrWhiteSpace(invoiceId))
                {
                    string connectionStringToLocalDB = AppConfig.SqliteConnectionString;
                    string qShowMeInvoiceItems = @"
select
ii.GoodCode as [Код товара],
ii.Good as [Товар],
ii.ProducerName as [Производитель],
ii.CountryName as [Страна],
ii.GoodsGount as [Количество],
ii.PriceSupplierWithoutNDS as [Цена пост. без НДС],
ii.PriceSupplierWithNDS as [Цена пост. с НДС],
ii.PriceProducerWithoutNDS as [Цена произв. без НДС],
ii.PriceProducerWithNDS as [Цена произв. с НДС],
ii.NDS as [НДС %],
ii.JNVLS as [ЖНВЛП?],
ii.PriceReestr as [Предел. цена произв.],
ii.SumWithoutNDS as [Сумма пост. без НДС],
ii.SumWithNDS as [Сумма пост. с НДС],
ii.SumNDS as [Сумма НДС],
ii.Serial as [Серия],
ii.BestBefore as [Срок годности],
ii.Sertificate as [Сертификат],
ii.Marked as [Признак маркировки],
ii.GTIN as [GTIN]
from InvoiceItem ii
where ii.idInvoice = @invoiceId;";
                    using (SQLiteConnection conInvoiceItems = new SQLiteConnection(connectionStringToLocalDB))
                    {
                        try
                        {
                            conInvoiceItems.Open();
                            SQLiteCommand cmdShowMeInvoiceItems = new SQLiteCommand(qShowMeInvoiceItems, conInvoiceItems);
                            cmdShowMeInvoiceItems.Parameters.AddWithValue("@invoiceId", invoiceId);
                            DataTable tableInvoiceItems = new DataTable();
                            SQLiteDataAdapter daInvoiceItems = new SQLiteDataAdapter(cmdShowMeInvoiceItems);
                            daInvoiceItems.Fill(tableInvoiceItems);
                            dgvInvoiceItems.DataSource = tableInvoiceItems;
                            if (dgvInvoiceItems.Columns.Count > 10)
                            {
                                dgvInvoiceItems.Columns[10].ValueType = typeof(bool);
                            }
                        }
                        catch (Exception ex)
                        {
                            ToastNotification.ShowError($"Ошибка загрузки позиций накладной: {ex.Message}");
                        }
                        finally
                        {
                            conInvoiceItems.Close();
                        }
                    }

                }
            }
            else
            {
                dgvInvoiceItems.DataSource = null;
            }
        }

        private void ExportSelectedInvoice()
        {
            if (dgvInvoice.SelectedRows.Count == 0)
            {
                ToastNotification.ShowCustom("Выберите накладную для экспорта.", Color.DarkOrange, Color.White);
                return;
            }

            var row = dgvInvoice.SelectedRows[0];
            var invoiceId = row.Cells["ИД накладной"]?.Value?.ToString() ?? string.Empty;
            var invoiceNumber = row.Cells["Номер"]?.Value?.ToString() ?? string.Empty;

            if (string.IsNullOrWhiteSpace(invoiceId))
            {
                ToastNotification.ShowCustom("Не удалось определить накладную для экспорта.", Color.DarkOrange, Color.White);
                return;
            }

            try
            {
                var exportService = new InvoiceExportService();
                var filePath = exportService.ExportInvoice(invoiceId, FindForm());
                ToastNotification.ShowSuccess($"Накладная {invoiceNumber} сохранена:\n{filePath}");
            }
            catch (Exception ex)
            {
                AppDebugLog.Error("Invoices", $"Ошибка экспорта накладной {invoiceNumber}", ex);
                ToastNotification.ShowError($"Не удалось экспортировать накладную: {ex.Message}");
            }
        }

        private void txtInvoiceNumber_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                if (dgvInvoice.Rows.Count > 0)
                {
                    (dgvInvoice.DataSource as DataTable).DefaultView.RowFilter = string.Format($"[Номер] like '%{txtInvoiceNumber.Text}%'");
                    if (dgvInvoice.Rows.Count == 0)
                    {
                        getDatesFromCalendar();
                    }
                }
                    txtInvoiceNumber.Text = "Номер накладной";
                dgvInvoice.Focus();
            }
        }

        private void txtInvoiceNumber_Enter(object sender, EventArgs e)
        {
            if (txtInvoiceNumber.Text == "Номер накладной") 
            {
                txtInvoiceNumber.Text = string.Empty;
            }
        }

        private void txtInvoiceNumber_Leave(object sender, EventArgs e)
        {
            if (txtInvoiceNumber.Text == string.Empty)
            {
                txtInvoiceNumber.Text = "Номер накладной";
            }
        }

        private void comboSuppliers_SelectedIndexChanged(object sender, EventArgs e)
        {
            getDatesFromCalendar();
            selectInvoice();
        }

        private void comboConsignees_SelectedIndexChanged(object sender, EventArgs e)
        {
            getDatesFromCalendar();
            selectInvoice();
        }

        private void btnClearSuppliers_Click(object sender, EventArgs e)
        {
            loadSuppliers();
            getDatesFromCalendar();
        }

        private void btnClearConsignees_Click(object sender, EventArgs e)
        {
            loadConsignees();
            getDatesFromCalendar();
        }

        private void dgvInvoice_SelectionChanged(object sender, EventArgs e)
        {
            selectInvoice();
        }
    }
}
