import { create } from "zustand";

const FOCUS_REVIEW_HISTORY_STORAGE_KEY = "mindavio-focus-review-history";
const FOCUS_REVIEW_HISTORY_LIMIT = 21;

/* ── Types ────────────────────────────────────────────────────────────────── */

export interface TaskCompletion {
  taskId: string;
  taskTitle: string;
  completedAt: number;  // unix ms
  delta: number;        // ms since previous completion (or work timer start if first)
}

export interface FocusReviewSnapshot {
  activeTeamId: string | null;
  completedTasks: TaskCompletion[];
  endedAt: number;
  focusDuration: number;
  id: string;
  startedAt: number | null;
  workDuration: number;
}

interface FocusStore {
  /* ── Focus mode ── */
  focusActive:    boolean;
  focusStartTime: number | null;
  focusReturnPath: string | null;
  focusReviewHistory: FocusReviewSnapshot[];
  lastFocusReview: FocusReviewSnapshot | null;
  selectedFocusReviewId: string | null;

  /* ── Work timer ── */
  workTimerRunning:  boolean;
  workTimerStart:    number | null;  // timestamp when current segment started
  workTimerElapsed:  number;         // accumulated ms from previous segments

  /* ── Task tracking ── */
  taskCompletions:   TaskCompletion[];
  lastCompletionTime: number | null;

  /* ── Actions ── */
  startFocusMode:   () => void;
  endFocusMode:     () => void;
  completeFocusMode: (activeTeamId: string | null) => void;
  clearFocusReview: () => void;
  openFocusReview: (reviewId: string) => void;
  setFocusReturnPath: (path: string | null) => void;

  startWorkTimer:   () => void;
  pauseWorkTimer:   () => void;
  resetWorkTimer:   () => void;

  recordTaskCompletion: (taskId: string, taskTitle: string) => void;
}

/* ── Store ────────────────────────────────────────────────────────────────── */

function normalizeFocusReviewSnapshot(
  review: Partial<FocusReviewSnapshot> & Pick<FocusReviewSnapshot, "endedAt">,
): FocusReviewSnapshot {
  return {
    activeTeamId: review.activeTeamId ?? null,
    completedTasks: Array.isArray(review.completedTasks) ? review.completedTasks : [],
    endedAt: review.endedAt,
    focusDuration: review.focusDuration ?? 0,
    id: review.id ?? `focus-review-${review.endedAt}`,
    startedAt: review.startedAt ?? null,
    workDuration: review.workDuration ?? 0,
  };
}

function loadStoredFocusReviewHistory(): FocusReviewSnapshot[] {
  if (typeof window === "undefined") return [];

  try {
    const raw = window.localStorage.getItem(FOCUS_REVIEW_HISTORY_STORAGE_KEY);
    if (!raw) return [];

    const parsed = JSON.parse(raw);
    if (!Array.isArray(parsed)) return [];

    return parsed
      .filter(
        (review): review is Partial<FocusReviewSnapshot> & Pick<FocusReviewSnapshot, "endedAt"> =>
          typeof review === "object" &&
          review !== null &&
          typeof review.endedAt === "number",
      )
      .map((review) => normalizeFocusReviewSnapshot(review))
      .sort((a, b) => b.endedAt - a.endedAt)
      .slice(0, FOCUS_REVIEW_HISTORY_LIMIT);
  } catch {
    return [];
  }
}

function persistFocusReviewHistory(history: FocusReviewSnapshot[]) {
  if (typeof window === "undefined") return;

  try {
    window.localStorage.setItem(
      FOCUS_REVIEW_HISTORY_STORAGE_KEY,
      JSON.stringify(history.slice(0, FOCUS_REVIEW_HISTORY_LIMIT)),
    );
  } catch {
    // ignore storage issues
  }
}

const storedFocusReviewHistory = loadStoredFocusReviewHistory();
const latestStoredFocusReview = storedFocusReviewHistory[0] ?? null;

