;;; wttrin-debug.el --- Debug functions for wttrin.el -*- lexical-binding: t; -*-

;; Copyright (C) 2025-2026 Craig Jennings
;; Author: Craig Jennings <c@cjennings.net>
;; Keywords: debug weather wttrin

;; SPDX-License-Identifier: GPL-3.0-or-later

;;; Commentary:

;; This file contains debug functions for troubleshooting wttrin.el behavior.
;; It is only loaded when `wttrin-debug' is non-nil.
;;
;; Enable with:
;;   (setq wttrin-debug t)
;;   (require 'wttrin)
;;
;; Available debug functions:
;; - `wttrin-debug-show-raw' - View raw weather data with line numbers
;; - `wttrin-debug-mode-line' - Diagnose mode-line lighter issues
;; - `wttrin--debug-mode-line-info' - Auto-called when wttrin runs (if debug enabled)
;;
;; Interactive commands:
;; - M-x wttrin-debug-enable  - Enable debug mode
;; - M-x wttrin-debug-disable - Disable debug mode
;;
;; Earlier versions exposed these as `debug-wttrin-*'.  Those names remain
;; available as obsolete aliases and will be removed in a future release.
;;
;; When debug mode is enabled, raw weather data is automatically saved to
;; timestamped files in `temporary-file-directory' for bug reports.

;;; Code:

;; No (require 'wttrin) — this file is loaded BY wttrin.el, so wttrin
;; is already present.  The defvar/declare-function suppress byte-compiler
;; warnings for symbols defined in the parent file.
(defvar wttrin-debug)
(defvar wttrin--force-refresh)
(declare-function wttrin--get-cached-or-fetch "wttrin")

;;;###autoload
(defun wttrin-debug-show-raw (location)
  "Fetch and display raw wttr.in data for LOCATION with line numbers.
This is useful for debugging header parsing issues.
Always fetches fresh data from the API, bypassing cache."
  (interactive "sLocation: ")
  (let ((wttrin--force-refresh t))
    (wttrin--get-cached-or-fetch
     location
   (lambda (raw-string &optional _error-msg)
     (with-current-buffer (get-buffer-create "*wttrin-debug*")
       (erase-buffer)
       (when raw-string
         (insert raw-string))
       (goto-char (point-min))
       (let ((line-num 1))
         (while (not (eobp))
           (beginning-of-line)
           (insert (format "%2d: " line-num))
           (setq line-num (1+ line-num))
           (forward-line 1)))
       (goto-char (point-min))
       (switch-to-buffer (current-buffer)))))))

;;;###autoload
(defun wttrin-debug-enable ()
  "Enable wttrin debug mode.
Raw weather data will be saved to timestamped files for bug reports."
  (interactive)
  (setq wttrin-debug t)
  (message "Wttrin debug mode enabled. Raw data will be saved to: %s" temporary-file-directory))

;;;###autoload
(defun wttrin-debug-disable ()
  "Disable wttrin debug mode."
  (interactive)
  (setq wttrin-debug nil)
  (message "Wttrin debug mode disabled"))

;;;###autoload
(defun wttrin-debug-mode-line ()
  "Display detailed mode-line information for the wttrin buffer.
This is useful for diagnosing why the mode-line lighter isn't appearing."
  (interactive)
  (let ((buf (get-buffer "*wttr.in*")))
    (if (not buf)
        (message "No *wttr.in* buffer exists. Run M-x wttrin first.")
      (with-current-buffer buf
        (let ((formatted-mode (format-mode-line mode-name)))
          (with-output-to-temp-buffer "*wttrin-mode-debug*"
            (princ (format "=== Wttrin Mode-Line Debug Info ===\n\n"))
            (princ (format "Buffer: %s\n" (buffer-name)))
            (princ (format "Major mode: %s\n" major-mode))
            (princ (format "mode-name variable: %S\n" mode-name))
            (princ (format "mode-name type: %s\n" (type-of mode-name)))
            (princ (format "format-mode-line result: %S\n" formatted-mode))
            (princ (format "\nmode-line-format first 5 elements:\n"))
            (let ((i 0))
              (dolist (elem mode-line-format)
                (when (< i 5)
                  (princ (format "  [%d] %S\n" i elem))
                  (setq i (1+ i)))))
            (princ (format "\nSpecial-mode parent: %s\n"
                          (get 'wttrin-mode 'derived-mode-parent)))
            (princ (format "Is special-mode active: %s\n"
                          (derived-mode-p 'special-mode)))))))))

(defun wttrin--debug-mode-line-info ()
  "Auto-generate mode-line diagnostic information.
Called after every weather buffer display.  A no-op stub in wttrin.el
is overridden by this implementation when the debug module is loaded."
  (wttrin-debug-mode-line))

(defvar wttrin--debug-log nil
  "List of debug log entries. Each entry is (timestamp . message).")

(defun wttrin--debug-log (format-string &rest args)
  "Log a debug message if wttrin-debug is enabled.
FORMAT-STRING and ARGS are passed to `format'.
Messages are stored in `wttrin--debug-log' for later review."
  (when wttrin-debug
    (let ((msg (apply #'format format-string args))
          (timestamp (format-time-string "%H:%M:%S.%3N")))
      (push (cons timestamp msg) wttrin--debug-log))))

;;;###autoload
(defun wttrin-debug-clear-log ()
  "Clear the debug log."
  (interactive)
  (setq wttrin--debug-log nil)
  (message "Wttrin debug log cleared"))

;;;###autoload
(defun wttrin-debug-show-log ()
  "Display the wttrin debug log in a buffer."
  (interactive)
  (with-current-buffer (get-buffer-create "*wttrin-debug-log*")
    (erase-buffer)
    (insert "=== WTTRIN DEBUG LOG ===\n")
    (insert (format "Total entries: %d\n\n" (length wttrin--debug-log)))
    (if wttrin--debug-log
        (dolist (entry (reverse wttrin--debug-log))
          (insert (format "[%s] %s\n" (car entry) (cdr entry))))
      (insert "(No log entries yet)\n"))
    (goto-char (point-min))
    (display-buffer (current-buffer))))

;;; Obsolete aliases for the old `debug-wttrin-*' names.
;; Kept so existing keybindings and configurations keep working; emit
;; a byte-compile / runtime obsolescence warning to nudge migration.

(define-obsolete-function-alias 'debug-wttrin-show-raw
  'wttrin-debug-show-raw "0.4.0")
(define-obsolete-function-alias 'debug-wttrin-enable
  'wttrin-debug-enable "0.4.0")
(define-obsolete-function-alias 'debug-wttrin-disable
  'wttrin-debug-disable "0.4.0")
(define-obsolete-function-alias 'debug-wttrin-mode-line
  'wttrin-debug-mode-line "0.4.0")

(provide 'wttrin-debug)
;;; wttrin-debug.el ends here
