"""Slot panels, forms, edit/add, slot picker JS."""
from __future__ import annotations


from shared.sx.helpers import sx_call
from shared.sx.parser import SxExpr


# ===========================================================================
# SLOT PICKER JS — shared by entry edit + entry add forms
# ===========================================================================

_SLOT_PICKER_JS = """\
<script>
  (function () {
    function timeToMinutes(timeStr) {
      if (!timeStr) return 0;
      const [hours, minutes] = timeStr.split(':').map(Number);
      return hours * 60 + minutes;
    }

    function calculateCost(slotCost, slotStart, slotEnd, actualStart, actualEnd, flexible) {
      if (!flexible) {
        return parseFloat(slotCost);
      }
      if (!actualStart || !actualEnd) return 0;
      const slotStartMin = timeToMinutes(slotStart);
      const slotEndMin = timeToMinutes(slotEnd);
      const actualStartMin = timeToMinutes(actualStart);
      const actualEndMin = timeToMinutes(actualEnd);
      const slotDuration = slotEndMin - slotStartMin;
      const actualDuration = actualEndMin - actualStartMin;
      if (slotDuration <= 0 || actualDuration <= 0) return 0;
      const ratio = actualDuration / slotDuration;
      return parseFloat(slotCost) * ratio;
    }

    function initEntrySlotPicker(root, applyInitial) {
      if (applyInitial === undefined) applyInitial = false;
      const select = root.querySelector('[data-slot-picker]');
      if (!select) return;
      const timeFields = root.querySelector('[data-time-fields]');
      const startInput = root.querySelector('[data-entry-start]');
      const endInput = root.querySelector('[data-entry-end]');
      const helper = root.querySelector('[data-slot-boundary]');
      const costDisplay = root.querySelector('[data-cost-display]');
      const costRow = root.querySelector('[data-cost-row]');
      const fixedSummary = root.querySelector('[data-fixed-summary]');
      if (!startInput || !endInput) return;

      function updateCost() {
        const opt = select.selectedOptions[0];
        if (!opt || !opt.value) {
          if (costDisplay) costDisplay.textContent = '\\u00a30.00';
          return;
        }
        const cost = opt.dataset.cost || '0';
        const s = opt.dataset.start || '';
        const e = opt.dataset.end || '';
        const flexible = opt.dataset.flexible === '1';
        const calculatedCost = calculateCost(cost, s, e, startInput.value, endInput.value, flexible);
        if (costDisplay) costDisplay.textContent = '\\u00a3' + calculatedCost.toFixed(2);
      }

      function applyFromOption(opt) {
        if (!opt || !opt.value) {
          if (timeFields) timeFields.classList.add('hidden');
          if (costRow) costRow.classList.add('hidden');
          if (fixedSummary) fixedSummary.classList.add('hidden');
          return;
        }
        const s = opt.dataset.start || '';
        const e = opt.dataset.end || '';
        const flexible = opt.dataset.flexible === '1';
        if (!flexible) {
          if (s) startInput.value = s;
          if (e) endInput.value = e;
          if (timeFields) timeFields.classList.add('hidden');
          if (fixedSummary) {
            fixedSummary.classList.remove('hidden');
            fixedSummary.textContent = e ? s + ' \\u2013 ' + e : 'From ' + s + ' (open-ended)';
          }
          if (costRow) costRow.classList.remove('hidden');
        } else {
          if (timeFields) timeFields.classList.remove('hidden');
          if (fixedSummary) fixedSummary.classList.add('hidden');
          if (costRow) costRow.classList.remove('hidden');
          if (helper) {
            helper.textContent = e ? 'Times must be between ' + s + ' and ' + e + '.' : 'Start at or after ' + s + '.';
          }
        }
        updateCost();
      }

      if (applyInitial) applyFromOption(select.selectedOptions[0]);

      if (select._slotChangeHandler) select.removeEventListener('change', select._slotChangeHandler);
      select._slotChangeHandler = () => applyFromOption(select.selectedOptions[0]);
      select.addEventListener('change', select._slotChangeHandler);
      startInput.addEventListener('input', updateCost);
      endInput.addEventListener('input', updateCost);
    }

    document.addEventListener('DOMContentLoaded', () => initEntrySlotPicker(document, true));
    if (window.htmx) htmx.onLoad((content) => initEntrySlotPicker(content, true));
  })();
</script>"""