export const useFocusStore = create<FocusStore>((set, get) => ({
  focusActive:      false,
  focusStartTime:   null,
  focusReturnPath:  null,
  focusReviewHistory: storedFocusReviewHistory,
  lastFocusReview:  latestStoredFocusReview,
  selectedFocusReviewId: latestStoredFocusReview?.id ?? null,

  workTimerRunning: false,
  workTimerStart:   null,
  workTimerElapsed: 0,

  taskCompletions:    [],
  lastCompletionTime: null,

  startFocusMode: () => {
    playFocusChime();
    set({
      focusActive:      true,
      focusStartTime:   Date.now(),
      focusReturnPath:  get().focusReturnPath,
      selectedFocusReviewId: null,
      workTimerRunning: false,
      workTimerStart:   null,
      workTimerElapsed: 0,
      taskCompletions:  [],
      lastCompletionTime: null,
    });
  },

  endFocusMode: () => {
    set({
      focusActive:      false,
      focusStartTime:   null,
      focusReturnPath:  null,
      selectedFocusReviewId: null,
      workTimerRunning: false,
      workTimerStart:   null,
      workTimerElapsed: 0,
      taskCompletions:  [],
      lastCompletionTime: null,
    });
  },

  completeFocusMode: (activeTeamId) => {
    const {
      focusStartTime,
      taskCompletions,
      workTimerElapsed,
      workTimerRunning,
      workTimerStart,
    } = get();

    const endedAt = Date.now();
    const workDuration =
      workTimerRunning && workTimerStart
        ? workTimerElapsed + (endedAt - workTimerStart)
        : workTimerElapsed;

    const focusDuration = focusStartTime ? endedAt - focusStartTime : 0;
    const reviewSnapshot: FocusReviewSnapshot = {
      activeTeamId,
      completedTasks: taskCompletions,
      endedAt,
      focusDuration,
      id: `focus-review-${endedAt}`,
      startedAt: focusStartTime,
      workDuration,
    };
    const nextReviewHistory = [
      reviewSnapshot,
      ...get().focusReviewHistory.filter((review) => review.id !== reviewSnapshot.id),
    ].slice(0, FOCUS_REVIEW_HISTORY_LIMIT);

    persistFocusReviewHistory(nextReviewHistory);

    set({
      focusActive: false,
      focusStartTime: null,
      focusReturnPath: null,
      focusReviewHistory: nextReviewHistory,
      lastFocusReview: reviewSnapshot,
      selectedFocusReviewId: reviewSnapshot.id,
      workTimerRunning: false,
      workTimerStart: null,
      workTimerElapsed: 0,
      taskCompletions: [],
      lastCompletionTime: null,
    });
  },

  clearFocusReview: () => set({ selectedFocusReviewId: null }),
  openFocusReview: (reviewId) => set({ selectedFocusReviewId: reviewId }),
  setFocusReturnPath: (path) => set({ focusReturnPath: path }),

  startWorkTimer: () => {
    if (get().workTimerRunning) return;
    set({ workTimerRunning: true, workTimerStart: Date.now() });
  },

  pauseWorkTimer: () => {
    const { workTimerRunning, workTimerStart, workTimerElapsed } = get();
    if (!workTimerRunning || !workTimerStart) return;
    const elapsed = workTimerElapsed + (Date.now() - workTimerStart);
    set({ workTimerRunning: false, workTimerStart: null, workTimerElapsed: elapsed });
  },

  resetWorkTimer: () => {
    set({
      workTimerRunning:   false,
      workTimerStart:     null,
      workTimerElapsed:   0,
      taskCompletions:    [],
      lastCompletionTime: null,
    });
  },

  recordTaskCompletion: (taskId: string, taskTitle: string) => {
    // Always record — completing a task before the work timer is ever
    // started must not be silently dropped from the session review.
    const { workTimerStart, lastCompletionTime } = get();

    const now   = Date.now();
    const since = lastCompletionTime ?? workTimerStart;
    const delta = since ? now - since : 0;

    const completion: TaskCompletion = {
      taskId,
      taskTitle,
      completedAt: now,
      delta,
    };

    set((s) => ({
      taskCompletions:    [...s.taskCompletions, completion],
      lastCompletionTime: now,
    }));
  },
}));

/* ── Sound ────────────────────────────────────────────────────────────────── */

function playFocusChime() {
  if (typeof window === "undefined") return;
  try {
    const Ctor =
      (window as Window & typeof globalThis & { webkitAudioContext?: typeof AudioContext })
        .AudioContext ?? (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext;
    if (!Ctor) return;
    const ctx = new Ctor();
    // Must resume() first — new contexts start suspended in Chrome 66+
    void ctx.resume().then(() => {
      // Ascending major arpeggio: C5 → E5 → G5 → C6
      [523.25, 659.25, 783.99, 1046.5].forEach((freq, i) => {
        const osc  = ctx.createOscillator();
        const gain = ctx.createGain();
        osc.connect(gain);
        gain.connect(ctx.destination);
        osc.type = "sine";
        osc.frequency.value = freq;
        const t = ctx.currentTime + i * 0.13;
        gain.gain.setValueAtTime(0, t);
        gain.gain.linearRampToValueAtTime(0.12, t + 0.04);
        gain.gain.exponentialRampToValueAtTime(0.001, t + 0.7);
        osc.start(t);
        osc.stop(t + 0.7);
      });
    }).catch(() => {});
  } catch {
    /* AudioContext blocked by browser policy — silently skip */
  }
}

/* ── Helpers ──────────────────────────────────────────────────────────────── */

/** Get total work timer elapsed ms (including current running segment) */
export function getWorkElapsed(store: Pick<FocusStore, "workTimerRunning" | "workTimerStart" | "workTimerElapsed">, now: number): number {
  if (store.workTimerRunning && store.workTimerStart) {
    return store.workTimerElapsed + (now - store.workTimerStart);
  }
  return store.workTimerElapsed;
}

/** Format milliseconds to HH:MM:SS or MM:SS */
export function fmtMs(ms: number, forceHours = false): string {
  const totalSecs = Math.floor(ms / 1000);
  const h  = Math.floor(totalSecs / 3600);
  const m  = Math.floor((totalSecs % 3600) / 60);
  const s  = totalSecs % 60;
  const mm = m.toString().padStart(2, "0");
  const ss = s.toString().padStart(2, "0");
  if (h > 0 || forceHours) return `${h}:${mm}:${ss}`;
  return `${mm}:${ss}`;
}

/** Format delta ms to short readable string, e.g. "3m 12s" or "1h 4m" */
export function fmtDelta(ms: number): string {
  const totalSecs = Math.floor(ms / 1000);
  const h = Math.floor(totalSecs / 3600);
  const m = Math.floor((totalSecs % 3600) / 60);
  const s = totalSecs % 60;
  if (h > 0) return `${h}h ${m}m`;
  if (m > 0) return `${m}m ${s}s`;
  return `${s}s`;
}
