<?php

namespace App\Console\Commands\Migrations;

use App\Models\ProjectCharterDeliverable;
use App\Models\ProjectCharterTask;
use Illuminate\Support\Facades\DB;

class ProjectCharterTaskMigration extends BaseMigration
{
    protected string $oldTableName = 'sek_project_tasks';

    protected string $modelName = 'Project Charter Tasks';

    public function migrate(bool $dryRun = false, int $batchSize = 1000, int $startFrom = 0): void
    {
        $oldDb = DB::connection($this->connection);
        $this->processData($oldDb, $dryRun, $startFrom, $batchSize);

        // After migrating child tasks, clean up auto-generated tasks for deliverables that now have real tasks
        if (! $dryRun) {
            $this->cleanupAutoGeneratedTasks();
        }
    }

    protected function getModelName(): string
    {
        return 'Project Charter Task';
    }

    protected function getModelClass(): string
    {
        return 'App\\Models\\ProjectCharterTask';
    }

    protected function mapData(object $oldRecord): array
    {
        // Find the corresponding deliverable by matching report names
        $deliverable = $this->findMatchingDeliverable($oldRecord);

        if (! $deliverable) {
            return [];
        }

        return [
            'id' => $oldRecord->id,
            'name' => $oldRecord->task_name,
            'description' => $oldRecord->task_description,
            'start_date' => $this->parseDate($oldRecord->start_date),
            'end_date' => $this->parseDate($oldRecord->end_date),
            'estimated_cost' => $oldRecord->estimated_cost,
            'actual_cost' => $oldRecord->actual_cost,
            'progress_percentage' => $oldRecord->completion_percentage ?? 0,
            'project_charter_deliverable_id' => $deliverable->getKey(),
            'created_by' => $oldRecord->created_by,
            'created_at' => $this->parseDateTime($oldRecord->created_at),
            'updated_at' => $this->parseDateTime($oldRecord->modified_at ?? $oldRecord->created_at),
        ];
    }

    protected function validateData(array $data): bool
    {
        return ! empty($data) &&
            ! empty($data['name']) &&
            ! empty($data['project_charter_deliverable_id']);
    }

    protected function createModel(array $data): void
    {
        // Create the task with unguarded mass assignment to preserve IDs
        ProjectCharterTask::unguarded(function () use ($data) {
            $task = ProjectCharterTask::create($data);
            $this->info("📋 Migrated project charter task ID {$task->getKey()}: {$task->name}");
        });
    }

    protected function processData($oldDb, bool $dryRun, int $startFrom, int $batchSize): void
    {
        // Only migrate child tasks (tasks with parent_task_id not null)
        $query = $oldDb->table($this->oldTableName)
            ->whereNotNull('parent_task_id')
            ->orderBy('id')
            ->offset($startFrom);

        $totalRecords = $oldDb->table($this->oldTableName)
            ->whereNotNull('parent_task_id')
            ->count();

        $this->info("📊 Found {$totalRecords} child tasks to migrate");

        if ($totalRecords === 0) {
            $this->info('✅ No child tasks to migrate');

            return;
        }

        $bar = $this->command->getOutput()->createProgressBar($totalRecords);
        $bar->start();

        $query->chunk($batchSize, function ($oldRecords) use ($dryRun, $bar) {
            foreach ($oldRecords as $oldRecord) {
                $bar->advance();

                $data = $this->mapData($oldRecord);

                if ($this->validateData($data)) {
                    try {
                        if (! $dryRun) {
                            $this->createModel($data);
                        }
                        $this->stats['migrated']++;
                    } catch (\Exception $e) {
                        $this->stats['errors']++;
                        $this->error("❌ Error creating project charter task ID {$oldRecord->id}: {$e->getMessage()}");
                    }
                } else {
                    $this->stats['skipped']++;
                    $this->warn("⚠️  Skipped project charter task ID {$oldRecord->id} (validation failed or no matching deliverable)");
                }
            }
        });

        $bar->finish();
        $this->info('');
    }

    /**
     * Find the matching deliverable by linking the task to its parent's report name
     */
    private function findMatchingDeliverable(object $childTask): ?ProjectCharterDeliverable
    {
        // Get the parent task to find the report name
        $parentTask = DB::connection($this->connection)
            ->table('sek_project_tasks')
            ->where('id', $childTask->parent_task_id)
            ->first();

        if (! $parentTask) {
            $this->warn("⚠️  Parent task not found for child task ID: {$childTask->id}");

            return null;
        }

        // Extract the report name from parent task name
        // Parent task name format: "{report_name} مهمة لتقرير"
        $reportName = str_replace(' مهمة لتقرير', '', $parentTask->task_name);

        // Find the deliverable with matching name
        // Deliverable name should be the same as the report name
        $deliverable = ProjectCharterDeliverable::where('name', $reportName)->first();

        if (! $deliverable) {
            $this->warn("⚠️  No deliverable found with name matching report: '{$reportName}' for task ID: {$childTask->id}");

            return null;
        }

        return $deliverable;
    }

    /**
     * Clean up auto-generated tasks for deliverables that now have migrated child tasks
     */
    private function cleanupAutoGeneratedTasks(): void
    {
        $this->info('🧹 Cleaning up auto-generated tasks for deliverables with migrated child tasks...');

        $deletedCount = 0;

        // Get all deliverable names that have real (non-auto-generated) tasks
        $deliverableNamesWithRealTasks = ProjectCharterTask::whereHas('deliverable')
            ->where('name', 'NOT LIKE', 'مهمة لتقرير:%')
            ->with('deliverable')
            ->get()
            ->pluck('deliverable.name')
            ->unique();

        $this->info('📋 Found deliverable names with real tasks: '.$deliverableNamesWithRealTasks->implode(', '));

        // For each deliverable name that has real tasks
        foreach ($deliverableNamesWithRealTasks as $deliverableName) {
            // Get the latest deliverable instance for this name
            $latestDeliverable = ProjectCharterDeliverable::where('name', $deliverableName)
                ->orderBy('id', 'desc')
                ->first();

            if (! $latestDeliverable) {
                continue;
            }

            // Move all real tasks for this deliverable name to the latest deliverable instance
            $realTasks = ProjectCharterTask::whereHas('deliverable', function ($query) use ($deliverableName) {
                $query->where('name', $deliverableName);
            })->where('name', 'NOT LIKE', 'مهمة لتقرير:%')->get();

            foreach ($realTasks as $task) {
                $task->project_charter_deliverable_id = $latestDeliverable->id;
                $task->save();
                $this->info("📋 Moved real task '{$task->name}' to latest deliverable instance ID {$latestDeliverable->id}");
            }

            // Now delete ALL auto-generated tasks for this deliverable name
            $autoGeneratedTaskName = "مهمة لتقرير: {$deliverableName}";
            $autoGeneratedTasks = ProjectCharterTask::where('name', $autoGeneratedTaskName)->get();

            foreach ($autoGeneratedTasks as $task) {
                $task->delete();
                $deletedCount++;
                $this->info("🗑️  Deleted auto-generated task: {$task->name}");
            }
        }

        if ($deletedCount === 0) {
            $this->info('✅ No auto-generated tasks needed to be cleaned up');
        } else {
            $this->info("✅ Cleanup completed: {$deletedCount} auto-generated tasks removed");
        }
    }
}
