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

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

        public Item32Calculator(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 });
            }

            // ==========================================
            // COLLECT ONLY DOORS (Exclude Windows)
            // ==========================================
            var doors = collector
                .Where(e => e is FamilyInstance && e.Category != null &&
                           e.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Doors)
                .Cast<FamilyInstance>().ToList();

            foreach (var door in doors)
            {
                BoundingBoxXYZ box = door.get_BoundingBox(null);
                if (box == null) continue;

                double doorZ = UnitUtils.ConvertFromInternalUnits((box.Min.Z + box.Max.Z) / 2.0, UnitTypeId.Meters);
                var floor = activeFloors.FirstOrDefault(f => doorZ >= (f.BottomZ - 0.5) && doorZ <= (f.TopZ + 0.5)) ?? activeFloors.First();

                // Get Width and Height of Door Shutter
                double width = GetDimensionFromTypeOrInstance(door, "Width");
                if (width == 0) width = GetDimensionFromTypeOrInstance(door, "Rough Width");
                if (width == 0) width = 1.0;

                double height = GetDimensionFromTypeOrInstance(door, "Height");
                if (height == 0) height = GetDimensionFromTypeOrInstance(door, "Rough Height");
                if (height == 0) height = 2.1;

                // Area = Width x Height (Sqm)
                double shutterArea = width * height;
                totalQty += shutterArea;

                rows.Add(new EstimateRowModel
                {
                    SNo = "",
                    ItemOfWork = $"   -> 35mm Flush Door Shutter ({floor.Name}): {door.Name} [ID: {door.Id}]",
                    NosOfFlats = "1",
                    NosOfInstance = "1",
                    Length = width.ToString("F2"),
                    Width = "",                  // Blank for Sqm format
                    HeightDepth = height.ToString("F2"),
                    Qty = shutterArea.ToString("F2"),
                    Unit = "Sqm",
                    Remarks = $"35mm thick decorative flush door shutter area ({width:F2}m x {height:F2}m) with stainless steel hinges."
                });
            }

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

            return rows;
        }

        private double GetDimensionFromTypeOrInstance(FamilyInstance inst, string paramName)
        {
            if (inst.Symbol != null) { Parameter typeParam = inst.Symbol.LookupParameter(paramName); if (typeParam != null && typeParam.HasValue) return UnitUtils.ConvertFromInternalUnits(typeParam.AsDouble(), UnitTypeId.Meters); }
            Parameter instParam = inst.LookupParameter(paramName);
            if (instParam != null && instParam.HasValue) return UnitUtils.ConvertFromInternalUnits(instParam.AsDouble(), UnitTypeId.Meters);
            return 0;
        }
    }
}