using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using RevitEstimate.Models;

namespace RevitEstimate.Calculators
{
    public class Item24Calculator : IItemCalculator
    {
        private ProjectLevels _levels;

        public Item24Calculator(ProjectLevels levels = null)
        {
            _levels = levels ?? new ProjectLevels();
        }

        private class FloorLevelInfo
        {
            public string Name { get; set; }
            public double BottomZ { get; set; }
            public double TopZ { get; set; }
        }

        public List<EstimateRowModel> Calculate(List<Element> collector, out double totalQty)
        {
            totalQty = 0.0;
            var rows = new List<EstimateRowModel>();

            Document doc = collector.FirstOrDefault()?.Document;
            if (doc == null) return rows;

            // ==========================================
            // SETUP ACTIVE FLOORS FROM LEVEL WINDOW
            // ==========================================
            var activeFloors = new List<FloorLevelInfo>();
            activeFloors.Add(new FloorLevelInfo { Name = "GF", BottomZ = _levels.TopOfPlinth, TopZ = _levels.SlabTop });
            double currentTop = _levels.SlabTop;

            if (_levels.FirstFloorSlabTop != -8888 && _levels.FirstFloorSlabTop != 0)
            {
                activeFloors.Add(new FloorLevelInfo { Name = "FF", BottomZ = currentTop, TopZ = _levels.FirstFloorSlabTop });
                currentTop = _levels.FirstFloorSlabTop;
            }
            if (_levels.SecondFloorSlabTop != -8888 && _levels.SecondFloorSlabTop != 0)
            {
                activeFloors.Add(new FloorLevelInfo { Name = "SF", BottomZ = currentTop, TopZ = _levels.SecondFloorSlabTop });
                currentTop = _levels.SecondFloorSlabTop;
            }
            if (_levels.ThirdFloorSlabTop != -8888 && _levels.ThirdFloorSlabTop != 0)
            {
                activeFloors.Add(new FloorLevelInfo { Name = "TF", BottomZ = currentTop, TopZ = _levels.ThirdFloorSlabTop });
                currentTop = _levels.ThirdFloorSlabTop;
            }
            if (_levels.TerraceRoofTop != -8888 && _levels.TerraceRoofTop != 0)
            {
                activeFloors.Add(new FloorLevelInfo { Name = "Terrace", BottomZ = currentTop, TopZ = _levels.TerraceRoofTop });
            }

            // ==========================================
            // PART 1: KITCHEN COUNTERS / SLABS (< 1.8m height from floor)
            // ==========================================
            var floors = collector.Where(e => e.Category != null && e.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Floors).Cast<Floor>().ToList();

            foreach (var slab in floors)
            {
                BoundingBoxXYZ box = slab.get_BoundingBox(null);
                if (box == null) continue;

                double slabZ = UnitUtils.ConvertFromInternalUnits((box.Min.Z + box.Max.Z) / 2.0, UnitTypeId.Meters);

                // Find which floor this slab belongs to
                var floor = activeFloors.FirstOrDefault(f => slabZ >= (f.BottomZ - 0.5) && slabZ <= (f.TopZ + 0.5));
                if (floor == null) continue;

                // Check if slab height is below 1.8m from the adjacent bottom floor
                double heightAboveFloor = slabZ - floor.BottomZ;
                if (heightAboveFloor > 0 && heightAboveFloor <= 1.8)
                {
                    // Optional: check if associated room name contains "Kitchen"
                    bool isKitchenRelated = true;
                    // (Revit floors directly don't hold room names unless queried via spatial element, keeping it general for platform slabs)

                    if (isKitchenRelated)
                    {
                        double area = GetFloorArea(slab);
                        double length = Math.Sqrt(area); // Approximate length representation if rectangular
                        double width = Math.Sqrt(area);  // Approximate width representation

                        totalQty += area;

                        rows.Add(new EstimateRowModel
                        {
                            SNo = "",
                            ItemOfWork = $"   -> Kitchen Counter / Slab Top (Kota Stone) ({floor.Name}): {slab.Name} [ID: {slab.Id}]",
                            NosOfFlats = "1",
                            NosOfInstance = "1",
                            Length = area.ToString("F2"), // Displaying Area in Length column or standard format
                            Width = "",
                            HeightDepth = "",
                            Qty = area.ToString("F2"),
                            Unit = "Sqm",
                            Remarks = $"Kitchen slab surface at {heightAboveFloor:F2}m height from {floor.Name} bottom."
                        });
                    }
                }
            }

            // ==========================================
            // PART 2: STAIRS (Treads, Risers, Landings)
            // ==========================================
            var stairs = collector.Where(e => e.Category != null && e.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Stairs).ToList();

            foreach (var stair in stairs)
            {
                // Extract stair parameters (Tread / Riser / Landing areas if available)
                double stairArea = GetStairAreaParameter(stair);
                if (stairArea > 0)
                {
                    totalQty += stairArea;

                    rows.Add(new EstimateRowModel
                    {
                        SNo = "",
                        ItemOfWork = $"   -> Stair Finish (Treads/Risers/Landing): {stair.Name} [ID: {stair.Id}]",
                        NosOfFlats = "1",
                        NosOfInstance = "1",
                        Length = stairArea.ToString("F2"),
                        Width = "",
                        HeightDepth = "",
                        Qty = stairArea.ToString("F2"),
                        Unit = "Sqm",
                        Remarks = "Calculated from stair parameters (Tread/Riser/Landing)."
                    });
                }
            }

            if (rows.Count == 0)
            {
                rows.Add(new EstimateRowModel
                {
                    SNo = "",
                    ItemOfWork = "   -> [No Kitchen slabs or stairs found for Item 24]",
                    NosOfFlats = "-",
                    NosOfInstance = "0",
                    Length = "-",
                    Width = "-",
                    HeightDepth = "-",
                    Qty = "0.00",
                    Unit = "-",
                    Remarks = "No elements detected."
                });
            }

            return rows;
        }

        private double GetFloorArea(Floor floor)
        {
            Parameter areaParam = floor.get_Parameter(BuiltInParameter.HOST_AREA_COMPUTED) ?? floor.LookupParameter("Area");
            if (areaParam != null && areaParam.HasValue)
            {
                return UnitUtils.ConvertFromInternalUnits(areaParam.AsDouble(), UnitTypeId.SquareMeters);
            }
            return 2.0; // Default fallback for small counter slab
        }

        private double GetStairAreaParameter(Element stair)
        {
            // Check common parameter names for stair surface area
            Parameter areaParam = stair.LookupParameter("Actual Total Surface Area") ??
                                  stair.LookupParameter("Area") ??
                                  stair.LookupParameter("Surface Area");
            if (areaParam != null && areaParam.HasValue)
            {
                return UnitUtils.ConvertFromInternalUnits(areaParam.AsDouble(), UnitTypeId.SquareMeters);
            }
            return 0.0;
        }
    }
}