// M12: Zustand-store voor idee-gerelateerde realtime state.
//
// Wordt gevoed door `use-notifications-realtime.ts` (zelfde SSE-stream als de
// notifications-bell — geen tweede EventSource nodig). Houdt:
//   - jobByIdea: live status van de actieve grill/make-plan-job per idee
//   - ideaStatuses: optimistische idea-status-updates (uit job-events)
//   - openQuestionsByIdea: open vragen voor de Timeline-tab (M12 ST-1199)
//
// connectedWorkers wordt NIET gedupliceerd — UI-componenten lezen die direct
// via `useSoloStore(s => s.connectedWorkers)` (zie M12 grill-keuze 16).

import { create } from 'zustand'

import type { ClaudeJobStatusApi } from '@/lib/job-status'
import type { IdeaStatusApi } from '@/lib/idea-status'

export type IdeaJobKind = 'IDEA_GRILL' | 'IDEA_MAKE_PLAN'

export interface IdeaJobState {
  job_id: string
  idea_id: string
  kind: IdeaJobKind
  status: ClaudeJobStatusApi
  error?: string
  started_at?: string | null
  finished_at?: string | null
}

export interface IdeaQuestion {
  id: string
  idea_id: string
  question: string
  options: string[] | null
  status: 'open' | 'answered' | 'cancelled' | 'expired'
  answer?: string | null
  created_at: string
  expires_at: string
}

export type IdeaJobEvent =
  | {
      type: 'claude_job_enqueued'
      job_id: string
      idea_id: string
      user_id: string
      product_id?: string | null
      kind: IdeaJobKind
      status: 'queued'
    }
  | {
      type: 'claude_job_status'
      job_id: string
      idea_id: string
      user_id: string
      product_id?: string | null
      kind: IdeaJobKind
      status: ClaudeJobStatusApi
      error?: string
    }

export type IdeaQuestionEvent = {
  op: 'I' | 'U'
  entity: 'question'
  id: string
  product_id: string
  story_id: null
  idea_id: string
  task_id?: string | null
  assignee_id?: string | null
  status: 'open' | 'answered' | 'cancelled' | 'expired'
}

interface IdeaStore {
  jobByIdea: Record<string, IdeaJobState | undefined>
  ideaStatuses: Record<string, IdeaStatusApi | undefined>
  openQuestionsByIdea: Record<string, IdeaQuestion[]>

  // Bulk-init bij mount van een page (server-component → client hydration).
  initJobs: (jobs: IdeaJobState[]) => void
  initStatuses: (statuses: Record<string, IdeaStatusApi>) => void
  initQuestions: (ideaId: string, questions: IdeaQuestion[]) => void

  // Realtime event handlers — aangeroepen door use-notifications-realtime.
  handleIdeaJobEvent: (event: IdeaJobEvent) => void
  handleIdeaQuestionEvent: (event: IdeaQuestionEvent) => void

  // Optimistic updates vanuit server-actions in client-components.
  setIdeaStatus: (ideaId: string, status: IdeaStatusApi) => void
  setJobStatus: (job: IdeaJobState) => void

  // Cleanup bij navigeren weg van een detail-pagina.
  clearForIdea: (ideaId: string) => void
}

// Mapping van een job-status (uit pg_notify event) naar een afgeleide
// idea-status. De server is de bron-van-waarheid; dit is alleen optimistic UI.
function deriveIdeaStatusFromJob(
  kind: IdeaJobKind,
  status: ClaudeJobStatusApi,
): IdeaStatusApi | null {
  if (status === 'queued' || status === 'claimed' || status === 'running') {
    return kind === 'IDEA_GRILL' ? 'grilling' : 'planning'
  }
  if (status === 'failed') {
    return kind === 'IDEA_GRILL' ? 'grill_failed' : 'plan_failed'
  }
  // 'done' wordt door update_idea_*_md gezet (GRILLED resp. PLAN_READY) —
  // daar is geen kind-onafhankelijke afleiding voor; lees de DB-update via
  // re-fetch / page-revalidate. We laten de status hier ongemoeid.
  return null
}

export const useIdeaStore = create<IdeaStore>((set) => ({
  jobByIdea: {},
  ideaStatuses: {},
  openQuestionsByIdea: {},

  initJobs: (jobs) =>
    set(() => {
      const jobByIdea: Record<string, IdeaJobState> = {}
      for (const j of jobs) jobByIdea[j.idea_id] = j
      return { jobByIdea }
    }),

  initStatuses: (statuses) => set({ ideaStatuses: { ...statuses } }),

  initQuestions: (ideaId, questions) =>
    set((s) => ({
      openQuestionsByIdea: { ...s.openQuestionsByIdea, [ideaId]: questions },
    })),

  handleIdeaJobEvent: (event) =>
    set((s) => {
      const jobState: IdeaJobState = {
        job_id: event.job_id,
        idea_id: event.idea_id,
        kind: event.kind,
        status: event.status as ClaudeJobStatusApi,
        error: 'error' in event ? event.error : undefined,
      }
      const derived = deriveIdeaStatusFromJob(event.kind, event.status as ClaudeJobStatusApi)
      return {
        jobByIdea: { ...s.jobByIdea, [event.idea_id]: jobState },
        ideaStatuses:
          derived !== null
            ? { ...s.ideaStatuses, [event.idea_id]: derived }
            : s.ideaStatuses,
      }
    }),

  handleIdeaQuestionEvent: (event) =>
    set((s) => {
      const list = s.openQuestionsByIdea[event.idea_id] ?? []
      // Bij open/insert: we hebben alleen status + id; de UI fetcht de
      // detail bij re-render. Voor v1 markeren we 'm in de lijst zodat de
      // count niet uit sync raakt.
      let next = list
      if (event.status !== 'open') {
        next = list.filter((q) => q.id !== event.id)
      }
      return {
        openQuestionsByIdea: { ...s.openQuestionsByIdea, [event.idea_id]: next },
      }
    }),

  setIdeaStatus: (ideaId, status) =>
    set((s) => ({ ideaStatuses: { ...s.ideaStatuses, [ideaId]: status } })),

  setJobStatus: (job) =>
    set((s) => ({ jobByIdea: { ...s.jobByIdea, [job.idea_id]: job } })),

  clearForIdea: (ideaId) =>
    set((s) => {
      const { [ideaId]: _j, ...jobByIdea } = s.jobByIdea
      const { [ideaId]: _s, ...ideaStatuses } = s.ideaStatuses
      const { [ideaId]: _q, ...openQuestionsByIdea } = s.openQuestionsByIdea
      void _j
      void _s
      void _q
      return { jobByIdea, ideaStatuses, openQuestionsByIdea }
    }),
}))
