using System;
using System.Data;
using Npgsql;

namespace RestaurantApp.DAL
{
    public class ReportRepository
    {
        public DataTable GetDailyRevenue(DateTime dateFrom, DateTime dateTo)
        {
            var dt = new DataTable();
            using (var conn = Database.GetConnection())
            using (var cmd = new NpgsqlCommand(
                @"SELECT date(paid_at) as ""Дата"",
                         COUNT(*) as ""Платежей"",
                         SUM(amount) as ""Выручка (руб.)"",
                         AVG(amount) as ""Средний чек (руб.)""
                  FROM payment
                  WHERE paid_at::date BETWEEN @df AND @dt
                  GROUP BY date(paid_at) ORDER BY date(paid_at) DESC", conn))
            {
                cmd.Parameters.AddWithValue("df", dateFrom.Date);
                cmd.Parameters.AddWithValue("dt", dateTo.Date);
                using (var da = new NpgsqlDataAdapter(cmd)) da.Fill(dt);
            }
            return dt;
        }

        public DataTable GetDishSales(DateTime dateFrom, DateTime dateTo)
        {
            var dt = new DataTable();
            using (var conn = Database.GetConnection())
            using (var cmd = new NpgsqlCommand(
                @"SELECT d.name as ""Блюдо"",
                         dc.name as ""Категория"",
                         SUM(oi.quantity) as ""Кол-во"",
                         SUM(oi.quantity*oi.unit_price) as ""Выручка (руб.)""
                  FROM order_item oi
                  JOIN dish d ON d.dish_id=oi.dish_id
                  JOIN dish_category dc ON dc.category_id=d.category_id
                  JOIN ""order"" o ON o.order_id=oi.order_id
                  WHERE oi.status NOT IN ('cancelled')
                    AND o.opened_at::date BETWEEN @df AND @dt
                  GROUP BY d.name, dc.name
                  ORDER BY SUM(oi.quantity) DESC", conn))
            {
                cmd.Parameters.AddWithValue("df", dateFrom.Date);
                cmd.Parameters.AddWithValue("dt", dateTo.Date);
                using (var da = new NpgsqlDataAdapter(cmd)) da.Fill(dt);
            }
            return dt;
        }

        public DataTable GetWaiterStats(DateTime dateFrom, DateTime dateTo)
        {
            var dt = new DataTable();
            using (var conn = Database.GetConnection())
            using (var cmd = new NpgsqlCommand(
                @"SELECT e.last_name||' '||e.first_name as ""Официант"",
                         COUNT(DISTINCT o.order_id) as ""Заказов"",
                         SUM(o.total_amount) as ""Сумма (руб.)"",
                         AVG(o.total_amount) as ""Средний заказ (руб.)""
                  FROM ""order"" o
                  JOIN employee e ON e.employee_id=o.employee_id
                  WHERE o.status='closed'
                    AND o.opened_at::date BETWEEN @df AND @dt
                  GROUP BY e.last_name, e.first_name
                  ORDER BY SUM(o.total_amount) DESC", conn))
            {
                cmd.Parameters.AddWithValue("df", dateFrom.Date);
                cmd.Parameters.AddWithValue("dt", dateTo.Date);
                using (var da = new NpgsqlDataAdapter(cmd)) da.Fill(dt);
            }
            return dt;
        }

        public DataTable GetPaymentMethods(DateTime dateFrom, DateTime dateTo)
        {
            var dt = new DataTable();
            using (var conn = Database.GetConnection())
            using (var cmd = new NpgsqlCommand(
                @"SELECT method as ""Способ оплаты"",
                         COUNT(*) as ""Кол-во"",
                         SUM(amount) as ""Сумма (руб.)"",
                         ROUND(100.0*COUNT(*)/SUM(COUNT(*)) OVER(),1) as ""%""
                  FROM payment
                  WHERE paid_at::date BETWEEN @df AND @dt
                  GROUP BY method ORDER BY SUM(amount) DESC", conn))
            {
                cmd.Parameters.AddWithValue("df", dateFrom.Date);
                cmd.Parameters.AddWithValue("dt", dateTo.Date);
                using (var da = new NpgsqlDataAdapter(cmd)) da.Fill(dt);
            }
            return dt;
        }

        public DataTable GetLowStock()
        {
            var dt = new DataTable();
            using (var conn = Database.GetConnection())
            using (var cmd = new NpgsqlCommand(
                @"SELECT i.name as ""Ингредиент"",
                         i.unit as ""Ед. изм."",
                         i.stock_qty as ""Остаток"",
                         i.min_stock as ""Минимум"",
                         COALESCE(s.name,'') as ""Поставщик""
                  FROM ingredient i
                  LEFT JOIN supplier s ON s.supplier_id=i.supplier_id
                  WHERE i.stock_qty < i.min_stock
                  ORDER BY (i.stock_qty - i.min_stock)", conn))
            using (var da = new NpgsqlDataAdapter(cmd)) da.Fill(dt);
            return dt;
        }
    }
}
