const fs = require('fs');
const path = require('path');

const SEASONS_FILE = path.join(__dirname, '..', 'constants', 'seasons');

// Parse DD.MM from the "until eos" parenthetical to an end-of-day UTC unix ts
// for the season's year (inferred from the first weekN timestamp).
function _endOfDayUtc(year, day, month) {
    const d = new Date(Date.UTC(year, month - 1, day, 23, 59, 59));
    return Math.floor(d.getTime() / 1000);
}

// Parse the seasons file into:
//   { '2026-I': {start, end, weeks}, '2026-II': {start, end, weeks}, ... }
// where `end` is the last second (UTC) of the date in the "until eos" row.
// Status is computed at access time by getSeasons(), not cached here.
function parseSeasonsFile(content) {
    const lines = content.split('\n');
    const seasons = {};
    let current = null;
    let firstTs = null;
    let eosDay = null, eosMonth = null;
    let weekEntries = [];

    const seasonHeader = /^\s*(\d{4})-(I{1,3}|IV|VI{0,3}|IX|X)\s*$/;
    const weekLine = /^(week\s+\d+|until\s+eos)\s+\((\d{2}\.\d{2})\s+[—-]\s+(\d{2}\.\d{2})\)\s+<t:(\d+):R>\s+max BR\s+(\d+(?:\.\d+)?)/i;

    const commit = () => {
        if (current && firstTs !== null && eosDay !== null) {
            const year = parseInt(current.split('-')[0], 10);
            seasons[current] = {
                start: firstTs,
                end: _endOfDayUtc(year, eosDay, eosMonth),
                weeks: weekEntries,
            };
        }
        current = null; firstTs = null; eosDay = null; eosMonth = null;
        weekEntries = [];
    };

    for (const line of lines) {
        const h = line.match(seasonHeader);
        if (h) { commit(); current = `${h[1]}-${h[2]}`; continue; }
        if (!current) continue;
        const w = line.match(weekLine);
        if (w) {
            const kind = w[1].toLowerCase();
            const startDate = w[2];
            const endDate = w[3];
            const ts = parseInt(w[4], 10);
            const maxBr = parseFloat(w[5]);
            weekEntries.push({
                label: kind,
                start_date: startDate,
                end_date: endDate,
                start_ts: ts,
                max_br: maxBr,
            });
            if (firstTs === null) firstTs = ts;
            if (kind === 'until eos') {
                eosDay = parseInt(endDate.split('.')[0], 10);
                eosMonth = parseInt(endDate.split('.')[1], 10);
            }
        }
    }
    commit();
    return seasons;
}

// All "week N (…) <t:TS:R>" timestamps for a given season name, in order.
// Used as x-axis faint vline markers by the Python renderer.
function parseWeekBoundaries(content, seasonName) {
    const lines = content.split('\n');
    const out = [];
    let inSeason = false;
    const seasonHeader = /^\s*(\d{4})-(I{1,3}|IV|VI{0,3}|IX|X)\s*$/;
    const weekLine = /<t:(\d+):R>/;
    for (const line of lines) {
        const h = line.match(seasonHeader);
        if (h) { inSeason = `${h[1]}-${h[2]}` === seasonName; continue; }
        if (!inSeason) continue;
        const w = line.match(weekLine);
        if (w) out.push(parseInt(w[1], 10));
    }
    return out;
}

let _cached = null;
function _loadSeasons() {
    if (_cached) return _cached;
    const content = fs.readFileSync(SEASONS_FILE, 'utf8');
    const parsed = parseSeasonsFile(content);
    _cached = { content, parsed };
    return _cached;
}

function getSeasons() {
    const { parsed } = _loadSeasons();
    const now = Math.floor(Date.now() / 1000);
    const out = {};
    for (const [name, range] of Object.entries(parsed)) {
        out[name] = {
            start: range.start,
            end: range.end,
            status: range.end < now ? 'completed' : 'in_progress',
        };
    }
    return out;
}

function getSeasonRange(name) {
    return getSeasons()[name] || null;
}

function getSeasonDetails() {
    const { parsed } = _loadSeasons();
    const now = Math.floor(Date.now() / 1000);
    const out = {};
    for (const [name, range] of Object.entries(parsed)) {
        out[name] = {
            start: range.start,
            end: range.end,
            status: range.end < now ? 'completed' : 'in_progress',
            weeks: range.weeks || [],
        };
    }
    return out;
}

function getWeekBoundaries(name) {
    const { content } = _loadSeasons();
    return parseWeekBoundaries(content, name);
}

module.exports = { getSeasons, getSeasonRange, getSeasonDetails, getWeekBoundaries, parseSeasonsFile, parseWeekBoundaries };
