<?php

namespace App\Jobs;

use App\Models\Feature;
use App\Models\Phase;
use App\Models\ProgressSnapshot;
use App\Models\Task;
use Carbon\Carbon;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Log;

class CaptureDailyProgressSnapshot implements ShouldQueue
{
    use Queueable;

    public function __construct(
        public ?string $snapshotDate = null
    ) {}

    public function handle(): void
    {
        $date = $this->snapshotDate ? Carbon::parse($this->snapshotDate) : Carbon::today();

        Log::info('Starting daily progress snapshot capture', ['date' => $date->toDateString()]);

        $captured = 0;

        // Capture Phase snapshots
        $captured += $this->capturePhaseSnapshots($date);

        // Capture Feature snapshots
        $captured += $this->captureFeatureSnapshots($date);

        // Capture Task snapshots
        $captured += $this->captureTaskSnapshots($date);

        Log::info('Daily progress snapshot capture completed', [
            'date' => $date->toDateString(),
            'snapshots_captured' => $captured,
        ]);
    }

    private function capturePhaseSnapshots(Carbon $date): int
    {
        $count = 0;

        Phase::with(['project'])->chunkById(100, function ($phases) use ($date, &$count) {
            foreach ($phases as $phase) {
                // Skip if snapshot already exists for this date
                if (ProgressSnapshot::where('trackable_type', Phase::class)
                    ->where('trackable_id', $phase->id)
                    ->where('snapshot_date', $date)
                    ->exists()) {
                    continue;
                }

                $metadata = [
                    'project_id' => $phase->project_id,
                    'spi' => $phase->spi,
                    'is_on_track' => $phase->is_on_track,
                    'deviation_days' => $phase->deviation_days,
                    'start_deviation_days' => $phase->start_deviation_days,
                ];

                ProgressSnapshot::create([
                    'trackable_type' => Phase::class,
                    'trackable_id' => $phase->id,
                    'snapshot_date' => $date,
                    'progress' => $phase->progress_percent,
                    'planned_start' => $phase->planned_start,
                    'planned_end' => $phase->planned_end,
                    'actual_start' => $phase->actual_start,
                    'actual_end' => $phase->actual_end,
                    'method' => 'manual',
                    'metadata' => $metadata,
                ]);

                $count++;
            }
        });

        return $count;
    }

    private function captureFeatureSnapshots(Carbon $date): int
    {
        $count = 0;

        Feature::with(['layer.phase.project'])->chunkById(200, function ($features) use ($date, &$count) {
            foreach ($features as $feature) {
                if (ProgressSnapshot::where('trackable_type', Feature::class)
                    ->where('trackable_id', $feature->id)
                    ->where('snapshot_date', $date)
                    ->exists()) {
                    continue;
                }

                $metadata = [
                    'project_id' => $feature->layer->phase->project_id ?? null,
                    'phase_id' => $feature->layer->phase_id ?? null,
                    'layer_id' => $feature->layer_id,
                    'spi' => $feature->spi,
                    'is_on_track' => $feature->is_on_track,
                    'deviation_days' => $feature->deviation_days,
                    'start_deviation_days' => $feature->start_deviation_days,
                    'status' => $feature->status,
                ];

                ProgressSnapshot::create([
                    'trackable_type' => Feature::class,
                    'trackable_id' => $feature->id,
                    'snapshot_date' => $date,
                    'progress' => $feature->progress,
                    'planned_start' => $feature->planned_start,
                    'planned_end' => $feature->planned_end,
                    'actual_start' => $feature->actual_start,
                    'actual_end' => $feature->actual_end,
                    'method' => 'manual',
                    'metadata' => $metadata,
                ]);

                $count++;
            }
        });

        return $count;
    }

    private function captureTaskSnapshots(Carbon $date): int
    {
        $count = 0;

        Task::with(['project', 'phase'])->chunkById(200, function ($tasks) use ($date, &$count) {
            foreach ($tasks as $task) {
                if (ProgressSnapshot::where('trackable_type', Task::class)
                    ->where('trackable_id', $task->id)
                    ->where('snapshot_date', $date)
                    ->exists()) {
                    continue;
                }

                $metadata = [
                    'project_id' => $task->project_id,
                    'phase_id' => $task->phase_id,
                    'status' => $task->status,
                    'priority' => $task->priority,
                    'assigned_to' => $task->assigned_to,
                    'is_overdue' => $task->is_overdue,
                    'estimated_hours' => $task->estimated_hours,
                    'actual_hours' => $task->actual_hours,
                ];

                ProgressSnapshot::create([
                    'trackable_type' => Task::class,
                    'trackable_id' => $task->id,
                    'snapshot_date' => $date,
                    'progress' => $task->progress,
                    'planned_start' => $task->start_date,
                    'planned_end' => $task->due_date,
                    'actual_start' => $task->start_date,
                    'actual_end' => $task->completed_at?->toDateString(),
                    'method' => 'task',
                    'metadata' => $metadata,
                ]);

                $count++;
            }
        });

        return $count;
    }
}
