/**
 * Parse a subset of the OSM opening_hours format into FarmaClic's internal
 * shape: { mon: ["09:00", "21:00"], ..., sun: null }.
 *
 * Supports the patterns commonly seen on amenity=pharmacy nodes:
 *   "24/7"
 *   "Mo-Fr 09:00-21:00"
 *   "Mo-Fr 09:00-21:00; Sa 09:00-14:00; Su closed"
 *   "Mo,We,Fr 09:00-14:00"
 *   "Mo-Fr 09:00-13:30,16:30-20:00"  (split shifts: opens first, closes last)
 *
 * Public-holiday rules (PH/SH) and weeknumber/date filters are ignored.
 * Returns null if no usable rule was found.
 *
 * @param {string} input
 * @returns {{mon: string[]|null, tue: string[]|null, wed: string[]|null, thu: string[]|null, fri: string[]|null, sat: string[]|null, sun: string[]|null}|null}
 */
export function parseOsmOpeningHours(input) {
  if (!input || typeof input !== 'string') return null;
  const cleaned = input.trim().replace(/\s+/g, ' ');
  if (!cleaned) return null;

  const result = { mon: null, tue: null, wed: null, thu: null, fri: null, sat: null, sun: null };

  if (/^24\s*\/\s*7$/i.test(cleaned)) {
    for (const k of Object.keys(result)) result[k] = ['00:00', '24:00'];
    return result;
  }

  const rules = cleaned.split(';').map(r => r.trim()).filter(Boolean);
  let anySet = false;

  for (const rule of rules) {
    const ruleNoComment = rule.replace(/\([^)]*\)/g, '').trim();
    if (!ruleNoComment) continue;

    const lower = ruleNoComment.toLowerCase();
    if (lower === 'closed' || lower === 'off') continue;

    const tokens = ruleNoComment.split(/\s+/);
    const dayPart = tokens.shift();
    const timePart = tokens.join(' ').trim();
    if (!dayPart) continue;

    const days = expandDayPart(dayPart);
    if (!days.length) continue;

    if (!timePart || /^(off|closed)$/i.test(timePart)) {
      for (const d of days) result[d] = null;
      anySet = true;
      continue;
    }

    const range = collapseTimeRanges(timePart);
    if (!range) continue;

    for (const d of days) result[d] = range;
    anySet = true;
  }

  return anySet ? result : null;
}

const DAY_CODE_TO_KEY = { mo: 'mon', tu: 'tue', we: 'wed', th: 'thu', fr: 'fri', sa: 'sat', su: 'sun' };
const DAY_ORDER = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];

function expandDayPart(dayPart) {
  const out = new Set();
  for (const segment of dayPart.split(',')) {
    const seg = segment.trim();
    if (!seg) continue;
    if (/^(ph|sh)(-(ph|sh))?$/i.test(seg)) continue;

    const rangeMatch = seg.match(/^([A-Za-z]{2})-([A-Za-z]{2})$/);
    if (rangeMatch) {
      const a = DAY_CODE_TO_KEY[rangeMatch[1].toLowerCase()];
      const b = DAY_CODE_TO_KEY[rangeMatch[2].toLowerCase()];
      if (!a || !b) continue;
      const ai = DAY_ORDER.indexOf(a);
      const bi = DAY_ORDER.indexOf(b);
      if (ai === -1 || bi === -1) continue;
      if (ai <= bi) {
        for (let i = ai; i <= bi; i++) out.add(DAY_ORDER[i]);
      } else {
        for (let i = ai; i < DAY_ORDER.length; i++) out.add(DAY_ORDER[i]);
        for (let i = 0; i <= bi; i++) out.add(DAY_ORDER[i]);
      }
      continue;
    }

    const single = DAY_CODE_TO_KEY[seg.toLowerCase()];
    if (single) out.add(single);
  }
  return [...out];
}

function collapseTimeRanges(timePart) {
  const matches = [...timePart.matchAll(/(\d{1,2}):(\d{2})\s*-\s*(\d{1,2}):(\d{2})/g)];
  if (matches.length === 0) return null;
  const first = matches[0];
  const last = matches[matches.length - 1];
  const open = `${first[1].padStart(2, '0')}:${first[2]}`;
  const close = `${last[3].padStart(2, '0')}:${last[4]}`;
  return [open, close];
}
