using System;
using System.Collections.Generic;
using System.Data.SQLite;

namespace Электронная_Фармация.Classes
{
    /// <summary>
    /// Аптека = грузополучатель + LocationId. Прайс общий, заказы уходят с location_id выбранной аптеки.
    /// </summary>
    public static class ConsigneeHelper
    {
        public static string GetDefaultConsigneeName()
        {
            try
            {
                using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
                {
                    connection.Open();
                    using (var command = new SQLiteCommand(
                        @"SELECT ConsigneesName
                          FROM Consignees
                          ORDER BY ConsigneesUseAsDefault DESC, ConsigneesName
                          LIMIT 1",
                        connection))
                    {
                        var result = command.ExecuteScalar();
                        return result == null || result == DBNull.Value
                            ? string.Empty
                            : result.ToString().Trim();
                    }
                }
            }
            catch
            {
                return string.Empty;
            }
        }

        public static string GetLocationIdByName(string consigneeName)
        {
            if (string.IsNullOrWhiteSpace(consigneeName))
            {
                return string.Empty;
            }

            using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
            {
                connection.Open();
                using (var command = new SQLiteCommand(
                    @"SELECT ifnull(LocationId, '')
                      FROM Consignees
                      WHERE ConsigneesName = @name
                      LIMIT 1",
                    connection))
                {
                    command.Parameters.AddWithValue("@name", consigneeName.Trim());
                    var result = command.ExecuteScalar();
                    return result == null || result == DBNull.Value
                        ? string.Empty
                        : result.ToString().Trim();
                }
            }
        }

        public static string ResolveLocationId(string consigneeName)
        {
            var fromConsignee = GetLocationIdByName(consigneeName);
            if (!string.IsNullOrWhiteSpace(fromConsignee))
            {
                return fromConsignee;
            }

            return AppConfig.LocationId ?? string.Empty;
        }

        /// <summary>
        /// Помечает аптеку активной и синхронизирует AppConfig.LocationId.
        /// </summary>
        public static void SetActiveConsignee(string consigneeName)
        {
            if (string.IsNullOrWhiteSpace(consigneeName))
            {
                return;
            }

            var name = consigneeName.Trim();
            using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
            {
                connection.Open();
                using (var tx = connection.BeginTransaction())
                {
                    using (var clear = new SQLiteCommand(
                        "UPDATE Consignees SET ConsigneesUseAsDefault = 0",
                        connection,
                        tx))
                    {
                        clear.ExecuteNonQuery();
                    }

                    using (var setDefault = new SQLiteCommand(
                        @"UPDATE Consignees
                          SET ConsigneesUseAsDefault = 1
                          WHERE ConsigneesName = @name",
                        connection,
                        tx))
                    {
                        setDefault.Parameters.AddWithValue("@name", name);
                        setDefault.ExecuteNonQuery();
                    }

                    tx.Commit();
                }

                var locationId = GetLocationIdByName(name);
                if (!string.IsNullOrWhiteSpace(locationId))
                {
                    AppConfig.SetLocationId(locationId);
                }
            }
        }

        public static void SetLocationId(string consigneeName, string locationId)
        {
            if (string.IsNullOrWhiteSpace(consigneeName))
            {
                return;
            }

            using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
            {
                connection.Open();
                using (var command = new SQLiteCommand(
                    @"UPDATE Consignees
                      SET LocationId = @loc
                      WHERE ConsigneesName = @name",
                    connection))
                {
                    command.Parameters.AddWithValue("@loc", (locationId ?? string.Empty).Trim());
                    command.Parameters.AddWithValue("@name", consigneeName.Trim());
                    command.ExecuteNonQuery();
                }
            }
        }

        public static void MigrateGlobalLocationIdIfNeeded(SQLiteConnection connection)
        {
            var global = AppConfig.LocationId;
            if (string.IsNullOrWhiteSpace(global))
            {
                return;
            }

            using (var command = new SQLiteCommand(
                @"UPDATE Consignees
                  SET LocationId = @loc
                  WHERE (LocationId IS NULL OR trim(LocationId) = '')
                    AND (
                        ConsigneesUseAsDefault = 1
                        OR (SELECT COUNT(*) FROM Consignees) = 1
                    )",
                connection))
            {
                command.Parameters.AddWithValue("@loc", global.Trim());
                command.ExecuteNonQuery();
            }
        }

        public static void ApplyLocationIdToEmptyConsignees(string locationId)
        {
            if (string.IsNullOrWhiteSpace(locationId))
            {
                return;
            }

            using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
            {
                connection.Open();
                using (var command = new SQLiteCommand(
                    @"UPDATE Consignees
                      SET LocationId = @loc
                      WHERE LocationId IS NULL OR trim(LocationId) = ''",
                    connection))
                {
                    command.Parameters.AddWithValue("@loc", locationId.Trim());
                    command.ExecuteNonQuery();
                }
            }
        }