# ---------------------------------------------------------------------------
# Slot options (shared by entry edit + add forms)
# ---------------------------------------------------------------------------

def _slot_options_html(day_slots, selected_slot_id=None) -> str:
    """Build slot <option> elements."""
    parts = []
    for slot in day_slots:
        start = slot.time_start.strftime("%H:%M") if slot.time_start else ""
        end = slot.time_end.strftime("%H:%M") if slot.time_end else ""
        flexible = getattr(slot, "flexible", False)
        cost = getattr(slot, "cost", None)
        cost_str = str(cost) if cost is not None else "0"
        label_parts = [slot.name, f"({start}"]
        if end:
            label_parts.append(f"\u2013{end})")
        else:
            label_parts.append("\u2013open-ended)")
        if flexible:
            label_parts.append("[flexible]")
        label = " ".join(label_parts)

        parts.append(sx_call("events-slot-option",
                            value=str(slot.id),
                            data_start=start, data_end=end,
                            data_flexible="1" if flexible else "0",
                            data_cost=cost_str,
                            selected="selected" if selected_slot_id == slot.id else None,
                            label=label))
    return "".join(parts)


# ---------------------------------------------------------------------------
# Slot header row
# ---------------------------------------------------------------------------

def _slot_header_html(ctx: dict, *, oob: bool = False) -> str:
    """Build the slot detail header row."""
    from quart import url_for

    calendar = ctx.get("calendar")
    if not calendar:
        return ""
    cal_slug = getattr(calendar, "slug", "")
    slot = ctx.get("slot")
    if not slot:
        return ""

    desc = getattr(slot, "description", "") or ""
    label_sx = sx_call("events-slot-label",
                                  name=slot.name, description=desc)

    return sx_call("menu-row-sx", id="slot-row", level=5,
                  link_label_content=label_sx,
                  child_id="slot-header-child", oob=oob)


# ---------------------------------------------------------------------------
# Slot main panel
# ---------------------------------------------------------------------------

def render_slot_main_panel(slot, calendar, *, oob: bool = False) -> str:
    """Render slot detail view."""
    from quart import url_for, g

    styles = getattr(g, "styles", None) or {}
    list_container = getattr(styles, "list_container", "") if hasattr(styles, "list_container") else styles.get("list_container", "")
    pre_action = getattr(styles, "pre_action_button", "") if hasattr(styles, "pre_action_button") else styles.get("pre_action_button", "")
    cal_slug = getattr(calendar, "slug", "")

    days_display = getattr(slot, "days_display", "\u2014")
    days = days_display.split(", ")
    flexible = getattr(slot, "flexible", False)
    time_start = slot.time_start.strftime("%H:%M") if slot.time_start else ""
    time_end = slot.time_end.strftime("%H:%M") if slot.time_end else ""
    cost = getattr(slot, "cost", None)
    cost_str = f"{cost:.2f}" if cost is not None else ""
    desc = getattr(slot, "description", "") or ""

    edit_url = url_for("calendar.slots.slot.get_edit", slot_id=slot.id, calendar_slug=cal_slug)

    # Days pills
    if days and days[0] != "\u2014":
        days_inner = "".join(
            sx_call("events-slot-day-pill", day=d) for d in days
        )
        days_html = sx_call("events-slot-days-pills", days_inner=SxExpr(days_inner))
    else:
        days_html = sx_call("events-slot-no-days")

    sid = str(slot.id)

    result = sx_call("events-slot-panel",
                    slot_id=sid, list_container=list_container,
                    days=days_html,
                    flexible="yes" if flexible else "no",
                    time_str=f"{time_start} \u2014 {time_end}",
                    cost_str=cost_str,
                    pre_action=pre_action, edit_url=edit_url)

    if oob:
        result += sx_call("events-slot-description-oob", description=desc)

    return result


