<?php

declare(strict_types=1);

namespace App\Core;

use App\Shared\Schema\ChecksSchemaSupport;
use App\Shared\Schema\FinanceSchemaSupport;
use App\Shared\Schema\PartySchemaSupport;
use App\Shared\Schema\QuotationSchemaSupport;
use App\Shared\Security\RbacSupport;
use PDO;

final class AppBootstrap
{
    public static function bootLayout(PDO $pdo, bool $authenticated = false): void
    {
        RbacSupport::ensurePermissionsSeed($pdo);

        if (!$authenticated) {
            return;
        }

        SchemaRuntime::ensureMany($pdo, [
            [
                'key' => 'parties_full_schema',
                'callback' => static function () use ($pdo): void {
                    PartySchemaSupport::ensurePartiesFullSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_18_parties.sql',
            ],
            [
                'key' => 'checks_schema',
                'callback' => static function () use ($pdo): void {
                    ChecksSchemaSupport::ensureChecksSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_32_checks.sql',
            ],
        ]);
    }



    public static function bootParties(PDO $pdo): void
    {
        SchemaRuntime::ensure($pdo, 'parties_schema', static function () use ($pdo): void {
            PartySchemaSupport::ensurePartiesSchema($pdo);
        }, 'sql/migrate_v1_18_parties.sql');
    }

    public static function bootUsers(PDO $pdo): void
    {
        SchemaRuntime::ensure($pdo, 'users_cashbox_schema', static function () use ($pdo): void {
            FinanceSchemaSupport::ensureUsersCashboxSchema($pdo);
        }, 'sql/migrate_v1_28_users_cashbox.sql');
    }

    public static function bootQuotations(PDO $pdo, bool $forConversion = false): void
    {
        SchemaRuntime::ensure($pdo, 'quotations_schema', static function () use ($pdo): void {
            QuotationSchemaSupport::ensureQuotationsSchema($pdo);
        }, 'sql/migrate_v1_26_quotations.sql');

        if (!$forConversion) {
            return;
        }

        SchemaRuntime::ensureMany($pdo, [
            [
                'key' => 'sales_invoices_party_schema',
                'callback' => static function () use ($pdo): void {
                    PartySchemaSupport::ensureSalesInvoicesPartySchema($pdo);
                },
                'migration' => 'sql/migrate_v1_19_parties_links.sql',
            ],
            [
                'key' => 'party_ledger_schema',
                'callback' => static function () use ($pdo): void {
                    PartySchemaSupport::ensurePartyLedgerSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_20_party_ledger.sql',
            ],
            [
                'key' => 'cashboxes_schema',
                'callback' => static function () use ($pdo): void {
                    FinanceSchemaSupport::ensureCashboxesSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_27_cashboxes.sql',
            ],
            [
                'key' => 'sales_invoice_payment_schema',
                'callback' => static function () use ($pdo): void {
                    FinanceSchemaSupport::ensureSalesInvoicePaymentSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_31_sales_invoice_payment.sql',
            ],
        ]);
    }

    public static function bootSalesInvoices(PDO $pdo): void
    {
        SchemaRuntime::ensureMany($pdo, [
            [
                'key' => 'sales_invoices_party_schema',
                'callback' => static function () use ($pdo): void {
                    PartySchemaSupport::ensureSalesInvoicesPartySchema($pdo);
                },
                'migration' => 'sql/migrate_v1_19_parties_links.sql',
            ],
            [
                'key' => 'party_ledger_schema',
                'callback' => static function () use ($pdo): void {
                    PartySchemaSupport::ensurePartyLedgerSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_20_party_ledger.sql',
            ],
            [
                'key' => 'cashboxes_schema',
                'callback' => static function () use ($pdo): void {
                    FinanceSchemaSupport::ensureCashboxesSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_27_cashboxes.sql',
            ],
            [
                'key' => 'sales_invoice_payment_schema',
                'callback' => static function () use ($pdo): void {
                    FinanceSchemaSupport::ensureSalesInvoicePaymentSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_31_sales_invoice_payment.sql',
            ],
        ]);
    }
    public static function bootSalesReceipts(PDO $pdo, bool $withBankAccounts = false, bool $withPartyLedger = false): void
    {
        SchemaRuntime::ensureMany($pdo, [
            [
                'key' => 'customer_receipts_schema',
                'callback' => static function () use ($pdo): void {
                    FinanceSchemaSupport::ensureCustomerReceiptsSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_15_customer_receipts.sql',
            ],
            [
                'key' => 'parties_schema',
                'callback' => static function () use ($pdo): void {
                    PartySchemaSupport::ensurePartiesSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_18_parties.sql',
            ],
            [
                'key' => 'parties_migration_bridge',
                'callback' => static function () use ($pdo): void {
                    PartySchemaSupport::ensurePartiesMigrateFromCustomersSuppliers($pdo);
                },
                'migration' => 'sql/migrate_v1_18_parties.sql',
            ],
        ]);

        if ($withBankAccounts) {
            SchemaRuntime::ensure($pdo, 'bank_accounts_schema', static function () use ($pdo): void {
                FinanceSchemaSupport::ensureBankAccountsSchema($pdo);
            }, 'sql/migrate_v1_21_bank_accounts.sql');
        }

        if ($withPartyLedger) {
            SchemaRuntime::ensure($pdo, 'party_ledger_schema', static function () use ($pdo): void {
                PartySchemaSupport::ensurePartyLedgerSchema($pdo);
            }, 'sql/migrate_v1_20_party_ledger.sql');
        }
    }

    public static function bootPos(PDO $pdo): void
    {
        RbacSupport::ensurePermissionsSeed($pdo);

        SchemaRuntime::ensureMany($pdo, [
            [
                'key' => 'parties_full_schema',
                'callback' => static function () use ($pdo): void {
                    PartySchemaSupport::ensurePartiesFullSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_18_parties.sql',
            ],
            [
                'key' => 'cashboxes_schema',
                'callback' => static function () use ($pdo): void {
                    FinanceSchemaSupport::ensureCashboxesSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_27_cashboxes.sql',
            ],
            [
                'key' => 'sales_invoice_payment_schema',
                'callback' => static function () use ($pdo): void {
                    FinanceSchemaSupport::ensureSalesInvoicePaymentSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_31_sales_invoice_payment.sql',
            ],
            [
                'key' => 'users_cashbox_schema',
                'callback' => static function () use ($pdo): void {
                    FinanceSchemaSupport::ensureUsersCashboxSchema($pdo);
                },
                'migration' => 'sql/migrate_v1_28_users_cashbox.sql',
            ],
        ]);
    }

    public static function bootExpenses(PDO $pdo, bool $seedPermissions = false): void
    {
        SchemaRuntime::ensure($pdo, 'expenses_schema', static function () use ($pdo): void {
            FinanceSchemaSupport::ensureExpensesSchema($pdo);
        }, 'sql/migrate_v1_17_expenses.sql');

        if ($seedPermissions) {
            RbacSupport::ensurePermissionsSeed($pdo);
        }
    }
}