        public static IList<string> GetKnownSupplierIds()
        {
            var result = new List<string>();
            using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
            {
                connection.Open();
                using (var command = new SQLiteCommand(
                    @"SELECT DISTINCT trim(supplier_id)
                      FROM PriceList
                      WHERE supplier_id IS NOT NULL AND trim(supplier_id) <> ''
                      ORDER BY 1",
                    connection))
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        var id = reader.GetString(0);
                        if (!string.IsNullOrWhiteSpace(id))
                        {
                            result.Add(id);
                        }
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// Процент наценки, который клиент задал вручную для аптеки.
        /// null = ещё не сохраняли, брать fallback.
        /// </summary>
        public static decimal? GetClientMarkupPercent(string consigneeName)
        {
            if (string.IsNullOrWhiteSpace(consigneeName))
            {
                return null;
            }

            try
            {
                using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
                {
                    connection.Open();
                    using (var command = new SQLiteCommand(
                        @"SELECT ClientMarkupPercent
                          FROM Consignees
                          WHERE ConsigneesName = @name
                          LIMIT 1",
                        connection))
                    {
                        command.Parameters.AddWithValue("@name", consigneeName.Trim());
                        var result = command.ExecuteScalar();
                        if (result == null || result == DBNull.Value)
                        {
                            return null;
                        }

                        if (result is decimal d)
                        {
                            return d;
                        }

                        if (decimal.TryParse(
                            Convert.ToString(result, System.Globalization.CultureInfo.InvariantCulture),
                            System.Globalization.NumberStyles.Any,
                            System.Globalization.CultureInfo.InvariantCulture,
                            out var parsed))
                        {
                            return parsed;
                        }

                        return null;
                    }
                }
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Сохраняет процент наценки клиента для конкретной аптеки.
        /// Не сбрасывается при обновлении прайса.
        /// </summary>
        public static void SetClientMarkupPercent(string consigneeName, decimal markupPercent)
        {
            if (string.IsNullOrWhiteSpace(consigneeName))
            {
                return;
            }

            using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
            {
                connection.Open();
                using (var command = new SQLiteCommand(
                    @"UPDATE Consignees
                      SET ClientMarkupPercent = @pct
                      WHERE ConsigneesName = @name",
                    connection))
                {
                    command.Parameters.AddWithValue("@pct", markupPercent);
                    command.Parameters.AddWithValue("@name", consigneeName.Trim());
                    command.ExecuteNonQuery();
                }
            }
        }

        /// <summary>
        /// Если у аптеки ещё нет сохранённого процента — записать стартовое значение с сервера.
        /// Уже введённые клиентом значения не трогаем.
        /// </summary>
        public static void SeedClientMarkupPercentIfEmpty(decimal? serverMarkupPercent)
        {
            if (!serverMarkupPercent.HasValue)
            {
                return;
            }

            using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
            {
                connection.Open();
                using (var command = new SQLiteCommand(
                    @"UPDATE Consignees
                      SET ClientMarkupPercent = @pct
                      WHERE ClientMarkupPercent IS NULL",
                    connection))
                {
                    command.Parameters.AddWithValue("@pct", serverMarkupPercent.Value);
                    command.ExecuteNonQuery();
                }
            }
        }

        /// <summary>
        /// Подтягивает грузополучателей с сервера (BuyerLocation) в локальную таблицу Consignees.
        /// Источник истины — веб-кабинет; локально только кэш + выбор активной аптеки.
        /// </summary>
        public static int SyncFromServer(IList<BuyerLocationDto> locations)
        {
            if (locations == null || locations.Count == 0)
            {
                return 0;
            }

            var upserted = 0;
            using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
            {
                connection.Open();
                using (var tx = connection.BeginTransaction())
                {
                    // Сбрасываем default — выставим по данным сервера.
                    using (var clearDefault = new SQLiteCommand(
                        "UPDATE Consignees SET ConsigneesUseAsDefault = 0",
                        connection,
                        tx))
                    {
                        clearDefault.ExecuteNonQuery();
                    }

                    int nextCode;
                    using (var nextCodeCmd = new SQLiteCommand(
                        "SELECT ifnull(MAX(codeConsignees), 0) + 1 FROM Consignees",
                        connection,
                        tx))
                    {
                        nextCode = Convert.ToInt32(nextCodeCmd.ExecuteScalar());
                    }

                    foreach (var loc in locations)
                    {
                        var locationId = (loc.BuyerLocationID ?? string.Empty).Trim();
                        if (string.IsNullOrWhiteSpace(locationId))
                        {
                            continue;
                        }

                        var address = (loc.Address ?? string.Empty).Trim();
                        if (string.IsNullOrWhiteSpace(address))
                        {
                            address = "Грузополучатель";
                        }

                        var name = address;
                        if (name.Length > 120)
                        {
                            name = name.Substring(0, 120);
                        }

                        long? existingId = null;
                        using (var find = new SQLiteCommand(
                            @"SELECT idConsignees FROM Consignees
                              WHERE lower(trim(LocationId)) = lower(@loc)
                              LIMIT 1",
                            connection,
                            tx))
                        {
                            find.Parameters.AddWithValue("@loc", locationId);
                            var found = find.ExecuteScalar();
                            if (found != null && found != DBNull.Value)
                            {
                                existingId = Convert.ToInt64(found);
                            }
                        }

                        if (existingId.HasValue)
                        {
                            using (var upd = new SQLiteCommand(
                                @"UPDATE Consignees
                                  SET ConsigneesName = @name,
                                      ConsigneesAddress = @address,
                                      ConsigneesUseAsDefault = @isDefault,
                                      LocationId = @loc
                                  WHERE idConsignees = @id",
                                connection,
                                tx))
                            {
                                upd.Parameters.AddWithValue("@name", name);
                                upd.Parameters.AddWithValue("@address", address);
                                upd.Parameters.AddWithValue("@isDefault", loc.IsDefault ? 1 : 0);
                                upd.Parameters.AddWithValue("@loc", locationId);
                                upd.Parameters.AddWithValue("@id", existingId.Value);
                                upd.ExecuteNonQuery();
                            }
                        }
                        else
                        {
                            using (var ins = new SQLiteCommand(
                                @"INSERT INTO Consignees
                                  (codeConsignees, ConsigneesName, ConsigneesAddress, ConsigneesUseAsDefault, LocationId)
                                  VALUES (@code, @name, @address, @isDefault, @loc)",
                                connection,
                                tx))
                            {
                                ins.Parameters.AddWithValue("@code", nextCode++);
                                ins.Parameters.AddWithValue("@name", name);
                                ins.Parameters.AddWithValue("@address", address);
                                ins.Parameters.AddWithValue("@isDefault", loc.IsDefault ? 1 : 0);
                                ins.Parameters.AddWithValue("@loc", locationId);
                                ins.ExecuteNonQuery();
                            }
                        }

                        upserted++;
                    }

                    tx.Commit();
                }
            }

            var active = GetDefaultConsigneeName();
            if (!string.IsNullOrWhiteSpace(active))
            {
                SetActiveConsignee(active);
            }

            return upserted;
        }

        /// <summary>
        /// Синхронизирует поля заказа в `PriceList` (Zakaz/SummaZakaza) с корзиной выбранной аптеки.
        /// Данные корзины хранятся в TempOrderItems с фильтром по ConsigneeName, а PriceList обновляется
        /// только для текущего активного просмотра.
        /// </summary>
        public static void SyncCartToPriceList(string consigneeName)
        {
            var consignee = (consigneeName ?? string.Empty).Trim().Replace("'", "''");
            using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
            {
                connection.Open();

                using (var tx = connection.BeginTransaction())
                {
                    using (var clear = new SQLiteCommand(
                        @"UPDATE [PriceList]
                          SET [Zakaz] = NULL, [SummaZakaza] = NULL;", connection, tx))
                    {
                        clear.ExecuteNonQuery();
                    }

                    using (var sync = new SQLiteCommand(
                        @"UPDATE [PriceList]
                          SET
                            [Zakaz] = (
                                SELECT t.[Zakaz]
                                FROM [TempOrderItems] t
                                WHERE t.[ConsigneeName] = @consignee
                                  AND t.[id_PriceList_Item] = [PriceList].[id_PriceList_Item]
                                LIMIT 1
                            ),
                            [SummaZakaza] = (
                                SELECT t.[SummaZakaza]
                                FROM [TempOrderItems] t
                                WHERE t.[ConsigneeName] = @consignee
                                  AND t.[id_PriceList_Item] = [PriceList].[id_PriceList_Item]
                                LIMIT 1
                            )
                          WHERE EXISTS (
                                SELECT 1
                                FROM [TempOrderItems] t
                                WHERE t.[ConsigneeName] = @consignee
                                  AND t.[id_PriceList_Item] = [PriceList].[id_PriceList_Item]
                          );",
                        connection,
                        tx))
                    {
                        sync.Parameters.AddWithValue("@consignee", consignee);
                        sync.ExecuteNonQuery();
                    }

                    tx.Commit();
                }
            }
        }
    }
}
