<?php

declare(strict_types=1);

namespace OCA\Mitgliederverwaltung\Service;

use DateTime;
use OCA\Mitgliederverwaltung\Db\MemberMapper;
use OCP\DB\Exception;
use OCP\IConfig;

/**
 * Service for detecting membership milestones (Jubilaeen).
 *
 * Identifies members reaching configured membership duration thresholds
 * (e.g., 25, 50, 60, 70 years) in a given year.
 *
 * Part of Issue #59.
 */
class MilestoneService {

    private const APP_ID = 'mitgliederverwaltung';
    private const DEFAULT_THRESHOLDS = '10,25,40,50,60,70';

    private MemberMapper $memberMapper;
    private IConfig $config;

    public function __construct(
        MemberMapper $memberMapper,
        IConfig $config
    ) {
        $this->memberMapper = $memberMapper;
        $this->config = $config;
    }

    /**
     * Get upcoming milestones for a given year.
     *
     * For each active member, calculates membership duration in the target year.
     * If the duration matches a configured threshold, it's included.
     *
     * @param int $year The year to check milestones for
     * @param bool $includeInactive Include inactive members
     * @return array[] List of milestone entries
     * @throws Exception
     */
    public function getUpcomingMilestones(int $year, bool $includeInactive = false): array {
        $thresholds = $this->getThresholds();
        $members = $this->memberMapper->findAll(null, null, false);

        $milestones = [];

        foreach ($members as $member) {
            if (!$includeInactive && $member->getStatus() !== 'aktiv') {
                continue;
            }

            $eintritt = $member->getEintritt();
            if ($eintritt === null || $eintritt === '') {
                continue;
            }

            try {
                $eintrittDate = new DateTime($eintritt);
                $eintrittYear = (int)$eintrittDate->format('Y');
            } catch (\Exception $e) {
                continue;
            }

            $membershipYears = $year - $eintrittYear;

            if ($membershipYears > 0 && in_array($membershipYears, $thresholds, true)) {
                // The anniversary date is the Eintritt date in the milestone year
                $milestoneDate = $eintrittDate->format('m-d');

                $milestones[] = [
                    'memberId' => $member->getId(),
                    'vorname' => $member->getVorname(),
                    'nachname' => $member->getNachname(),
                    'eintritt' => $eintritt,
                    'mitgliedsjahre' => $membershipYears,
                    'jubilaeumDatum' => $year . '-' . $milestoneDate,
                    'status' => $member->getStatus(),
                ];
            }
        }

        // Sort by milestone date
        usort($milestones, function ($a, $b) {
            return strcmp($a['jubilaeumDatum'], $b['jubilaeumDatum']);
        });

        return $milestones;
    }

    /**
     * Get configured milestone thresholds.
     *
     * @return int[]
     */
    public function getThresholds(): array {
        $value = $this->config->getAppValue(
            self::APP_ID,
            'milestone_thresholds',
            self::DEFAULT_THRESHOLDS
        );

        return array_map('intval', array_filter(
            explode(',', $value),
            fn($v) => is_numeric(trim($v))
        ));
    }

    /**
     * Set milestone thresholds.
     *
     * @param int[] $thresholds Array of year values
     */
    public function setThresholds(array $thresholds): void {
        $filtered = array_filter($thresholds, fn($v) => is_numeric($v) && (int)$v > 0);
        sort($filtered);
        $this->config->setAppValue(
            self::APP_ID,
            'milestone_thresholds',
            implode(',', $filtered)
        );
    }
}
