import unittest
from pathlib import Path
import re


ROOT = Path(__file__).resolve().parent


class TrendBreakDashboardTableTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.dashboard = (ROOT / "trend_break_dashboard.html").read_text(encoding="utf-8")

    def test_detection_date_and_time_columns_are_sortable(self):
        self.assertIn(
            '<th class="sortable" data-sort="detected"',
            self.dashboard,
        )
        self.assertIn(
            '<th class="sortable" data-sort="maxProfitDays"',
            self.dashboard,
        )
        self.assertIn(">Deteksi</th>", self.dashboard)
        self.assertIn(">Puncak</th>", self.dashboard)

    def test_table_headers_are_single_word_and_related_columns_are_merged(self):
        headers = [label.strip() for label in re.findall(r"<th[^>]*>([^<]+)</th>", self.dashboard)]
        self.assertEqual(
            headers,
            ["Ticker", "Kandidat", "Deteksi", "Profit", "Puncak", "Entry", "P/L", "H+0", "H+1", "H+2", "TV", "Volume", "Tech", "Bandar"],
        )
        self.assertIn("function detectionCell(row, liveView)", self.dashboard)
        self.assertIn("function entryCell(row)", self.dashboard)
        self.assertIn("function volumeCell(row, latestValue)", self.dashboard)

    def test_live_and_archive_rows_expose_detection_date_and_time(self):
        self.assertIn("detectedDate: detection.date", self.dashboard)
        self.assertIn("detectedTime: detection.time", self.dashboard)
        self.assertIn('if (sortKey === "detected") return `${r.detectedDate || ""} ${r.detectedTime || ""}`;', self.dashboard)
        self.assertIn("daysToMaxProfit: Number.isFinite(timing?.maxProfitDays)", self.dashboard)
        self.assertIn('if (sortKey === "maxProfitDays")', self.dashboard)

    def test_peak_profit_cell_explains_holding_period(self):
        self.assertIn("function maxProfitTimingCell(row)", self.dashboard)
        self.assertIn("<span class=\"badge ${badgeClass}\">H+${days}</span>", self.dashboard)
        self.assertIn("timing.maxProfitDate", self.dashboard)

    def test_summary_shows_average_days_to_a_reasonable_peak(self):
        self.assertIn(">Rata-rata Puncak ≥5%</label>", self.dashboard)
        self.assertIn('id="filter-peak-days-value"', self.dashboard)
        self.assertIn("const PEAK_PROFIT_TARGET_PCT = 5;", self.dashboard)
        self.assertIn("function calcPeakTiming(candidateRows)", self.dashboard)
        self.assertIn("maxProfitPct < PEAK_PROFIT_TARGET_PCT", self.dashboard)
        self.assertIn("setText(\"filter-peak-days-value\"", self.dashboard)

    def test_first_day_close_profit_is_next_to_realtime_pl(self):
        self.assertIn(
            '<th class="sortable" data-sort="plpct">P/L</th>',
            self.dashboard,
        )
        self.assertIn('<th class="sortable" data-sort="firstDayClosePnl">H+0</th>', self.dashboard)
        self.assertIn('<th class="sortable" data-sort="day1ClosePnl">H+1</th>', self.dashboard)
        self.assertIn('<th class="sortable" data-sort="day2ClosePnl">H+2</th>', self.dashboard)
        self.assertIn("const firstDayClosePrice = positiveNumber(", self.dashboard)
        self.assertIn("firstDayClosePct", self.dashboard)
        self.assertIn("const closePnlByDay = {};", self.dashboard)
        self.assertIn("let dailyCloseHistory = {};", self.dashboard)
        self.assertIn("async function loadDailyCloseHistory()", self.dashboard)
        self.assertIn("/api/trend_break_daily_closes?", self.dashboard)
        self.assertIn("const dailyBars = Object.entries(dailyCloseHistory[base.ticker] || {})", self.dashboard)
        self.assertIn("function dayCloseCell(row, offset)", self.dashboard)
        self.assertIn("function firstDayCloseCell(row)", self.dashboard)
        self.assertIn("function secondDayCloseCell(row)", self.dashboard)
        self.assertIn("function thirdDayCloseCell(row)", self.dashboard)
        self.assertIn("<td>${plHtml}</td>", self.dashboard)
        self.assertIn("<td>${firstDayCloseCell(r)}</td>", self.dashboard)
        self.assertIn("<td>${secondDayCloseCell(r)}</td>", self.dashboard)
        self.assertIn("<td>${thirdDayCloseCell(r)}</td>", self.dashboard)

    def test_change_display_and_sort_use_the_same_tv_quote_as_price(self):
        self.assertIn('data-sort="rtprice" title="Harga dan perubahan quote TV terbaru">TV</th>', self.dashboard)
        self.assertNotIn(">Chg</th>", self.dashboard)
        self.assertIn("function tvCell(price, change)", self.dashboard)
        self.assertIn("<td>${tvCell(rtPrice, chg)}</td>", self.dashboard)
        self.assertIn("if (sortKey === \"change\") return (displayQuote.change_pct != null ? displayQuote.change_pct : r.change) || 0;", self.dashboard)
        self.assertIn("const chg = displayQuote.change_pct != null ? displayQuote.change_pct : r.change;", self.dashboard)
        self.assertIn("const displayChg = displayQuote.change_pct != null ? displayQuote.change_pct : row.change;", self.dashboard)
        self.assertIn("`TV Scanner${time}`", self.dashboard)

    def test_sort_headers_publish_direction_for_keyboard_and_screen_reader_users(self):
        self.assertIn('th.setAttribute("aria-sort", sorted ? (sortDir === 1 ? "ascending" : "descending") : "none");', self.dashboard)


if __name__ == "__main__":
    unittest.main()
