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

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

        public Item47Calculator(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 double Height => Math.Abs(TopZ - BottomZ);
        }

        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 (Superstructure)
            // ==========================================
            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 });
            }

            // ==========================================
            // COLLECT COLUMNS (Superstructure > TopOfPlinth)
            // ==========================================
            var columns = collector
                .Where(e => e.Category != null &&
                           (e.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Columns ||
                            e.Category.Id.IntegerValue == (int)BuiltInCategory.OST_StructuralColumns))
                .ToList();

            foreach (var col in columns)
            {
                BoundingBoxXYZ box = col.get_BoundingBox(null);
                if (box == null) continue;

                double colBotZ = UnitUtils.ConvertFromInternalUnits(box.Min.Z, UnitTypeId.Meters);
                double colTopZ = UnitUtils.ConvertFromInternalUnits(box.Max.Z, UnitTypeId.Meters);

                // Ensure it is in superstructure (above plinth level)
                if (colTopZ <= _levels.TopOfPlinth) continue;

                foreach (var floor in activeFloors)
                {
                    double overlapBot = Math.Max(colBotZ, floor.BottomZ);
                    double overlapTop = Math.Min(colTopZ, floor.TopZ);
                    double overlapHeight = overlapTop - overlapBot;

                    if (overlapHeight > 0.05)
                    {
                        // Extract cross-section dimensions (Width & Depth)
                        double w = 0.3; // Default fallback width
                        double thk = 0.3; // Default fallback depth

                        Parameter bParam = col.LookupParameter("B") ?? col.LookupParameter("Width");
                        Parameter dParam = col.LookupParameter("D") ?? col.LookupParameter("Depth");

                        if (bParam != null && bParam.HasValue)
                            w = UnitUtils.ConvertFromInternalUnits(bParam.AsDouble(), UnitTypeId.Meters);
                        if (dParam != null && dParam.HasValue)
                            thk = UnitUtils.ConvertFromInternalUnits(dParam.AsDouble(), UnitTypeId.Meters);

                        // Shuttering Perimeter = 2 * (Width + Depth)
                        double perimeter = 2.0 * (w + thk);

                        // Shuttering Area = Perimeter * Height (for this floor segment)
                        double qty = perimeter * overlapHeight;
                        totalQty += qty;

                        rows.Add(new EstimateRowModel
                        {
                            SNo = "",
                            ItemOfWork = $"   -> Superstructure Column Shuttering ({floor.Name}): {col.Name} [ID: {col.Id}]",
                            NosOfFlats = "1",
                            NosOfInstance = "1",
                            Length = perimeter.ToString("F2"),      // Perimeter (2 x (W + D))
                            Width = "",                               // Blank for Sqm format
                            HeightDepth = overlapHeight.ToString("F2"), // Floor segment height
                            Qty = qty.ToString("F2"),
                            Unit = "Sqm",
                            Remarks = $"Superstructure column formwork in {floor.Name} (Perimeter={perimeter:F2}m x H={overlapHeight:F2}m)."
                        });
                    }
                }
            }

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

            return rows;
        }
    }
}