/**
 * @fileoverview Utilitários para persistência de progresso de atividades de letramento no `localStorage`.
 *
 * Este módulo fornece helpers seguros e convenientes para carregar, salvar
 * e gerenciar o progresso das atividades de letramento digital, incluindo
 * controle de fases completadas por categoria.
 *
 * Convenções:
 * - Padrão de chave para progresso: `letramento:progress:{atividadeId}`
 * - Padrão de chave para fases completadas: `letramento:completed-phases:{categoria}`
 *
 * Schema de progresso por atividade:
 * ```
 * {
 *   atividadeId:  string,
 *   status:       'not-started' | 'started' | 'running' | 'success' | 'failure' | 'completed',
 *   attempts:     number,
 *   score:        number | null,
 *   startedAt:    string | null,   // ISO 8601
 *   completedAt:  string | null,   // ISO 8601
 *   lastAccess:   string,          // ISO 8601
 * }
 * ```
 *
 * Exemplo de uso:
 * ```js
 * import { getProgress, saveProgress, getCompletedPhases } from '../services/letramentoStorage';
 *
 * const progress = getProgress('mouse-velocidade');
 * saveProgress('mouse-velocidade', { status: 'completed', score: 100 });
 * const completed = getCompletedPhases('mouse');
 * ```
 *
 * @module services.letramentoStorage
 */

import { getAtividade } from '../atividades/letramento/letramentoRegistry';
import { safeLocalGet } from '../utils/localStorage';

const PREFIX = 'letramento:progress:';
const COMPLETED_PREFIX = 'letramento:completed-phases:';

/**
 * Gera a chave de storage para o progresso de uma atividade específica.
 *
 * @private
 * @param {string} atividadeId - Identificador da atividade
 * @returns {string} Chave formatada para uso no `localStorage`
 */
function storageKey(atividadeId) {
  return `${PREFIX}${atividadeId}`;
}

/**
 * Gera a chave de storage para as fases completadas de uma categoria.
 *
 * @private
 * @param {string} categoria - Nome da categoria de atividades
 * @returns {string} Chave formatada para uso no `localStorage`
 */
function completedPhasesKey(categoria) {
  return `${COMPLETED_PREFIX}${categoria}`;
}

/**
 * Obtém a lista de IDs de atividades completadas para uma categoria específica.
 *
 * Retorna um array de strings contendo os IDs das atividades que foram
 * marcadas como completadas nesta categoria. Em caso de erro ou ausência
 * de dados, retorna um array vazio.
 *
 * @param {string} categoria - Nome da categoria (ex: 'mouse', 'teclado')
 * @returns {string[]} Array com IDs das atividades completadas
 *
 * @example
 * const completed = getCompletedPhases('mouse');
 * // => ['mouse-velocidade', 'mouse-precisao']
 */
export function getCompletedPhases(categoria) {
  return safeLocalGet(completedPhasesKey(categoria), Array.isArray) ?? [];
}

/**
 * Adiciona uma atividade à lista de fases completadas de uma categoria.
 *
 * Se a atividade já estiver na lista, não duplica a entrada. A função
 * sempre retorna a lista atualizada de atividades completadas.
 *
 * @param {string} categoria - Nome da categoria da atividade
 * @param {string} atividadeId - ID da atividade a marcar como completada
 * @returns {string[]} Array atualizado com IDs das atividades completadas
 *
 * @example
 * addCompletedPhase('mouse', 'mouse-velocidade');
 * // => ['mouse-velocidade']
 */
export function addCompletedPhase(categoria, atividadeId) {
  const completed = getCompletedPhases(categoria);
  if (!completed.includes(atividadeId)) {
    completed.push(atividadeId);
    try {
      localStorage.setItem(completedPhasesKey(categoria), JSON.stringify(completed));
    } catch (e) {
      console.error('[letramentoStorage] Falha ao salvar fase completada', e);
    }
  }
  return completed;
}

/**
 * Remove todas as fases completadas de uma categoria do `localStorage`.
 *
 * Útil para resetar o progresso de uma categoria específica ou para
 * testes/depuração.
 *
 * @param {string} categoria - Nome da categoria a limpar
 * @returns {void}
 */
export function clearCompletedPhases(categoria) {
  localStorage.removeItem(completedPhasesKey(categoria));
}

