<?php

namespace App\Console\Commands\Migrations;

use App\Models\Department;
use App\Models\PerformanceCard;
use Illuminate\Support\Facades\DB;

class PerformanceCardMigration extends BaseMigration
{
    protected string $oldTableName = 'performance_cards';

    protected string $modelName = 'Performance Cards';

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

    protected function getModelName(): string
    {
        return 'Performance Card';
    }

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

    protected function processData($oldDb, bool $dryRun = false, int $startFrom = 0, int $batchSize = 1000): void
    {
        $query = $oldDb->table($this->oldTableName)
            ->whereNotNull('id')
            ->orderBy('id');

        $totalCount = $query->count();
        $this->stats['total'] = $totalCount;

        $this->info("📊 Found {$totalCount} performance cards to migrate");

        if ($totalCount === 0) {
            $this->warn('⚠️  No performance cards found to migrate');

            return;
        }

        $processed = 0;
        $bar = $this->command->getOutput()->createProgressBar($totalCount);

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

                    try {
                        $data = $this->mapData($oldRecord);
                        if ($this->validateData($data)) {
                            if (! $dryRun) {
                                $this->createModel($data);
                            }
                            $this->stats['migrated']++;
                            $this->info("✅ Created performance card: {$data['goal']} (ID: {$data['id']})");
                        } else {
                            $this->stats['skipped']++;
                            $this->warn("⚠️  Skipped performance card ID {$oldRecord->id} (validation failed)");
                        }
                    } catch (\Exception $e) {
                        $this->stats['errors']++;
                        $this->error("❌ Error creating performance card ID {$oldRecord->id}: {$e->getMessage()}");
                    }
                }
            });

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

    protected function mapData($oldRecord): array
    {
        // Get or create department
        $departmentId = $this->getOrCreateDepartment($oldRecord->associated_department);

        return [
            'id' => $oldRecord->id,
            'goal' => $oldRecord->goal,
            'project_manner' => empty($oldRecord->project_manner)
                ? PerformanceCard::PROJECT_MANNER_DEVELOPMENTAL
                : $oldRecord->project_manner,
            'department_id' => $departmentId,
            '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
    {
        // Check if performance card with this ID already exists
        if (PerformanceCard::find($data['id'])) {
            $this->warn("⚠️  Performance card with ID {$data['id']} already exists");

            return false;
        }

        // Validate required fields
        if (empty($data['goal'])) {
            $this->warn("⚠️  Performance card ID {$data['id']} has no goal");

            return false;
        }

        if (empty($data['department_id'])) {
            $this->warn("⚠️  Performance card ID {$data['id']} has no department");

            return false;
        }

        return true;
    }

    protected function createModel(array $data): void
    {
        // Use DB transaction for each performance card creation
        DB::transaction(function () use ($data) {
            // Create using raw database insertion to preserve ID
            DB::table('performance_cards')->insert($data);
        });
    }

    /**
     * Get or create department based on the associated_department text
     */
    protected function getOrCreateDepartment(string $departmentText): ?int
    {
        if (empty($departmentText)) {
            return null;
        }

        // Clean up the department text and convert to proper name
        $departmentName = $this->formatDepartmentName($departmentText);

        // Check if department already exists
        $department = Department::where('name', $departmentName)->first();

        if (! $department) {
            // Create new department
            $department = Department::create([
                'name' => $departmentName,
                'description' => "Department migrated from legacy system: {$departmentText}",
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            $this->info("📁 Created department: {$departmentName}");
        }

        return $department->getKey();
    }

    /**
     * Format department name from legacy text
     */
    protected function formatDepartmentName(string $departmentText): string
    {
        // Convert underscore-separated text to proper department name
        $name = str_replace('_', ' ', $departmentText);
        $name = strtolower($name);
        $name = ucwords($name);

        // Handle specific department mappings if needed
        $mappings = [
            'Project Management' => 'Project Management',
            'Technical Department' => 'Technical Department',
            'Finance Department' => 'Finance Department',
            'Hr Department' => 'HR Department',
            'Operations Department' => 'Operations Department',
        ];

        return $mappings[$name] ?? $name;
    }

    public function rollback(): void
    {
        $this->info('🔄 Rolling back Performance Card migration...');

        // Get the count before deletion for reporting
        $count = PerformanceCard::count();

        // Delete all migrated performance cards
        PerformanceCard::truncate();

        // Also clean up departments that were created during migration
        $departmentCount = Department::where('description', 'like', 'Department migrated from legacy system:%')->count();
        Department::where('description', 'like', 'Department migrated from legacy system:%')->delete();

        $this->info("✅ Rolled back {$count} performance cards and {$departmentCount} departments");
    }
}
