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

namespace RevitEstimate.Estimation
{
    public static class EstimateEngine
    {
        public static List<EstimateRowModel> GenerateEstimateReport(Document doc, ProjectLevels levels = null)
        {
            var finalRows = new List<EstimateRowModel>();
            var masterItems = GetMasterScheduleItems();

            var collector = new FilteredElementCollector(doc)
                .WhereElementIsNotElementType()
                .Where(e => e.Category != null)
                .ToList();

            foreach (var masterItem in masterItems)
            {
                int itemNo = masterItem.Key;

                // Add Master Item Header Row
                finalRows.Add(new EstimateRowModel
                {
                    SNo = itemNo.ToString(),
                    ItemOfWork = masterItem.Value,
                    NosOfFlats = "",
                    NosOfInstance = "",
                    Length = "",
                    Width = "",
                    HeightDepth = "",
                    Qty = "",
                    Unit = "",
                    Remarks = "--- Master Schedule Item ---"
                });

                double totalItemQty = 0;
                List<EstimateRowModel> itemRows = new List<EstimateRowModel>();
                IItemCalculator calculator = null;

                // Routing to respective Calculator based on Item Number (1 to 57)
                switch (itemNo)
                {
                    case 1: calculator = new Item01Calculator(levels); break;
                    case 2: calculator = new Item02Calculator(levels); break;
                    case 3: calculator = new Item03Calculator(levels); break;
                    case 4: calculator = new Item04Calculator(levels); break;
                    case 5: calculator = new Item05Calculator(levels); break;
                    case 6: calculator = new Item06Calculator(levels); break;
                    case 7: calculator = new Item07Calculator(levels); break;
                    case 8: calculator = new Item08Calculator(levels); break;
                    case 9: calculator = new Item09Calculator(levels); break;
                    case 10: calculator = new Item10Calculator(levels); break;
                    case 11: calculator = new Item11Calculator(levels); break;
                    case 12: calculator = new Item12Calculator(levels); break;
                    case 13: calculator = new Item13Calculator(levels); break;
                    case 14: calculator = new Item14Calculator(levels); break;
                    case 15: calculator = new Item15Calculator(levels); break;
                    case 16: calculator = new Item16Calculator(levels); break;
                    case 17: calculator = new Item17Calculator(levels); break;
                    case 18: calculator = new Item18Calculator(levels); break;
                    case 19: calculator = new Item19Calculator(levels); break;
                    case 20: calculator = new Item20Calculator(levels); break;
                    case 21: calculator = new Item21Calculator(levels); break;
                    case 22: calculator = new Item22Calculator(levels); break;
                    case 23: calculator = new Item23Calculator(levels); break;
                    case 24: calculator = new Item24Calculator(levels); break;
                    case 25: calculator = new Item25Calculator(levels); break;
                    case 26: calculator = new Item26Calculator(levels); break;
                    case 27: calculator = new Item27Calculator(levels); break;
                    case 28: calculator = new Item28Calculator(levels); break;
                    case 29: calculator = new Item29Calculator(levels); break;
                    case 30: calculator = new Item30Calculator(levels); break;
                    case 31: calculator = new Item31Calculator(levels); break;
                    case 32: calculator = new Item32Calculator(levels); break;
                    case 33: calculator = new Item33Calculator(levels); break;
                    case 34: calculator = new Item34Calculator(levels); break;
                    case 35: calculator = new Item35Calculator(levels); break;
                    case 36: calculator = new Item36Calculator(levels); break;
                    case 37: calculator = new Item37Calculator(levels); break;
                    case 38: calculator = new Item38Calculator(levels); break;
                    case 39: calculator = new Item39Calculator(levels); break;
                    case 40: calculator = new Item40Calculator(levels); break;
                    case 41: calculator = new Item41Calculator(levels); break;
                    case 42: calculator = new Item42Calculator(levels); break;
                    case 43: calculator = new Item43Calculator(levels); break;
                    case 44: calculator = new Item44Calculator(levels); break;
                    case 45: calculator = new Item45Calculator(levels); break;
                    case 46: calculator = new Item46Calculator(levels); break;
                    case 47: calculator = new Item47Calculator(levels); break;
                    case 48: calculator = new Item48Calculator(levels); break;
                    case 49: calculator = new Item49Calculator(levels); break;
                    case 50: calculator = new Item50Calculator(levels); break;
                    case 51: calculator = new Item51Calculator(levels); break;
                    case 52: calculator = new Item52Calculator(levels); break;
                    case 53: calculator = new Item53Calculator(levels); break;
                    case 54: calculator = new Item54Calculator(levels); break;
                    case 55: calculator = new Item55Calculator(levels); break;
                    case 56: calculator = new Item56Calculator(levels); break;
                    case 57: calculator = new Item57Calculator(levels); break;
                    default:
                        calculator = null;
                        break;
                }

                if (calculator != null)
                {
                    itemRows = calculator.Calculate(collector, out totalItemQty);
                }
                else
                {
                    itemRows.Add(new EstimateRowModel
                    {
                        SNo = "",
                        ItemOfWork = "    -> [Awaiting specific calculator file implementation]",
                        NosOfFlats = "-",
                        NosOfInstance = "0",
                        Length = "-",
                        Width = "-",
                        HeightDepth = "-",
                        Qty = "0.00",
                        Unit = "-",
                        Remarks = "Pending implementation."
                    });
                    totalItemQty = 0;
                }

                finalRows.AddRange(itemRows);

                // ==========================================
                // ACCURATE DYNAMIC UNIT SELECTION FOR ITEMS 1-57
                // ==========================================
                string itemUnit = "Cum"; // Default fallback

                if (itemNo == 1 || itemNo == 2)
                {
                    itemUnit = "Cum"; // Excavation / Earthwork
                }
                else if (itemNo == 3 || itemNo == 4 || itemNo == 14 || itemNo == 17)
                {
                    itemUnit = "Cum"; // Concrete & DPC
                }
                else if ((itemNo >= 5 && itemNo <= 7) || (itemNo >= 47 && itemNo <= 50) || itemNo == 55)
                {
                    itemUnit = "Sqm"; // Centering & Shuttering
                }
                else if (itemNo == 8 || itemNo == 18)
                {
                    itemUnit = "Cum"; // Brick work in foundation/superstructure
                }
                else if (itemNo == 9 || itemNo == 22 || itemNo == 23)
                {
                    itemUnit = "Sqm"; // Plastering
                }
                else if (itemNo == 10 || itemNo == 12 || itemNo == 13)
                {
                    itemUnit = "Cum"; // Filling / Anti-termite treatment basis
                }
                else if (itemNo == 11)
                {
                    itemUnit = "Sqm"; // Anti-termite area treatment
                }
                else if (itemNo == 15)
                {
                    itemUnit = "Sqm"; // Bitumen coat on DPC
                }
                else if (itemNo == 16 || itemNo == 21)
                {
                    itemUnit = "Kg"; // Steel Reinforcement
                }
                else if (itemNo == 19)
                {
                    itemUnit = "Sqm"; // Half brick masonry
                }
                else if (itemNo == 20)
                {
                    itemUnit = "Rm"; // M.S. bars extra in half brick
                }
                else if (itemNo >= 24 && itemNo <= 30)
                {
                    itemUnit = "Sqm"; // Flooring, Kota stone, Tiles, Apron
                }
                else if (itemNo == 31)
                {
                    itemUnit = "Cum"; // Wood work frames
                }
                else if (itemNo == 32 || itemNo == 39)
                {
                    itemUnit = "Sqm"; // Door shutters / Glazing
                }
                else if (itemNo >= 33 && itemNo <= 43)
                {
                    itemUnit = "Nos"; // Hardware fittings (Hold fast, tower bolts, handles, knobs, stoppers)
                }
                else if (itemNo == 44 || itemNo == 45 || itemNo == 46)
                {
                    itemUnit = "Sqm"; // Putty, Exterior Paint, Grills
                }
                else if (itemNo == 51)
                {
                    itemUnit = "Rm"; // SS Railing
                }
                else if (itemNo == 52 || itemNo == 53)
                {
                    itemUnit = "Sqm"; // Waterproofing (Terrace & Wet areas)
                }
                else if (itemNo == 54)
                {
                    itemUnit = "Cum"; // RCC Stairs
                }
                else if (itemNo == 56)
                {
                    itemUnit = "Sqm"; // CC Coping
                }
                else if (itemNo == 57)
                {
                    itemUnit = "Sqm"; // Enamel Paint on grills/frames
                }

                // Add Total Quantity Summary Row for the Item
                finalRows.Add(new EstimateRowModel
                {
                    SNo = "",
                    ItemOfWork = $"** TOTAL QUANTITY FOR ITEM {itemNo} **",
                    NosOfFlats = "",
                    NosOfInstance = "",
                    Length = "",
                    Width = "",
                    HeightDepth = "",
                    Qty = totalItemQty.ToString("F2"),
                    Unit = itemUnit,
                    Remarks = $"Summary total for Item {itemNo}"
                });
            }

            // === Apply Smart Naming (Replaces IDs with Comment -> Mark -> Name -> ID) ===
            ApplySmartNaming(doc, finalRows);

            return finalRows;
        }