# ---------------------------------------------------------------------------
# Slots table
# ---------------------------------------------------------------------------

def render_slots_table(slots, calendar) -> str:
    """Render slots table with rows and add button."""
    from quart import url_for, g
    from shared.browser.app.csrf import generate_csrf_token
    csrf = generate_csrf_token()

    styles = getattr(g, "styles", None) or {}
    list_container = getattr(styles, "list_container", "") if hasattr(styles, "list_container") else styles.get("list_container", "")
    tr_cls = getattr(styles, "tr", "") if hasattr(styles, "tr") else styles.get("tr", "")
    pill_cls = getattr(styles, "pill", "") if hasattr(styles, "pill") else styles.get("pill", "")
    action_btn = getattr(styles, "action_button", "") if hasattr(styles, "action_button") else styles.get("action_button", "")
    pre_action = getattr(styles, "pre_action_button", "") if hasattr(styles, "pre_action_button") else styles.get("pre_action_button", "")
    hx_select = getattr(g, "hx_select_search", "#main-panel")
    cal_slug = getattr(calendar, "slug", "")

    rows_html = ""
    if slots:
        for s in slots:
            slot_href = url_for("defpage_slot_detail", calendar_slug=cal_slug, slot_id=s.id)
            del_url = url_for("calendar.slots.slot.slot_delete", calendar_slug=cal_slug, slot_id=s.id)
            desc = getattr(s, "description", "") or ""

            days_display = getattr(s, "days_display", "\u2014")
            day_list = days_display.split(", ")
            if day_list and day_list[0] != "\u2014":
                days_inner = "".join(
                    sx_call("events-slot-day-pill", day=d) for d in day_list
                )
                days_html = sx_call("events-slot-days-pills", days_inner=SxExpr(days_inner))
            else:
                days_html = sx_call("events-slot-no-days")

            time_start = s.time_start.strftime("%H:%M") if s.time_start else ""
            time_end = s.time_end.strftime("%H:%M") if s.time_end else ""
            cost = getattr(s, "cost", None)
            cost_str = f"{cost:.2f}" if cost is not None else ""

            rows_html += sx_call("events-slots-row",
                                tr_cls=tr_cls, slot_href=slot_href,
                                pill_cls=pill_cls, hx_select=hx_select,
                                slot_name=s.name, description=desc,
                                flexible="yes" if s.flexible else "no",
                                days=days_html,
                                time_str=f"{time_start} - {time_end}",
                                cost_str=cost_str, action_btn=action_btn,
                                del_url=del_url,
                                csrf_hdr={"X-CSRFToken": csrf})
    else:
        rows_html = sx_call("events-slots-empty-row")

    add_url = url_for("calendar.slots.add_form", calendar_slug=cal_slug)

    return sx_call("events-slots-table",
                  list_container=list_container, rows=SxExpr(rows_html),
                  pre_action=pre_action, add_url=add_url)


# ---------------------------------------------------------------------------
# Slot edit form
# ---------------------------------------------------------------------------

