<?php

app_require('modules/goals/classes/goals_criteria.php');
app_require('modules/goals/helpers/goals_criteria_target_duration.php');
app_require('modules/goals/helpers/goals_criteria_type.php');

use goals\classes\goals_criteria;
use goals\helpers\goals_criteria_target_duration as TargetDuration;
use goals\helpers\goals_criteria_type as CriteriaType;

function goals_test_department(int $id): object
{
    $department = new stdClass();
    $department->id = $id;
    return $department;
}

it('computes weekly target using touched ISO weeks for March 2026', function (): void {
    $criteria = new goals_criteria();
    $criteria->type = CriteriaType::NONE;
    $criteria->target = 10;
    $criteria->target_duration = TargetDuration::WEEKS;
    $criteria->target_duration_every = 1;
    $criteria->start = new DateTime('2026-03-01 00:00:00');
    $criteria->end = new DateTime('2026-03-31 23:59:59');
    $criteria->departments->set([goals_test_department(12)]);
    $criteria->validateAndSanitize();

    $target = $criteria->calculateTargetForRange(
        new DateTime('2026-03-01 00:00:00'),
        new DateTime('2026-03-31 23:59:59')
    );

    expect($target)->toBe(60.0);
});

it('applies target_duration_every for weekly cadence', function (): void {
    $criteria = new goals_criteria();
    $criteria->type = CriteriaType::NONE;
    $criteria->target = 10;
    $criteria->target_duration = TargetDuration::WEEKS;
    $criteria->target_duration_every = 2;
    $criteria->start = new DateTime('2026-03-01 00:00:00');
    $criteria->end = new DateTime('2026-03-31 23:59:59');
    $criteria->departments->set([goals_test_department(12)]);
    $criteria->validateAndSanitize();

    $target = $criteria->calculateTargetForRange(
        new DateTime('2026-03-01 00:00:00'),
        new DateTime('2026-03-31 23:59:59')
    );

    expect($target)->toBe(30.0);
});

it('prorates ENTIRE_DURATION target by overlap days', function (): void {
    $criteria = new goals_criteria();
    $criteria->type = CriteriaType::NONE;
    $criteria->target = 310;
    $criteria->target_duration = TargetDuration::ENTIRE_DURATION;
    $criteria->start = new DateTime('2026-01-01 00:00:00');
    $criteria->end = new DateTime('2026-01-31 23:59:59');
    $criteria->departments->set([goals_test_department(12)]);
    $criteria->validateAndSanitize();

    $target = $criteria->calculateTargetForRange(
        new DateTime('2026-01-01 00:00:00'),
        new DateTime('2026-01-07 23:59:59')
    );

    expect($target)->toBe(70.0);
});

it('splits advanced target by override weights per department', function (): void {
    $criteria = new goals_criteria();
    $criteria->type = CriteriaType::NONE;
    $criteria->target = 10;
    $criteria->target_duration = TargetDuration::WEEKS;
    $criteria->target_duration_every = 1;
    $criteria->start = new DateTime('2026-03-01 00:00:00');
    $criteria->end = new DateTime('2026-03-31 23:59:59');
    $criteria->departments->set([goals_test_department(12), goals_test_department(15)]);
    $criteria->department_daily_targets = [12 => 3, 15 => 1];
    $criteria->validateAndSanitize();

    $dept12 = $criteria->calculateTargetForRange(
        new DateTime('2026-03-01 00:00:00'),
        new DateTime('2026-03-31 23:59:59'),
        12,
        [12, 15]
    );
    $dept15 = $criteria->calculateTargetForRange(
        new DateTime('2026-03-01 00:00:00'),
        new DateTime('2026-03-31 23:59:59'),
        15,
        [12, 15]
    );

    expect($dept12)->toBe(45.0);
    expect($dept15)->toBe(15.0);
});

it('preserves legacy target behavior when target_duration is missing', function (): void {
    $criteria = new goals_criteria();
    $criteria->type = CriteriaType::NONE;
    $criteria->target = 70;
    $criteria->start = new DateTime('first day of this month 00:00:00');
    $criteria->end = new DateTime('now');
    $criteria->departments->set([goals_test_department(12)]);
    $criteria->validateAndSanitize();

    $monthProgress = $criteria->getProgressDetails('month');
    $allProgress = $criteria->getProgressDetails();

    expect((float)$monthProgress['target'])->toBe(0.0);
    expect((float)$allProgress['target'])->toBe(70.0);
});
