<?php

namespace App\Console\Commands\Migrations;

use App\Models\Order;
use App\Models\OrderFinance;
use App\Models\OrderRequirement;
use Illuminate\Support\Facades\DB;

class OrderFinanceMigration extends BaseMigration
{
    protected string $oldTableName = 'sek_requests';

    protected string $modelName = 'Order Finance';

    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 'Order Finance';
    }

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

    protected function processData($oldDb, bool $dryRun = false, int $startFrom = 0, int $batchSize = 1000): void
    {
        // Get orders that have accepted requirements and financial data
        $query = $oldDb->table($this->oldTableName)
            ->select('sek_requests.*')
            ->join('sek_requirements', 'sek_requests.id', '=', 'sek_requirements.request_id')
            ->where('sek_requirements.status', 'ACCEPTED')
            ->where(function ($q) {
                $q->whereNotNull('sek_requests.count')
                    ->orWhereNotNull('sek_requests.capacity')
                    ->orWhereNotNull('sek_requests.offer_price')
                    ->orWhereNotNull('sek_requests.additional_fees')
                    ->orWhereNotNull('sek_requests.operation_cost')
                    ->orWhereNotNull('sek_requests.operation_cost_percentage')
                    ->orWhereNotNull('sek_requests.execution_duration')
                    ->orWhereNotNull('sek_requests.company_name');
            })
            ->groupBy('sek_requests.id')
            ->orderBy('sek_requests.created_at');

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

        $this->info("📊 Found {$totalCount} orders with financial data and accepted requirements to migrate");

        if ($totalCount === 0) {
            $this->warn('⚠️  No order finance records 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) {
                    try {
                        $this->processOrderFinance($oldRecord, $dryRun);
                    } catch (\Exception $e) {
                        $this->stats['errors']++;
                        $orderId = $oldRecord->id ?? 'unknown';
                        $this->error("❌ Error migrating finance for order ID {$orderId}: ".$e->getMessage());
                    }

                    $processed++;
                    $bar->advance();
                }
            });

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

    private function processOrderFinance(object $oldRecord, bool $dryRun): void
    {
        // Check if the order exists
        $order = Order::find($oldRecord->id);
        if (! $order) {
            $this->warn("⚠️  Skipping finance for order {$oldRecord->id}: Order not found");
            $this->stats['skipped']++;

            return;
        }

        // Get accepted requirements for this order
        $acceptedRequirements = OrderRequirement::where('order_id', $order->getKey())
            ->where('status', OrderRequirement::STATUS_ACCEPTED)
            ->get();

        if ($acceptedRequirements->isEmpty()) {
            $this->warn("⚠️  Skipping finance for order {$order->getKey()}: No accepted requirements found");
            $this->stats['skipped']++;

            return;
        }

        // Create finance record for each accepted requirement
        foreach ($acceptedRequirements as $requirement) {
            if ($this->shouldCreateFinanceRecord($oldRecord, $requirement, $dryRun)) {
                if (! $dryRun) {
                    $this->createFinanceRecord($order, $requirement, $oldRecord);
                    $this->stats['migrated']++;
                } else {
                    $this->info("🔍 [DRY RUN] Would create finance record for Order {$order->getKey()}, Requirement {$requirement->getKey()}");
                }
            }
        }
    }

    private function shouldCreateFinanceRecord(object $oldRecord, OrderRequirement $requirement, bool $dryRun): bool
    {
        // Check if finance record already exists
        $existingFinance = OrderFinance::where('order_id', $requirement->order_id)
            ->where('order_requirement_id', $requirement->getKey())
            ->first();

        if ($existingFinance) {
            if (! $dryRun) {
                $this->info("ℹ️  Finance record already exists for Order {$requirement->order_id}, Requirement {$requirement->getKey()}");
            }

            return false;
        }

        return true;
    }

    private function createFinanceRecord(Order $order, OrderRequirement $requirement, object $oldRecord): void
    {
        $financeData = [
            'order_id' => $order->getKey(),
            'order_requirement_id' => $requirement->getKey(),
            'count' => ! empty($oldRecord->count) ? (int) $oldRecord->count : null,
            'capacity' => ! empty($oldRecord->capacity) ? (int) $oldRecord->capacity : null,
            'execution_duration' => ! empty($oldRecord->execution_duration) ? (int) $oldRecord->execution_duration : null,
            'company_name' => $oldRecord->company_name ?? null,
            'offer_price' => ! empty($oldRecord->offer_price) ? (float) $oldRecord->offer_price : null,
            'additional_fees' => ! empty($oldRecord->additional_fees) ? (float) $oldRecord->additional_fees : null,
            'operation_cost_percentage' => ! empty($oldRecord->operation_cost_percentage) ? (float) $oldRecord->operation_cost_percentage : null,
            'operation_cost' => ! empty($oldRecord->operation_cost) ? (float) $oldRecord->operation_cost : null,
            'status' => 'pending', // Default status
            'created_by' => $order->created_by,
            'created_at' => $order->created_at,
            'updated_at' => $order->updated_at,
        ];

        try {
            OrderFinance::create($financeData);
            $this->info("💰 Created finance record for order {$order->getKey()}, requirement {$requirement->getKey()}");
        } catch (\Exception $e) {
            $this->error("❌ Failed to create finance record for order {$order->getKey()}: ".$e->getMessage());
            throw $e;
        }
    }

    protected function mapData(object $oldRecord): array
    {
        // Not used in this migration as we process data differently
        return [];
    }

    protected function validateData(array $data): bool
    {
        // Not used in this migration as we process data differently
        return true;
    }

    protected function createModel(array $data): void
    {
        // Not used in this migration as we process data differently
    }
}
