<!DOCTYPE html>
<htcontenteditablehead>
<meta charset="UTF-8">
<title>Rent History Analyzer v1.0</title>
<script src="https://unpkg.com/tesseract.js@v2.1.0/dist/tesseract.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/ScrollTrigger.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Poppins:wght@300;500;700&family=Great+Vibes&family=Montserrat:wght@300;400;600&display=swap" rel="stylesheet">
<style>
*{box-sizing:border-box;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;margin:0;padding:0}
html,body{width:100%;height:100%;overflow-x:hidden;scroll-behavior:smooth}
body{background:linear-gradient(135deg,#152535 0%,#3A4F6C 40%,#9EC0EE 100%);font-family:'Poppins',sans-serif;color:#EDEEF2;display:flex;flex-direction:column;position:relative;justify-content:flex-start;align-items:center;overflow-y:auto}
::selection{background:#9EC0EE;color:#152535}
.floatingDeco{position:absolute;border-radius:50%;background:radial-gradient(circle at center,rgba(212,231,248,0.2) 0%,rgba(158,192,238,0.1) 70%,transparent 100%);animation:floatUpDown 6s ease-in-out infinite alternate;pointer-events:none;z-index:1}
.floatingDeco.deco1{top:20%;left:10%;width:300px;height:300px;animation-delay:.5s}
.floatingDeco.deco2{top:50%;right:15%;width:250px;height:250px;animation-delay:1s}
.floatingDeco.deco3{top:70%;left:30%;width:200px;height:200px;animation-delay:1.5s}
@keyframes floatUpDown{0%{transform:translateY(0);opacity:.7}100%{transform:translateY(-30px);opacity:1}}
#topBar{width:100%;background:rgba(21,37,53,.95);display:flex;align-items:center;justify-content:space-between;padding:10px 5%;position:fixed;top:0;left:0;z-index:9999;box-shadow:0 2px 10px rgba(0,0,0,.7)}
#topBar img{height:50px;object-fit:contain;cursor:pointer;transition:transform .3s ease}
#topBar img:hover{transform:scale(1.05) rotate(-3deg)}
#pageTitle{font-family:'Playfair Display',serif;font-size:22px;margin:0;letter-spacing:1px;font-weight:700;text-shadow:1px 1px 3px rgba(0,0,0,.4)}
button{background:#3A4F6C;color:#EDEEF2;padding:14px 28px;border:none;border-radius:8px;cursor:pointer;font-family:'Montserrat',sans-serif;font-weight:600;text-transform:uppercase;font-size:14px;letter-spacing:1px;transition:all .3s ease,box-shadow .3s ease;margin-top:20px;position:relative;z-index:10}
button::before{content:'';position:absolute;top:-5px;left:-5px;right:-5px;bottom:-5px;border-radius:12px;background:linear-gradient(45deg,#9EC0EE,#3A4F6C);opacity:0;z-index:-1;transition:opacity .3s ease}
button:hover{background:#152535;transform:scale(1.05);box-shadow:0 8px 20px rgba(0,0,0,.4)}
button:hover::before{opacity:.3}
.stepContainer{width:90%;max-width:1200px;background:#EDEEF2;margin-top:80px;margin-bottom:50px;padding:40px;border-radius:20px;box-shadow:0 20px 40px rgba(0,0,0,.3);position:relative;display:none;flex-direction:column;align-items:center;color:#152535;z-index:2}
.stepContainer.show{display:flex}
.stepContainer::before{content:'';position:absolute;top:-10%;left:-10%;height:120%;width:120%;background:linear-gradient(140deg,rgba(158,192,238,.15) 0%,rgba(237,238,242,.1) 50%,transparent 100%);border-radius:30px;transform:rotate(-2deg);z-index:-1}
.stepContainer h2{font-family:'Playfair Display',serif;text-transform:uppercase;letter-spacing:1px;font-size:26px;margin-bottom:10px;color:#152535;position:relative;opacity:0}
.stepContainer h2::after{content:'';position:absolute;left:50%;transform:translateX(-50%);bottom:-6px;width:100px;height:3px;background:linear-gradient(90deg,#3A4F6C,#9EC0EE)}
.show h2{animation:fadeInUp 1.2s ease forwards}
@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}}
#step1 h2{margin-bottom:30px}
#imageUpload{margin-bottom:20px;font-size:14px;cursor:pointer;background:#D4E7F8;padding:10px;border-radius:8px;color:#152535;border:2px dashed #3A4F6C;outline:none;transition:border-color .3s ease}
#imageUpload:hover{border-color:#9EC0EE}
.spinnerContainer{position:relative;margin-top:20px;display:flex;flex-direction:column;justify-content:center;align-items:center;opacity:0}
.show .spinnerContainer{animation:fadeIn 1.5s forwards ease}
@keyframes fadeIn{0%{opacity:0;transform:translateY(30px)}100%{opacity:1;transform:translateY(0)}}
#loading{color:#152535;font-size:18px;font-weight:700;margin-top:20px;text-align:center;display:none}
.processingSpinner{width:80px;height:80px;border:8px solid #9EC0EE;border-top:8px solid #152535;border-radius:50%;animation:spin 1s linear infinite}
@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
#headerData{margin-top:20px;width:100%;display:none;background:#D4E7F8;border-radius:8px;padding:20px;box-shadow:0 10px 20px rgba(0,0,0,.1);position:relative}
#headerData h3{font-family:'Playfair Display',serif;letter-spacing:1px;color:#152535;font-size:20px;margin:0 0 15px;padding-bottom:5px;border-bottom:2px solid #9EC0EE;position:relative}
#headerData p{margin:6px 0;font-size:16px;line-height:1.4;color:#152535}
#headerData span[contenteditable="true"]{padding:0 4px;border-bottom:1px dashed #3A4F6C;cursor:text;transition:background .2s ease,color .2s ease}
#headerData span[contenteditable="true"]:hover{background:#FFF8DC}
#headerData.fadeInAnimated{animation:fadeInUp2 1s ease forwards}
@keyframes fadeInUp2{0%{opacity:0;transform:translateY(50px)}100%{opacity:1;transform:translateY(0)}}
#rentTable{width:100%;border-collapse:collapse;margin-top:30px;display:none;box-shadow:0 10px 20px rgba(0,0,0,.15);overflow:hidden;border-radius:8px;background:#EDEEF2;position:relative}
#rentTable.fadeInAnimated{animation:fadeInUp2 1.2s ease forwards}
#rentTable thead{background:#152535}
#rentTable th{color:#EDEEF2;padding:12px;text-transform:uppercase;font-size:14px;letter-spacing:1px;text-align:left;position:relative}
#rentTable th::after{content:'';position:absolute;left:0;bottom:-1px;width:100%;height:2px;background:linear-gradient(90deg,#9EC0EE,#3A4F6C)}
#rentTable td{border-bottom:1px solid #ddd;padding:12px;font-size:14px;vertical-align:middle;position:relative;transition:background-color .2s ease;color:#152535}
#rentTable tr:hover td{background-color:rgba(212,231,248,.3)}
#rentTable td:focus{outline:2px solid #9EC0EE;background-color:#FFF8DC!important}
[contenteditable="true"]:focus{outline:2px solid #9EC0EE}

/* Overcharge Analysis Styles */
#overchargeCheck {
    display: none;
    margin-left: 20px;
    background: #9EC0EE;
    color: #152535;
    padding: 8px 16px;
    border-radius: 4px;
    font-size: 14px;
    transition: all 0.3s ease;
}

#overchargeCheck:hover {
    background: #3A4F6C;
    color: #EDEEF2;
}

.overcharge-analysis {
    margin-top: 40px;
    padding: 20px;
    background: white;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}

.analysis-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 40px;
}

.analysis-spinner {
    width: 50px;
    height: 50px;
    border: 5px solid #f3f3f3;
    border-top: 5px solid #3498db;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

.analysis-results {
    margin-top: 20px;
}

.overcharge-details {
    margin-top: 20px;
    padding: 15px;
    background: #f8f9fa;
    border-radius: 8px;
    border: 1px solid #dee2e6;
}

.overcharge-total {
    font-size: 18px;
    font-weight: bold;
    color: #dc3545;
    margin-bottom: 15px;
}

@media (max-width:768px){body{font-size:18px}#step1,#step2,#step3{padding:20px}.stepContainer{padding:20px;margin-top:70px}#rentTable,#rentTable thead,#rentTable tbody,#rentTable th,#rentTable td,#rentTable tr{display:block}#rentTable tr{margin-bottom:15px}#rentTable td{text-align:right;padding-left:50%;position:relative;border:none;border-bottom:1px solid #ddd;white-space:normal}#rentTable td::before{content:attr(data-label);position:absolute;left:10px;width:calc(50% - 20px);text-align:left;font-weight:bold}#rentTable thead tr{display:none}}
#toggleMoreInfo{background:#9EC0EE;color:#152535;border-radius:8px;font-weight:700;margin-top:100px}
#toggleMoreInfo:hover{background:#3A4F6C;color:#EDEEF2;transform:scale(1.03)}
#moreInfoContainer{width:90%;max-width:1200px;background:rgba(212,231,248,.9);margin-top:20px;padding:20px 30px;border-radius:15px;box-shadow:0 10px 20px rgba(0,0,0,.2);position:relative;display:none;color:#152535;backdrop-filter:blur(6px)}
#moreInfoContainer.expanded{display:block;animation:fadeInExpand .8s forwards}
@keyframes fadeInExpand{0%{opacity:0;transform:translateY(30px)}100%{opacity:1;transform:translateY(0)}}
#moreInfoContainer h2{font-family:'Playfair Display',serif;text-transform:uppercase;margin-bottom:10px;color:#152535;position:relative;font-size:22px}
#moreInfoContainer p{margin:10px 0;line-height:1.6;font-size:16px}
footer{width:100%;text-align:center;padding:20px 0;background:rgba(21,37,53,.9);position:fixed;bottom:0;left:0;color:#EDEEF2;font-family:'Montserrat',sans-serif;font-size:14px;letter-spacing:.5px;box-shadow:0 -2px 10px rgba(0,0,0,.7);z-index:999}
footer a{color:#9EC0EE;text-decoration:none;font-weight:600}
footer a:hover{text-decoration:underline}
</style>
</head>
<body>
<div class="floatingDeco deco1"></div>
<div class="floatingDeco deco2"></div>
<div class="floatingDeco deco3"></div>
<div id="topBar">
    <img src="https://renthistory.org/media/rent-history.webp" alt="RentHistory.org Logo" onclick="window.open('https://renthistory.org','_blank')"/>
    <h1 id="pageTitle">Rent History Analyzer v1.0</h1>
    <button id="overchargeCheck" style="display: none;">Check for Overcharges</button>
</div>
<button id="toggleMoreInfo">More Info / Instructions</button>
<div id="moreInfoContainer">
    <h2>How This Works</h2>
    <p>Upload your clear and unredacted DHCR rent history document. We'll extract the data to show you potential overcharges, rent stabilization issues, and more. Once the table appears, review and confirm your data for accuracy.</p>
</div>
<div id="step1" class="stepContainer show">
    <h2>Upload Your Rent History Document(s)</h2>
    <input type="file" id="imageUpload" accept="image/*" multiple>
    <button onclick="uploadImages()">Upload</button>
</div>
<div id="step2" class="stepContainer">
    <h2>Processing Your Upload</h2>
    <div class="spinnerContainer">
        <div class="processingSpinner"></div>
        <p id="loading">Processing... Please wait.</p>
    </div>
</div>
<div id="step3" class="stepContainer">
    <div id="headerData">
        <h3>Extracted Document Details:</h3>
        <p><strong>Subject Premises:</strong> <span id="subjectPremises" contenteditable="true"></span></p>
        <p><strong>Building ID Number:</strong> <span id="buildingID" contenteditable="true"></span></p>
        <p><strong>Request Date:</strong> <span id="requestDate" contenteditable="true"></span></p>
        <p><strong>Request No.:</strong> <span id="requestNo" contenteditable="true"></span></p>
        <p><strong>Number of Rooms:</strong> <span id="numRooms" contenteditable="true"></span></p>
    </div>
    <h3 style="margin-top:40px;color:#152535;">Extracted Table (click any cell to edit):</h3>
    <table id="rentTable">
        <thead>
            <tr>
                <th>Year</th>
                <th>Apt. Stat</th>
                <th>Filing Date</th>
                <th>Legal Regulated Rent</th>
                <th>Pref. Rent</th>
                <th>Actual Rent Paid</th>
                <th>Reasons Differ./Change</th>
                <th>Lease Began/Ends</th>
                <th>Tenant</th>
                <th>Exempt/Missing</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>
    <button style="margin-top:40px;" onclick="analyzeData()">Analyze</button>
</div>
<div id="overchargeAnalysisContainer" class="stepContainer">
    <h2>Overcharge Analysis</h2>
    <div id="overchargeLoading" class="analysis-loading" style="display: none;">
        <div class="analysis-spinner"></div>
        <p>Analyzing rent history for overcharges...</p>
    </div>
    <div id="overchargeResults" class="analysis-results" style="display: none;">
        <div id="illegalIncreasesSection" class="overcharge-details"></div>
        <div id="hypotheticalRentSection" class="overcharge-details" style="margin-top:20px;"></div>
    </div>
</div>
<footer>Powered by <a href="https://renthistory.org" target="_blank">RentHistory.org</a> | Helping you understand your Rent History, quickly and easily.</footer>
<script>
const rgbGuidelines = {
    "1990-1991": { oneYear: 4.5, twoYear: 7.0 },
    "1991-1992": { oneYear: 4.0, twoYear: 6.5 },
    "1992-1993": { oneYear: 3.0, twoYear: 5.0 },
    "1993-1994": { oneYear: 3.0, twoYear: 5.0 },
    "1994-1995": { oneYear: 2.0, twoYear: 4.0 },
    "1995-1996": { oneYear: 2.0, twoYear: 4.0 },
    "1996-1997": { oneYear: 5.0, twoYear: 7.0 },
    "1997-1998": { oneYear: 2.0, twoYear: 4.0 },
    "1998-1999": { oneYear: 2.0, twoYear: 4.0 },
    "1999-2000": { oneYear: 2.0, twoYear: 4.0 },
    "2000-2001": { oneYear: 4.0, twoYear: 6.0 },
    "2001-2002": { oneYear: 4.0, twoYear: 6.0 },
    "2002-2003": { oneYear: 2.0, twoYear: 4.0 },
    "2003-2004": { oneYear: 4.5, twoYear: 7.5 },
    "2004-2005": { oneYear: 3.5, twoYear: 6.5 },
    "2005-2006": { oneYear: 2.75, twoYear: 5.5 },
    "2006-2007": { oneYear: 4.25, twoYear: 7.25 },
    "2007-2008": { oneYear: 3.0, twoYear: 5.75 },
    "2008-2009": { oneYear: 4.5, twoYear: 8.5 },
    "2009-2010": { oneYear: 3.0, twoYear: 6.0 },
    "2010-2011": { oneYear: 2.25, twoYear: 4.5 },
    "2011-2012": { oneYear: 3.75, twoYear: 7.25 },
    "2012-2013": { oneYear: 2.0, twoYear: 4.0 },
    "2013-2014": { oneYear: 4.0, twoYear: 7.75 },
    "2014-2015": { oneYear: 1.0, twoYear: 2.75 },
    "2015-2016": { oneYear: 0.0, twoYear: 2.0 },
    "2016-2017": { oneYear: 0.0, twoYear: 2.0 },
    "2017-2018": { oneYear: 1.25, twoYear: 2.0 },
    "2018-2019": { oneYear: 1.5, twoYear: 2.5 },
    "2019-2020": { oneYear: 1.5, twoYear: 2.5 },
    "2020-2021": { oneYear: 0.0, twoYear: 0.0 },
    "2021-2022": { oneYear: 0.0, twoYear: 2.5 },
    "2022-2023": { oneYear: 3.25, twoYear: 5.0 },
    "2023-2024": { oneYear: 3.0, twoYear: 2.75 },
    "2024-2025": { oneYear: 2.75, twoYear: 5.25 }
};

function showStep(step) {
    [1, 2, 3].forEach(n => {
        document.getElementById("step" + n).classList.remove("show");
    });
    let stepElement = document.getElementById("step" + step);
    stepElement.classList.add("show");
    if (step === 2) {
        document.getElementById("loading").style.display = "block";
    } else {
        document.getElementById("loading").style.display = "none";
    }
}

document.getElementById("toggleMoreInfo").addEventListener("click", () => {
    document.getElementById("moreInfoContainer").classList.toggle("expanded");
});

document.getElementById("overchargeCheck").addEventListener("click", () => {
    analyzeOvercharges();
});

showStep(1);

let globalRows = [];
let headerCaptured = false;
let capturedHeaderData = {
    subjectPremises: "",
    buildingID: "",
    requestDate: "",
    requestNo: "",
    numRooms: ""
};

function analyzeOvercharges() {
    document.getElementById("overchargeLoading").style.display = "block";
    document.getElementById("overchargeResults").style.display = "none";
    document.getElementById("overchargeAnalysisContainer").classList.add("show");

    // Gather rent data in chronological order
    const tableRows = document.querySelectorAll("#rentTable tbody tr");
    if (!tableRows.length) {
        document.getElementById("overchargeLoading").style.display = "none";
        document.getElementById("overchargeResults").style.display = "block";
        document.getElementById("illegalIncreasesSection").innerHTML = `
            <div class="overcharge-total">No data available for analysis.</div>
        `;
        document.getElementById("hypotheticalRentSection").innerHTML = `
            <div class="overcharge-total">No data available for analysis.</div>
        `;
        return;
    }

    // Extract row data
    const leaseData = [];
    tableRows.forEach((row) => {
        const cells = row.querySelectorAll("td");
        const yearRaw       = cells[0].innerText.trim();
        const regulatedRent = cells[3].innerText.replace(/[^0-9.-]+/g, "").trim();
        const leasePeriod   = cells[7].innerText.trim();

        let startDate = "";
        let endDate   = "";
        if (leasePeriod.includes("-")) {
            const parts = leasePeriod.split("-").map(p => p.trim());
            startDate = parts[0] || "";
            endDate   = parts[1] || "";
        }

        const yearNum = parseInt(yearRaw, 10);
        const rentNum = parseFloat(regulatedRent);

        leaseData.push({
            year: !isNaN(yearNum) ? yearNum : null,
            startDate: startDate,
            endDate: endDate,
            legalRent: !isNaN(rentNum) ? rentNum : null
        });
    });

    // Sort by year ascending
    leaseData.sort((a, b) => {
        if (a.year === null && b.year === null) return 0;
        if (a.year === null) return 1;
        if (b.year === null) return -1;
        return a.year - b.year;
    });

    // Determine if a lease is 1-year or 2-year based on approximate difference in start/end
    function getLeaseDurationInYears(start, end) {
        // If we can't parse, assume 1 year
        if (!start || !end) return 1;
        const partsStart = start.split("/");
        const partsEnd   = end.split("/");
        if (partsStart.length !== 3 || partsEnd.length !== 3) return 1;

        const monthStart = parseInt(partsStart[0], 10);
        const dayStart   = parseInt(partsStart[1], 10);
        const yearStart  = parseInt(partsStart[2], 10);

        const monthEnd   = parseInt(partsEnd[0], 10);
        const dayEnd     = parseInt(partsEnd[1], 10);
        const yearEnd    = parseInt(partsEnd[2], 10);

        if (isNaN(monthStart) || isNaN(dayStart) || isNaN(yearStart) ||
            isNaN(monthEnd)   || isNaN(dayEnd)   || isNaN(yearEnd)) return 1;

        const dateStart = new Date(yearStart, monthStart - 1, dayStart);
        const dateEnd   = new Date(yearEnd, monthEnd - 1, dayEnd);

        let diffInMonths = (yearEnd - yearStart) * 12 + (monthEnd - monthStart);
        if (dayEnd < dayStart) diffInMonths--;

        if (diffInMonths >= 18) {
            // assume 2-year
            return 2;
        }
        return 1;
    }

    // Lease-to-lease comparison
    const illegalIncreases = [];
    let previousLegalRent = null;
    let previousYear = null;
    let hypotheticalRents = [];

    for (let i = 0; i < leaseData.length; i++) {
        const current = leaseData[i];
        if (current.legalRent === null) {
            hypotheticalRents.push(current.legalRent);
            previousLegalRent = null;
            previousYear = current.year;
            continue;
        }
        if (i === 0) {
            // First lease, just push as is
            hypotheticalRents.push(current.legalRent);
            previousLegalRent = current.legalRent;
            previousYear = current.year;
            continue;
        }

        const duration = getLeaseDurationInYears(current.startDate, current.endDate);
        const yearKey = `${previousYear}-${current.year}`;
        let guideline = rgbGuidelines[yearKey] || null;

        // If we have no guideline, we can't do a direct year-based lookup
        // We simply won't label it as illegal automatically, but we keep a fallback approach
        if (!guideline) {
            hypotheticalRents.push(current.legalRent);
            previousLegalRent = current.legalRent;
            previousYear = current.year;
            continue;
        }

        let allowedIncreasePercent = duration === 2 ? guideline.twoYear : guideline.oneYear;
        let maxAllowedRent = previousLegalRent * (1 + allowedIncreasePercent / 100);
        if (current.legalRent > maxAllowedRent) {
            illegalIncreases.push({
                year: current.year,
                actualRent: current.legalRent,
                allowedRent: maxAllowedRent,
                overcharge: current.legalRent - maxAllowedRent,
                leaseDuration: duration
            });
            hypotheticalRents.push(maxAllowedRent);
            previousLegalRent = maxAllowedRent;
        } else {
            hypotheticalRents.push(current.legalRent);
            previousLegalRent = current.legalRent;
        }
        previousYear = current.year;
    }

    // Build the text for suspected illegal increases
    let illegalText = "";
    if (!illegalIncreases.length) {
        illegalText += `<div class="overcharge-total">No suspected illegal increases were found on a lease-to-lease basis.</div>`;
    } else {
        illegalText += `<div class="overcharge-total">Suspected Illegal Increases Detected:</div>`;
        illegalIncreases.forEach(il => {
            illegalText += `
                <div style="margin-bottom:10px;">
                    <strong>Year:</strong> ${il.year}<br/>
                    <strong>Lease Duration:</strong> ${il.leaseDuration}-year<br/>
                    <strong>Actual Rent:</strong> $${il.actualRent.toFixed(2)}<br/>
                    <strong>Max Allowed (Lease-to-Lease):</strong> $${il.allowedRent.toFixed(2)}<br/>
                    <strong>Difference:</strong> $${il.overcharge.toFixed(2)}<br/>
                </div>
            `;
        });
    }

    // Build the text for hypothetical final rent calculation
    let hypotheticalText = "";
    if (!illegalIncreases.length) {
        hypotheticalText += `<div class="overcharge-total">Since there were no illegal increases, your rent data remains unchanged.</div>`;
    } else {
        const lastIndex = hypotheticalRents.length - 1;
        const finalHypothetical = hypotheticalRents[lastIndex];
        const lastActual = leaseData[leaseData.length - 1].legalRent;
        if (lastActual === null) {
            hypotheticalText += `
                <div class="overcharge-total">Cannot determine final actual rent due to incomplete data.</div>
            `;
        } else {
            const difference = lastActual - finalHypothetical;
            hypotheticalText += `
                <div style="margin-bottom:10px;">
                    <div class="overcharge-total">If no illegal increases had happened...</div>
                    <p><strong>Actual Current Rent:</strong> $${lastActual.toFixed(2)}</p>
                    <p><strong>Hypothetical Current Rent:</strong> $${finalHypothetical.toFixed(2)}</p>
                    <p><strong>Difference:</strong> $${difference.toFixed(2)}</p>
                </div>
            `;
        }
    }

    document.getElementById("illegalIncreasesSection").innerHTML = `
        <h3>Suspected Illegal Increases (Lease-to-Lease)</h3>
        ${illegalText}
        <canvas id="illegalIncreasesChart" width="400" height="200" style="background:#fff; margin-top:20px;"></canvas>
    `;
    document.getElementById("hypotheticalRentSection").innerHTML = `
        <h3>Hypothetical Rent Without Illegal Increases</h3>
        ${hypotheticalText}
        <canvas id="hypotheticalRentChart" width="400" height="200" style="background:#fff; margin-top:20px;"></canvas>
    `;

    // Minimal example of drawing a rudimentary chart on canvas
    function drawSimpleLineChart(canvasId, dataPoints, labelColor) {
        const canvas = document.getElementById(canvasId);
        if (!canvas) return;
        const ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        if (!dataPoints.length) return;

        const padding = 30;
        const chartWidth = canvas.width - padding * 2;
        const chartHeight = canvas.height - padding * 2;
        const maxVal = Math.max(...dataPoints);
        const minVal = Math.min(...dataPoints);

        // Draw axes
        ctx.strokeStyle = "#999";
        ctx.beginPath();
        ctx.moveTo(padding, padding);
        ctx.lineTo(padding, padding + chartHeight);
        ctx.lineTo(padding + chartWidth, padding + chartHeight);
        ctx.stroke();

        // Plot data
        ctx.strokeStyle = labelColor;
        ctx.beginPath();
        dataPoints.forEach((val, i) => {
            const x = padding + (i / (dataPoints.length - 1)) * chartWidth;
            let normalized = 0;
            if (maxVal > minVal) {
                normalized = (val - minVal) / (maxVal - minVal);
            }
            const y = padding + chartHeight - normalized * chartHeight;
            if (i === 0) {
                ctx.moveTo(x, y);
            } else {
                ctx.lineTo(x, y);
            }
        });
        ctx.stroke();
    }

    // Data for charts
    const illegalData = illegalIncreases.map(il => il.overcharge);
    const hypotheticalData = hypotheticalRents.filter(v => v !== null);

    drawSimpleLineChart("illegalIncreasesChart", illegalData, "#dc3545");
    drawSimpleLineChart("hypotheticalRentChart", hypotheticalData, "#28a745");

    document.getElementById("overchargeLoading").style.display = "none";
    document.getElementById("overchargeResults").style.display = "block";
}

function uploadImages() {
    let files = document.getElementById("imageUpload").files;
    if (!files.length) {
        alert("Please select at least one image.");
        return;
    }
    showStep(2);
    processFilesSequentially(Array.from(files))
        .then(() => {
            buildFinalTable();
            showStep(3);
            document.getElementById("overchargeCheck").style.display = "block";
            gsap.from("#headerData", {
                y: 50,
                opacity: 0,
                duration: 1,
                onStart: () => {
                    document.getElementById("headerData").style.display = "block";
                    document.getElementById("headerData").classList.add("fadeInAnimated");
                }
            });
            gsap.from("#rentTable", {
                y: 50,
                opacity: 0,
                duration: 1.2,
                delay: 0.5,
                onStart: () => {
                    document.getElementById("rentTable").style.display = "table";
                    document.getElementById("rentTable").classList.add("fadeInAnimated");
                },
                onComplete: () => {
                    showVerificationPopup();
                }
            });
        })
        .catch(() => {
            alert("An error occurred while processing the images.");
            showStep(1);
        });
}

async function processFilesSequentially(files) {
    for (let file of files) {
        await processSingleFile(file);
    }
}

function processSingleFile(file) {
    return new Promise((resolve, reject) => {
        let reader = new FileReader();
        reader.onload = function(event) {
            let img = new Image();
            img.src = event.target.result;
            img.onload = function() {
                Tesseract.recognize(img, "eng", {
                    logger: m => console.log(m)
                }).then(({ data: { text } }) => {
                    parseAndStoreData(text);
                    resolve();
                }).catch(error => {
                    reject(error);
                });
            };
        };
        reader.readAsDataURL(file);
    });
}

function parseAndStoreData(text) {
    if (!headerCaptured) {
        captureHeaderDetails(text);
    }

    let lines = text.split(/\r?\n/).map(line => line.trim()).filter(line => line);
    let i = 0;

    while (i < lines.length) {
        let line = lines[i];
        if (!line) {
            i++;
            continue;
        }

        if (/^\d{4}/.test(line)) {
            let match = line.match(/^(\d{4})\s+(.*)$/);
            if (match) {
                let year = match[1];
                let rest = match[2].trim();

                if (/reg\s+not\s+found/i.test(rest)) {
                    globalRows.push({
                        year: year,
                        aptStat: "",
                        filingDate: "",
                        regulatedRent: "",
                        prefRent: "",
                        actualRentPaid: "",
                        reasonsChange: "",
                        leaseStart: "",
                        leaseEnd: "",
                        tenantName: "",
                        exemptMissing: "Missing"
                    });
                    i++;
                    continue;
                }

                if (/exempt\s+apartment.*not\s+required/i.test(rest)) {
                    globalRows.push({
                        year: year,
                        aptStat: "",
                        filingDate: "",
                        regulatedRent: "",
                        prefRent: "",
                        actualRentPaid: "",
                        reasonsChange: "",
                        leaseStart: "",
                        leaseEnd: "",
                        tenantName: "",
                        exemptMissing: "Exempt"
                    });
                    i++;
                    continue;
                }

                let rentMatch = line.match(/^(\d{4})\s+([A-Z]{2}(?:-[A-Z])?)\s+(\d{2}\/\d{2}\/\d{4})?\s*(?:_)?\s*(\d+\.\d+)?\s*(\d+\.\d+)?\s*(\d+\.\d+)?\s*(\d{2}\/\d{2}\/\d{4})?/);
                let aptStat = "";
                let filingDate = "";
                let regulatedRent = "";
                let prefRent = "";
                let actualRentPaid = "";
                let leaseStart = "";
                let reasonsChange = "";
                let leaseEnd = "";
                let tenantName = "";
                let exemptMissing = "";

                if (rentMatch) {
                    aptStat = rentMatch[2] || "";
                    filingDate = rentMatch[3] || "";
                    regulatedRent = rentMatch[4] || "";
                    prefRent = rentMatch[5] || "";
                    actualRentPaid = rentMatch[6] || "";
                    leaseStart = rentMatch[7] || "";

                    let nextLine = (lines[i + 1] || "").trim();
                    if (/^TENANT/i.test(nextLine)) {
                        i++;
                        let tenantInfo = nextLine.replace(/^TENANT.*?:/i, "").trim();
                        tenantInfo = tenantInfo.replace(/\btenant\b/gi, "").trim();
                        tenantInfo = tenantInfo.replace(/[~()]/g, "").trim();
                        tenantInfo = tenantInfo.replace(/[|]+/g, "").trim();

                        let reasonMatch = tenantInfo.match(/\b(LEAS\/RNL|VAC\/LEAS)\b/);
                        if (reasonMatch) {
                            reasonsChange = reasonMatch[1];
                            tenantInfo = tenantInfo.replace(reasonMatch[1], "").trim();
                        }

                        let dateMatch = tenantInfo.match(/\b(\d{2}\/\d{2}\/\d{4})\b/);
                        if (dateMatch) {
                            leaseEnd = dateMatch[1];
                            tenantInfo = tenantInfo.replace(dateMatch[1], "").trim();
                        }

                        tenantInfo = tenantInfo.replace(/^[^a-z0-9]+/i, "").replace(/[^a-z0-9]+$/i, "");
                        tenantName = tenantInfo.trim();
                    }

                    if (!reasonsChange) {
                        let reasonMatch = line.match(/\s(LEAS\/RNL|VAC\/LEAS)\s/);
                        if (reasonMatch) {
                            reasonsChange = reasonMatch[1];
                        }
                    }

                    if (!leaseEnd) {
                        let endMatch = line.match(/(\d{2}\/\d{2}\/\d{4})$/);
                        if (endMatch && leaseStart !== endMatch[1]) {
                            leaseEnd = endMatch[1];
                        }
                    }
                }

                globalRows.push({
                    year: year,
                    aptStat: aptStat,
                    filingDate: filingDate,
                    regulatedRent: regulatedRent,
                    prefRent: prefRent,
                    actualRentPaid: actualRentPaid,
                    reasonsChange: reasonsChange,
                    leaseStart: leaseStart,
                    leaseEnd: leaseEnd,
                    tenantName: tenantName,
                    exemptMissing: exemptMissing
                });
            }
        }
        i++;
    }
}

function captureHeaderDetails(text) {
    headerCaptured = true;

    let buildingIdMatch = text.match(/Building\s+Id\s+Number:\s*(\d+)/i);
    if (buildingIdMatch) {
        capturedHeaderData.buildingID = buildingIdMatch[1];
    }

    let requestDateMatch = text.match(/Request\s+Date:\s*(\d{2}\/\d{2}\/\d{4})/i);
    if (requestDateMatch) {
        capturedHeaderData.requestDate = requestDateMatch[1];
    }

    let requestNoMatch = text.match(/Request\s+No.:\s*(\S+)/i);
    if (requestNoMatch) {
        capturedHeaderData.requestNo = requestNoMatch[1];
    }

    let roomsMatch = text.match(/Number\s+of\s+Rooms:\s*(\d+)/i);
    if (roomsMatch) {
        capturedHeaderData.numRooms = roomsMatch[1];
    }

    let premises = getSubjectPremises(text);
    if (premises) {
        capturedHeaderData.subjectPremises = premises;
    }
}

function getSubjectPremises(text) {
    let lines = text.split(/\r?\n/);
    let premisesLines = [];
    let collecting = false;

    for (let line of lines) {
        if (/^Subject\s+Premises:/i.test(line)) {
            collecting = true;
            let content = line.split(/Subject\s+Premises:/i)[1] || "";
            premisesLines.push(content.trim());
            continue;
        }

        if (collecting) {
            if (/Building\s+Id\s+Number:/i.test(line)) break;
            if (/Request\s+Date:/i.test(line)) break;
            if (/Number\s+of\s+Rooms:/i.test(line)) break;
            if (/Request\s+No\.:/i.test(line)) break;
            premisesLines.push(line.trim());
        }
    }

    let result = premisesLines.join(" ");
    result = result.replace(/Number\s+of\s+Rooms:\s*\d+/i, "");
    result = result.replace(/\b(Apt)([A-Za-z0-9]+)/gi, "$1 $2");
    return result.trim();
}

function buildFinalTable() {
    document.getElementById("subjectPremises").innerText = capturedHeaderData.subjectPremises || "N/A";
    document.getElementById("buildingID").innerText = capturedHeaderData.buildingID || "N/A";
    document.getElementById("requestDate").innerText = capturedHeaderData.requestDate || "N/A";
    document.getElementById("requestNo").innerText = capturedHeaderData.requestNo || "N/A";
    document.getElementById("numRooms").innerText = capturedHeaderData.numRooms || "N/A";
    document.getElementById("headerData").style.display = "block";

    let tbody = document.querySelector("#rentTable tbody");
    tbody.innerHTML = "";

    if (!globalRows.length) {
        alert("No structured data found.");
        return;
    }

    globalRows.sort((a, b) => {
        let yearA = parseInt(a.year, 10) || 0;
        let yearB = parseInt(b.year, 10) || 0;
        return yearA - yearB;
    });

    for (let row of globalRows) {
        let tr = document.createElement("tr");
        tr.innerHTML = `
            <td contenteditable="true" data-label="Year">${row.year || ""}</td>
            <td contenteditable="true" data-label="Apt. Stat">${row.aptStat || ""}</td>
            <td contenteditable="true" data-label="Filing Date">${row.filingDate || ""}</td>
            <td contenteditable="true" data-label="Legal Regulated Rent">${row.regulatedRent || ""}</td>
            <td contenteditable="true" data-label="Pref. Rent">${row.prefRent || ""}</td>
            <td contenteditable="true" data-label="Actual Rent Paid">${row.actualRentPaid || ""}</td>
            <td contenteditable="true" data-label="Reasons Differ./Change">${row.reasonsChange || ""}</td>
            <td contenteditable="true" data-label="Lease Began/Ends">${row.leaseStart && row.leaseEnd ? row.leaseStart + " - " + row.leaseEnd : row.leaseStart || ""}</td>
            <td contenteditable="true" data-label="Tenant">${row.tenantName || ""}</td>
            <td contenteditable="true" data-label="Exempt/Missing">${row.exemptMissing || ""}</td>
        `;
        tbody.appendChild(tr);
    }
}

function showVerificationPopup() {
    alert("Double-check the data in the header and table. If everything looks correct, press 'Analyze' to proceed.");
}

// This remains the same, just calls analyzeOvercharges()
function analyzeData() {
    analyzeOvercharges();
}
</script>
</body>
</html>