def render_slot_edit_form(slot, calendar) -> str:
    """Render slot edit form (replaces _types/slot/_edit.html)."""
    from quart import url_for, g
    from shared.browser.app.csrf import generate_csrf_token
    csrf = generate_csrf_token()

    styles = getattr(g, "styles", None) or {}
    list_container = styles.get("list_container", "") if isinstance(styles, dict) else getattr(styles, "list_container", "")
    action_btn = styles.get("action_button", "") if isinstance(styles, dict) else getattr(styles, "action_button", "")
    cancel_btn = styles.get("cancel_button", "") if isinstance(styles, dict) else getattr(styles, "cancel_button", "")
    cal_slug = getattr(calendar, "slug", "")
    sid = slot.id

    put_url = url_for("calendar.slots.slot.put", calendar_slug=cal_slug, slot_id=sid)
    cancel_url = url_for("calendar.slots.slot.get_view", calendar_slug=cal_slug, slot_id=sid)

    cost = getattr(slot, "cost", None)
    cost_val = f"{cost:.2f}" if cost is not None else ""
    start_val = slot.time_start.strftime("%H:%M") if slot.time_start else ""
    end_val = slot.time_end.strftime("%H:%M") if slot.time_end else ""
    desc_val = getattr(slot, "description", "") or ""

    # Days checkboxes
    day_keys = [("mon", "Mon"), ("tue", "Tue"), ("wed", "Wed"), ("thu", "Thu"),
                ("fri", "Fri"), ("sat", "Sat"), ("sun", "Sun")]
    all_checked = all(getattr(slot, k, False) for k, _ in day_keys)

    days_parts = [sx_call("events-day-all-checkbox",
                         checked="checked" if all_checked else None)]
    for key, label in day_keys:
        checked = getattr(slot, key, False)
        days_parts.append(sx_call("events-day-checkbox",
                                 name=key, label=label,
                                 checked="checked" if checked else None))
    days_html = "".join(days_parts)

    flexible = getattr(slot, "flexible", False)

    return sx_call("events-slot-edit-form",
                  slot_id=str(sid), list_container=list_container,
                  put_url=put_url, cancel_url=cancel_url, csrf=csrf,
                  name_val=slot.name or "", cost_val=cost_val,
                  start_val=start_val, end_val=end_val,
                  desc_val=desc_val, days=SxExpr(days_html),
                  flexible_checked="checked" if flexible else None,
                  action_btn=action_btn, cancel_btn=cancel_btn)


# ---------------------------------------------------------------------------
# Slot add form / button
# ---------------------------------------------------------------------------

def render_slot_add_form(calendar) -> str:
    """Render slot add form (replaces _types/slots/_add.html)."""
    from quart import url_for, g
    from shared.browser.app.csrf import generate_csrf_token
    csrf = generate_csrf_token()

    styles = getattr(g, "styles", None) or {}
    action_btn = styles.get("action_button", "") if isinstance(styles, dict) else getattr(styles, "action_button", "")
    cancel_btn = styles.get("cancel_button", "") if isinstance(styles, dict) else getattr(styles, "cancel_button", "")
    cal_slug = getattr(calendar, "slug", "")

    post_url = url_for("calendar.slots.post", calendar_slug=cal_slug)
    cancel_url = url_for("calendar.slots.add_button", calendar_slug=cal_slug)
    csrf_hdr = {"X-CSRFToken": csrf}

    # Days checkboxes (all unchecked for add)
    day_keys = [("mon", "Mon"), ("tue", "Tue"), ("wed", "Wed"), ("thu", "Thu"),
                ("fri", "Fri"), ("sat", "Sat"), ("sun", "Sun")]
    days_parts = [sx_call("events-day-all-checkbox", checked=None)]
    for key, label in day_keys:
        days_parts.append(sx_call("events-day-checkbox", name=key, label=label, checked=None))
    days_html = "".join(days_parts)

    return sx_call("events-slot-add-form",
                  post_url=post_url, csrf=csrf_hdr,
                  days=SxExpr(days_html),
                  action_btn=action_btn, cancel_btn=cancel_btn,
                  cancel_url=cancel_url)


def render_slot_add_button(calendar) -> str:
    """Render slot add button (replaces _types/slots/_add_button.html)."""
    from quart import url_for, g

    styles = getattr(g, "styles", None) or {}
    pre_action = styles.get("pre_action_button", "") if isinstance(styles, dict) else getattr(styles, "pre_action_button", "")
    cal_slug = getattr(calendar, "slug", "")
    add_url = url_for("calendar.slots.add_form", calendar_slug=cal_slug)

    return sx_call("events-slot-add-button", pre_action=pre_action, add_url=add_url)
