<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('loan_products', function (Blueprint $table): void {
            $table->string('loan_number_prefix', 20)->default('LON')->after('description');
            $table->unsignedInteger('term_value')->default(1)->after('repayment_frequency');
            $table->string('term_unit', 20)->default('months')->after('term_value');
            $table->string('penalty_type', 20)->default('percentage')->after('penalty_rate');
            $table->string('processing_fee_type', 20)->default('fixed')->after('penalty_type');
            $table->decimal('processing_fee_value', 14, 2)->default(0)->after('processing_fee_type');
            $table->string('guarantor_requirement', 20)->default('optional')->after('maximum_amount');
            $table->string('collateral_requirement', 20)->default('optional')->after('guarantor_requirement');
        });

        Schema::table('loans', function (Blueprint $table): void {
            $table->string('interest_method', 40)->default('flat')->after('interest_rate');
            $table->decimal('processing_fee', 14, 2)->default(0)->after('interest_amount');
            $table->unsignedInteger('term_value')->default(1)->after('term_days');
            $table->string('term_unit', 20)->default('months')->after('term_value');
            $table->date('first_repayment_date')->nullable()->after('application_date');
        });

        Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
            $table->decimal('fee_due', 14, 2)->default(0)->after('interest_due');
        });

        Schema::table('loan_payments', function (Blueprint $table): void {
            $table->decimal('fee_component', 14, 2)->default(0)->after('interest_component');
        });

        DB::table('loan_products')
            ->select(['id', 'term_days'])
            ->orderBy('id')
            ->get()
            ->each(function ($product): void {
                [$termValue, $termUnit] = $this->termParts((int) $product->term_days);

                DB::table('loan_products')
                    ->where('id', $product->id)
                    ->update([
                        'term_value' => $termValue,
                        'term_unit' => $termUnit,
                    ]);
            });

        DB::table('loans')
            ->select(['id', 'term_days'])
            ->orderBy('id')
            ->get()
            ->each(function ($loan): void {
                [$termValue, $termUnit] = $this->termParts((int) $loan->term_days);

                DB::table('loans')
                    ->where('id', $loan->id)
                    ->update([
                        'term_value' => $termValue,
                        'term_unit' => $termUnit,
                    ]);
            });
    }

    public function down(): void
    {
        Schema::table('loan_payments', function (Blueprint $table): void {
            $table->dropColumn('fee_component');
        });

        Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
            $table->dropColumn('fee_due');
        });

        Schema::table('loans', function (Blueprint $table): void {
            $table->dropColumn(['interest_method', 'processing_fee', 'term_value', 'term_unit', 'first_repayment_date']);
        });

        Schema::table('loan_products', function (Blueprint $table): void {
            $table->dropColumn([
                'loan_number_prefix',
                'term_value',
                'term_unit',
                'penalty_type',
                'processing_fee_type',
                'processing_fee_value',
                'guarantor_requirement',
                'collateral_requirement',
            ]);
        });
    }

    private function termParts(int $termDays): array
    {
        return match (true) {
            $termDays > 0 && $termDays % 365 === 0 => [(int) ($termDays / 365), 'years'],
            $termDays > 0 && $termDays % 30 === 0 => [(int) ($termDays / 30), 'months'],
            $termDays > 0 && $termDays % 7 === 0 => [(int) ($termDays / 7), 'weeks'],
            default => [max(1, $termDays), 'days'],
        };
    }
};
