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

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

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

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

            var stairs = collector
                .Where(e => e.Category != null && e.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Stairs)
                .ToList();

            if (stairs.Count == 0)
            {
                rows.Add(new EstimateRowModel { SNo = "", ItemOfWork = "   -> [No Stairs found]", Qty = "0.00", Unit = "Sqm" });
                return rows;
            }

            foreach (var stair in stairs)
            {
                string stairName = stair.Name;
                ElementId stairId = stair.Id;

                int actualRisers = GetParameterInt(stair, "Actual Risers") > 0 ? GetParameterInt(stair, "Actual Risers") : 15;
                int actualTreads = GetParameterInt(stair, "Actual Treads") > 0 ? GetParameterInt(stair, "Actual Treads") : 14;
                double riserHeight = GetParameterDouble(stair, "Actual Riser Height") > 0 ? GetParameterDouble(stair, "Actual Riser Height") : 0.15;
                double treadDepth = GetParameterDouble(stair, "Actual Tread Depth") > 0 ? GetParameterDouble(stair, "Actual Tread Depth") : 0.25;
                double stairWidth = GetParameterDouble(stair, "Width") > 0 ? GetParameterDouble(stair, "Width") : 1.20;

                double totalGoing = actualTreads * treadDepth;
                double totalRise = actualRisers * riserHeight;
                double slantLength = Math.Sqrt((totalGoing * totalGoing) + (totalRise * totalRise));

                // 1. Waist Slab Soffit
                double qtyWaistFormwork = slantLength * stairWidth;
                totalQty += qtyWaistFormwork;

                rows.Add(new EstimateRowModel
                {
                    SNo = "",
                    ItemOfWork = $"   -> Waist Slab Soffit Shuttering for Stair: {stairName} [ID: {stairId}]",
                    NosOfFlats = "1",
                    NosOfInstance = "1",
                    Length = slantLength.ToString("F2"),
                    Width = stairWidth.ToString("F2"),
                    HeightDepth = "",
                    Qty = qtyWaistFormwork.ToString("F2"),
                    Unit = "Sqm",
                    Remarks = $"Waist slab bottom shuttering (Slant L={slantLength:F2}m x W={stairWidth:F2}m)."
                });

                // 2. Riser Faces
                double qtyRiserFormwork = actualRisers * riserHeight * stairWidth;
                totalQty += qtyRiserFormwork;

                rows.Add(new EstimateRowModel
                {
                    SNo = "",
                    ItemOfWork = $"   -> Riser Steps Face Shuttering for Stair: {stairName} [ID: {stairId}]",
                    NosOfFlats = "1",
                    NosOfInstance = actualRisers.ToString(),
                    Length = stairWidth.ToString("F2"),
                    Width = "",
                    HeightDepth = riserHeight.ToString("F2"),
                    Qty = qtyRiserFormwork.ToString("F2"),
                    Unit = "Sqm",
                    Remarks = $"Riser face formwork ({actualRisers} risers x Height={riserHeight}m x Width={stairWidth}m)."
                });

                // 3. Landing Soffit
                double landingArea = GetLandingArea(stair);
                double qtyLandingFormwork = landingArea;
                totalQty += qtyLandingFormwork;

                rows.Add(new EstimateRowModel
                {
                    SNo = "",
                    ItemOfWork = $"   -> Landing Soffit Shuttering for Stair: {stairName} [ID: {stairId}]",
                    NosOfFlats = "1",
                    NosOfInstance = "1",
                    Length = landingArea.ToString("F2"),
                    Width = "",
                    HeightDepth = "",
                    Qty = qtyLandingFormwork.ToString("F2"),
                    Unit = "Sqm",
                    Remarks = $"Landing soffit formwork area ({landingArea:F2} Sqm)."
                });
            }

            return rows;
        }

        private int GetParameterInt(Element elem, string paramName)
        {
            Parameter param = elem.LookupParameter(paramName);
            if (param != null && param.HasValue) return param.AsInteger();
            return 0;
        }

        private double GetParameterDouble(Element elem, string paramName)
        {
            Parameter param = elem.LookupParameter(paramName);
            if (param != null && param.HasValue)
            {
                return UnitUtils.ConvertFromInternalUnits(param.AsDouble(), UnitTypeId.Meters);
            }
            return 0.0;
        }

        private double GetLandingArea(Element stair)
        {
            try
            {
                BoundingBoxXYZ box = stair.get_BoundingBox(null);
                if (box != null)
                {
                    double width = UnitUtils.ConvertFromInternalUnits(box.Max.X - box.Min.X, UnitTypeId.Meters);
                    double length = UnitUtils.ConvertFromInternalUnits(box.Max.Y - box.Min.Y, UnitTypeId.Meters);
                    if (width > 0 && length > 0)
                    {
                        return Math.Round(width * length * 0.3, 2);
                    }
                }
            }
            catch { }
            return 1.5;
        }
    }
}