/**
 * Carrega o progresso salvo de uma atividade específica.
 *
 * A função tenta ler e fazer parse do progresso salvo. Em caso de valor
 * ausente, dados corrompidos ou erro de parsing, retorna `null`.
 *
 * @param {string} atividadeId - ID da atividade
 * @returns {Object|null} Objeto com o progresso da atividade ou `null` se ausente/inválido
 * @returns {string} returns.atividadeId - ID da atividade
 * @returns {string} returns.status - Status atual ('not-started' | 'started' | 'running' | 'success' | 'failure' | 'completed')
 * @returns {number} returns.attempts - Número de tentativas realizadas
 * @returns {number|null} returns.score - Pontuação obtida
 * @returns {string|null} returns.startedAt - Timestamp ISO 8601 do início
 * @returns {string|null} returns.completedAt - Timestamp ISO 8601 da conclusão
 * @returns {string} returns.lastAccess - Timestamp ISO 8601 do último acesso
 *
 * @example
 * const progress = getProgress('mouse-velocidade');
 * if (progress?.status === 'completed') {
 *   console.log(`Score: ${progress.score}`);
 * }
 */
export function getProgress(atividadeId) {
  return safeLocalGet(storageKey(atividadeId));
}

/**
 * Salva ou atualiza o progresso de uma atividade no `localStorage`.
 *
 * Faz merge do progresso existente com as atualizações fornecidas,
 * automaticamente atualiza o timestamp de `lastAccess`, e quando o status
 * muda para 'completed' ou 'success', adiciona a atividade à lista de
 * fases completadas da categoria.
 *
 * Se a atividade ainda não tem progresso salvo, inicializa com valores
 * padrão antes de aplicar as atualizações.
 *
 * @param {string} atividadeId - ID da atividade
 * @param {Object} update - Objeto com campos a atualizar
 * @param {string} [update.status] - Novo status da atividade
 * @param {number} [update.attempts] - Atualizar contagem de tentativas
 * @param {number|null} [update.score] - Pontuação obtida
 * @param {string|null} [update.startedAt] - Timestamp ISO 8601 do início
 * @param {string|null} [update.completedAt] - Timestamp ISO 8601 da conclusão
 * @returns {Object} O objeto de progresso completo após a atualização
 *
 * @example
 * // Marcar como iniciada
 * saveProgress('mouse-velocidade', {
 *   status: 'started',
 *   startedAt: new Date().toISOString()
 * });
 *
 * // Completar com pontuação
 * saveProgress('mouse-velocidade', {
 *   status: 'completed',
 *   score: 85,
 *   completedAt: new Date().toISOString()
 * });
 */
export function saveProgress(atividadeId, update) {
  const existing = getProgress(atividadeId) ?? {
    atividadeId,
    status: 'not-started',
    attempts: 0,
    score: null,
    startedAt: null,
    completedAt: null,
  };

  const next = {
    ...existing,
    ...update,
    lastAccess: new Date().toISOString(),
  };

  try {
    localStorage.setItem(storageKey(atividadeId), JSON.stringify(next));
    
    // Se a atividade foi completada, adiciona ao array de completadas
    if ((next.status === 'completed' || next.status === 'success') && existing.status !== next.status) {
      const atividade = getAtividade(atividadeId);
      if (atividade?.categoria) {
        addCompletedPhase(atividade.categoria, atividadeId);
      }
    }
  } catch (e) {
    console.error('[letramentoStorage] Falha ao salvar progresso', e);
  }

  return next;
}

/**
 * Obtém o progresso de todas as atividades salvas no `localStorage`.
 *
 * Itera por todas as chaves do `localStorage` que seguem o padrão
 * `letramento:progress:*` e retorna um objeto mapeando IDs de atividades
 * para seus respectivos progressos.
 *
 * @returns {Object.<string, Object>} Objeto com progressos indexados por atividadeId
 *
 * @example
 * const allProgress = getAllProgress();
 * // => {
 * //   'mouse-velocidade': { status: 'completed', score: 100, ... },
 * //   'mouse-precisao': { status: 'started', score: null, ... }
 * // }
 */
export function getAllProgress() {
  const result = {};
  for (let i = 0; i < localStorage.length; i++) {
    const k = localStorage.key(i);
    if (k && k.startsWith(PREFIX)) {
      const id = k.slice(PREFIX.length);
      result[id] = getProgress(id);
    }
  }
  return result;
}

/**
 * Remove o progresso salvo de uma atividade específica do `localStorage`.
 *
 * Útil para resetar o progresso individual de uma atividade ou para
 * testes/depuração. Não remove a atividade da lista de fases completadas
 * da categoria.
 *
 * @param {string} atividadeId - ID da atividade a limpar
 * @returns {void}
 */
export function clearProgress(atividadeId) {
  localStorage.removeItem(storageKey(atividadeId));
}