        private static void ApplySmartNaming(Document doc, List<EstimateRowModel> rows)
        {
            var regex = new Regex(@"\[ID:\s*(-?\d+)\]");

            foreach (var row in rows)
            {
                if (string.IsNullOrEmpty(row.ItemOfWork)) continue;

                var match = regex.Match(row.ItemOfWork);
                if (match.Success)
                {
                    if (long.TryParse(match.Groups[1].Value, out long idVal))
                    {
                        // ==========================================
                        // VERSION COMPATIBILITY FIX: ElementId (int vs long)
                        // ==========================================
#if REVIT2025
                        ElementId eId = new ElementId(idVal);
#else
                        ElementId eId = new ElementId((int)idVal);
#endif

                        Element elem = doc.GetElement(eId);

                        if (elem != null)
                        {
                            string replacementText = null;

                            // 1. Pehle COMMENT check karo
                            Parameter commentParam = elem.LookupParameter("Comments");
                            if (commentParam != null && commentParam.HasValue && !string.IsNullOrWhiteSpace(commentParam.AsString()))
                            {
                                replacementText = $"[{commentParam.AsString()}]";
                            }
                            else
                            {
                                // 2. Phir MARK check karo
                                Parameter markParam = elem.LookupParameter("Mark") ?? elem.LookupParameter("Member Mark");
                                if (markParam != null && markParam.HasValue && !string.IsNullOrWhiteSpace(markParam.AsString()))
                                {
                                    replacementText = $"({markParam.AsString()})";
                                }
                                else
                                {
                                    // 3. Phir NAME check karo
                                    if (!string.IsNullOrWhiteSpace(elem.Name))
                                    {
                                        replacementText = $"{{{elem.Name}}}";
                                    }
                                    else
                                    {
                                        // 4. Agar kuch na mile toh ID hi rehne do
                                        replacementText = match.Value;
                                    }
                                }
                            }

                            if (replacementText != null)
                            {
                                row.ItemOfWork = row.ItemOfWork.Replace(match.Value, replacementText);
                            }
                        }
                    }
                }
            }
        }

