/**
 * Scheduler tipo cron para Alpha.
 *
 * Las tareas se ejecutan solo cuando la app está abierta (web app).
 * En RUMBO (Tauri) esto se vuelve un proceso en segundo plano real.
 */

import Dexie, { type EntityTable } from 'dexie'

interface ScheduleRule {
  id?: number
  name: string
  description?: string
  /** 0=dom, 1=lun, ..., 6=sáb */
  daysOfWeek: number[]
  /** 0-23 */
  hour: number
  /** 0-59 */
  minute: number
  action: ScheduleAction
  enabled: boolean
  lastRun: string | null
  createdAt: string
}

type ScheduleAction =
  | { type: 'generate_progress_report' }
  | { type: 'check_hus' }
  | { type: 'daily_prep' }
  | { type: 'reminder'; message: string }

interface ExecutionLog {
  id?: number
  ruleId: number
  ruleName: string
  executedAt: string
  success: boolean
  message: string
}

const db = new Dexie('alpha-scheduler') as Dexie & {
  rules: EntityTable<ScheduleRule, 'id'>
  logs: EntityTable<ExecutionLog, 'id'>
}

db.version(1).stores({
  rules: '++id, enabled, hour, minute',
  logs: '++id, ruleId, executedAt',
})

export { db }
export type { ScheduleRule, ScheduleAction, ExecutionLog }

// ─── Engine ─────────────────────────────────────────────────

type Subscriber = (ruleId: number, message: string) => void

let intervalId: ReturnType<typeof setInterval> | null = null
let subscribers: Subscriber[] = []

function now(): string {
  return new Date().toISOString()
}

function matchesRule(rule: ScheduleRule, date: Date): boolean {
  if (!rule.enabled) return false
  if (!rule.daysOfWeek.includes(date.getDay())) return false
  if (rule.hour !== date.getHours()) return false
  if (rule.minute !== date.getMinutes()) return false
  return true
}

async function executeRule(rule: ScheduleRule): Promise<string> {
  const projectNames: string[] = [] // se llenará del store

  switch (rule.action.type) {
    case 'generate_progress_report':
      return `📊 Informe de avance generado para ${projectNames.length || 'todos los'} proyectos.`

    case 'check_hus': {
      // En la iteración real consulta KAPPA API
      return `🎫 HUs revisadas. ${projectNames.length || 'N'} proyectos actualizados.`
    }

    case 'daily_prep':
      return `📋 Daily prep: recordatorio de revisar HUs pendientes y bloqueos para hoy.`

    case 'reminder':
      return `⏰ ${rule.action.message}`

    default:
      return `✅ Tarea "${rule.name}" ejecutada.`
  }
}

async function runRule(rule: ScheduleRule) {
  let success = true
  let message = ''
  try {
    message = await executeRule(rule)
  } catch (e: any) {
    success = false
    message = e.message
  }

  await db.rules.update(rule.id!, { lastRun: now() })
  await db.logs.add({
    ruleId: rule.id!,
    ruleName: rule.name,
    executedAt: now(),
    success,
    message,
  })

  for (const sub of subscribers) {
    sub(rule.id!, message)
  }
}

async function tick() {
  const date = new Date()
  const rules = await db.rules.where('enabled').equals(1).toArray()
  for (const rule of rules) {
    if (matchesRule(rule, date)) {
      await runRule(rule)
    }
  }
}

export function startScheduler() {
  if (intervalId) return
  tick() // ejecutar inmediatamente por si acaba de pasar el minuto
  intervalId = setInterval(tick, 60_000) // cada minuto
}

export function stopScheduler() {
  if (intervalId) {
    clearInterval(intervalId)
    intervalId = null
  }
}

export function onScheduledTask(cb: Subscriber) {
  subscribers.push(cb)
  return () => {
    subscribers = subscribers.filter(s => s !== cb)
  }
}

// ─── Helpers ────────────────────────────────────────────────

export function computeNextRun(rule: ScheduleRule): Date | null {
  if (!rule.enabled || rule.daysOfWeek.length === 0) return null

  const now = new Date()
  const candidate = new Date(now)
  candidate.setHours(rule.hour, rule.minute, 0, 0)

  // Buscar el próximo día que coincida
  for (let i = 0; i < 8; i++) {
    const check = new Date(candidate)
    check.setDate(check.getDate() + i)

    if (rule.daysOfWeek.includes(check.getDay())) {
      if (check > now) return check
    }
  }
  return null
}

export const DAY_LABELS = ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb']

export const DEFAULT_RULES: Omit<ScheduleRule, 'id' | 'createdAt' | 'lastRun'>[] = [
  {
    name: 'Informe semanal de avance',
    description: 'Genera un resumen de estado de cada proyecto activo',
    daysOfWeek: [5], // viernes
    hour: 9,
    minute: 0,
    action: { type: 'generate_progress_report' },
    enabled: true,
  },
  {
    name: 'Revisión de HUs pendientes',
    description: 'Revisa HUs en progreso, bloqueadas y vencidas en todos los proyectos',
    daysOfWeek: [1, 2, 3, 4, 5], // lun-vie
    hour: 8,
    minute: 0,
    action: { type: 'check_hus' },
    enabled: true,
  },
  {
    name: 'Daily prep',
    description: 'Prepara el resumen diario: qué HUs toca hoy, bloqueos, entregables próximos',
    daysOfWeek: [1, 2, 3, 4, 5],
    hour: 7,
    minute: 30,
    action: { type: 'daily_prep' },
    enabled: true,
  },
]
