package main

import (
    "log"
    "time"

    "github.com/robfig/cron/v3"
)

// initScheduler creates and starts the background cron jobs responsible for
// peer lifecycle automation: expiry deletion, data-limit restriction, and monthly resets.
func initScheduler() *cron.Cron {
    c := cron.New(cron.WithSeconds())

    // 2:00 AM daily - Delete expired peers
    if _, err := c.AddFunc("0 0 2 * * *", deleteExpiredPeers); err != nil {
        log.Printf("scheduler: failed to schedule deleteExpiredPeers: %v", err)
    }

    // 3:00 AM daily - Disable peers that exceeded data limit
    if _, err := c.AddFunc("0 0 3 * * *", restrictOverLimitPeers); err != nil {
        log.Printf("scheduler: failed to schedule restrictOverLimitPeers: %v", err)
    }

    // 1st day of every month at 00:00 - Reset data usage counters
    if _, err := c.AddFunc("0 0 0 1 * *", resetMonthlyUsage); err != nil {
        log.Printf("scheduler: failed to schedule resetMonthlyUsage: %v", err)
    }

    c.Start()
    log.Println("scheduler: started background jobs (expiry, data-limit, monthly reset)")
    return c
}

// deleteExpiredPeers removes peers whose ExpiresAt is non-zero and in the past.
func deleteExpiredPeers() {
    now := time.Now()
    var peers []Peer
    if err := db.Where("expires_at != 0 AND expires_at <= ?", now).Find(&peers).Error; err != nil {
        log.Printf("scheduler: error querying expired peers: %v", err)
        return
    }
    if len(peers) == 0 {
        log.Println("scheduler: no expired peers to delete")
        return
    }
    for _, p := range peers {
        if err := db.Delete(&p).Error; err != nil {
            log.Printf("scheduler: failed to delete peer %d: %v", p.ID, err)
        } else {
            log.Printf("scheduler: deleted expired peer %d", p.ID)
        }
    }
}

// restrictOverLimitPeers disables peers that have exceeded their data limit.
func restrictOverLimitPeers() {
    var peers []Peer
    if err := db.Find(&peers).Error; err != nil {
        log.Printf("scheduler: error loading peers for restriction: %v", err)
        return
    }
    for _, p := range peers {
        if p.Enabled && p.DataLimitGB > 0 {
            limitBytes := p.DataLimitGB * 1_000_000_000
            if p.CurrentDataUsageBytes >= limitBytes {
                p.Enabled = false
                if err := db.Save(&p).Error; err != nil {
                    log.Printf("scheduler: failed to disable peer %d: %v", p.ID, err)
                } else {
                    log.Printf("scheduler: disabled peer %d due to data limit (%d/%d bytes)", p.ID, p.CurrentDataUsageBytes, limitBytes)
                }
            }
        }
    }
}

// resetMonthlyUsage resets all peers' CurrentDataUsageBytes to zero at the start of each month.
func resetMonthlyUsage() {
    var peers []Peer
    if err := db.Find(&peers).Error; err != nil {
        log.Printf("scheduler: error loading peers for monthly reset: %v", err)
        return
    }
    for _, p := range peers {
        if p.CurrentDataUsageBytes != 0 {
            p.CurrentDataUsageBytes = 0
            if err := db.Save(&p).Error; err != nil {
                log.Printf("scheduler: failed to reset usage for peer %d: %v", p.ID, err)
            } else {
                log.Printf("scheduler: reset monthly usage for peer %d", p.ID)
            }
        }
    }
}