        public static Dictionary<int, string> GetMasterScheduleItems()
        {
            return new Dictionary<int, string>()
            {
                { 1, "Excavation in foundation in ordinary soil (loam clay, or sand) including lift up to 1.5 meter and lead up to 30 m..." },
                { 2, "Excavating, supplying and filling of local earth (including royalty) by mechanical transport upto a lead of 5km..." },
                { 3, "Providing and laying in position cement concrete of specified grade excluding the cost of centering and shuttering - All work up to plinth level : 1:4:8" },
                { 4, "Providing and laying in position specified grade of reinforced cement concrete, excluding centering, shuttering - M20 RCC" },
                { 5, "Centering and shuttering including strutting, propping etc. and removal of form for : Foundation" },
                { 6, "Centering and shuttering including strutting, propping etc. and removal of form for : Column" },
                { 7, "Centering and shuttering including strutting, propping etc. and removal of form for : Plinth beam" },
                { 8, "Brick work with common burnt clay F.P.S. bricks in foundation and plinth in: Cement mortar 1:6" },
                { 9, "15 mm cement plaster on rough side of single or half brick wall of mix: 1:4" },
                { 10, "Supplying and filling in plinth with sand under floors, including watering, ramming, consolidating and dressing complete." },
                { 11, "Diluting and injecting chemical emulsion for PRE-CONSTRUCTIONAL anti-termite treatment" },
                { 12, "Treatment of soil under floors using chemical emulsion @ one litre per hole, 300 mm apart including drilling 12 mm holes" },
                { 13, "Treatment of masonry using chemical emulsion @ one litre per hole at 300 mm interval including drilling holes at 45 degree" },
                { 14, "Providing and laying damp-proof course 40mm thick with cement concrete 1:2:4" },
                { 15, "Providing & applying a coat of residual petroleum bitumen of grade of VG-10 on damp proof course" },
                { 16, "Steel reinforcement for R.C.C. work including straightening, cutting, bending, placing in position and binding upto plinth level (Fe-500D)" },
                { 17, "Providing and laying in position specified grade of reinforced cement concrete - All work up to plinth level : 1:1.5:3 (M20 RCC)" },
                { 18, "Brick work with common burnt clay F.P.S. bricks in superstructure above plinth level up to floor V level in all shapes" },
                { 19, "Half brick masonry with common burnt clay F.P.S. bricks in Super structure in : cement mortar 1:4 above floor V level" },
                { 20, "Extra for providing and placing in position 2 Nos 6mm dia. M.S. bars at every third course of half brick masonry." },
                { 21, "Steel reinforcement for R.C.C. work including straightening, cutting, bending above plinth level (Fe-500D)" },
                { 22, "15 mm cement plaster on rough side of single or half brick wall of mix: 1:6" },
                { 23, "12 mm cement plaster of mix : 1:6" },
                { 24, "Providing and fixing 18 mm thick (Granite) gang saw cut, mirror polished, machine cut for kitchen platforms, vanity counters" },
                { 25, "Kota stone slab flooring over 20 mm (average) thick base laid over and jointed with grey cement slurry : 25 mm thick" },
                { 26, "Kota stone slabs 20 mm thick in risers of steps, skirting, dado and pillars laid on 12 mm cement mortar 1:3" },
                { 27, "Providing and laying Vitrified tiles in different sizes with water absorption less than 0.08% (600x600 mm)" },
                { 28, "Providing and fixing 1st quality ceramic glazed floor tiles conforming to IS:15622 in skirting, risers and dados" },
                { 29, "Providing and fixing 1st quality ceramic glazed Wall tiles conforming to IS:15622 in skirting, risers and dados" },
                { 30, "62 mm thick cement concrete flooring with concrete hardener topping (At Apron)" },
                { 31, "Providing and fixing wood work in frames of doors, windows, clerestory windows and other frames..." },
                { 32, "Providing and fixing ISI marked flush door shutters conforming to IS:2202 (Part I) decorative type..." },
                { 33, "Hold Fast" },
                { 34, "M.S. Tower Bolts" },
                { 35, "Handle" },
                { 36, "Door Knob and handle (belan)" },
                { 37, "Door Stopper" },
                { 38, "Hold fast lugs / dash fasteners (Included in Item 31)" },
                { 39, "Providing and fixing glazing in fire resistant door shutters, fixed panels & partitions etc..." },
                { 40, "Hold Fast (Window)" },
                { 41, "M.S. Tower Bolts (Window)" },
                { 42, "Handle (Window)" },
                { 43, "Door Knob and handle (Window)" },
                { 44, "Providing and applying white cement based putty..." },
                { 45, "Finishing walls with Premium Acrylic Smooth exterior paint with Silicone additives (For Outer surface - New work)" },
                { 46, "Providing and fixing M.S. grills of required pattern in frames of windows with M.S. Flats" },
                { 47, "Centering and shuttering for Columns, Pillars, Piers, Abutments and Posts." },
                { 48, "Centering and shuttering for Suspended floors, roofs, landings and balconies." },
                { 49, "Centering and shuttering for Lintels, beams, plinth beams and cantilevers." },
                { 50, "Centering and shuttering for other structural components." },
                { 51, "Providing and fixing stainless steel (Grade 304) railing made of Hollow tubes, channels, plates" },
                { 52, "Providing and laying integral cement based water proofing treatment including brick bat coba on terrace" },
                { 53, "Providing and applying waterproofing treatment to toilet, bathroom, balcony and sunken slabs" },
                { 54, "Providing and laying reinforced cement concrete in stairs, landings and stair components" },
                { 55, "Centering and shuttering for stairs, landings, waist slabs and stair components" },
                { 56, "Providing and laying cement concrete coping over parapet wall with drip course" },
                { 57, "Providing and applying synthetic enamel paint on steel frames, grills, doors and windows" }
            };
        }
    }
}