<?php

namespace App\Sync;

/**
 * Central definition of every table that participates in desktop <-> server sync.
 *
 * The order of the array IS the dependency order: parents are listed before the
 * children that reference them, so applying changes top-to-bottom always resolves
 * foreign keys. Pushing/pulling walks this list forward; nothing here relies on the
 * integer primary keys, only on the per-row `sync_uuid`.
 *
 * Per-table keys:
 *  - fks:    map of local column => [parent table, hard?]. When "hard" is true a
 *            missing parent defers the row (retry after parents applied); when false
 *            (a soft/audit FK such as created_by) a missing parent is tolerated and the
 *            column is left as-is / nulled.
 *  - scope:  how the server decides which rows belong to a device's company on pull:
 *              'self'   -> the companies row whose id == company (company row itself)
 *              'company'-> table has a company_id column, filter by it
 *              'global' -> shared reference data, returned to every device
 *              ['via' => 'child_col', 'table' => 'parent'] -> scoped through a parent
 *  - owner:  'master' (reference data, usually authored on the server) or
 *            'device' (transactional data, authored on the desktop). Used only for
 *            documentation / conflict defaults; both directions still sync.
 *
 * This file is intentionally identical on the API (server) and desktop apps.
 */
class SyncRegistry
{
    public static function tables(): array
    {
        return [
            'companies' => [
                'fks'   => ['created_by' => ['users', false]],
                'scope' => 'self',
                'owner' => 'master',
                'match' => ['email'],
            ],
            'roles' => [
                'fks'   => ['company_id' => ['companies', false]],
                'scope' => 'company',
                'owner' => 'master',
                'match' => ['company_id', 'name'],
            ],
            'departments' => [
                'fks'   => [
                    'company_id' => ['companies', true],
                    'leader_id'  => ['users', false],
                    'created_by' => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'master',
                'match' => ['company_id', 'name'],
            ],
            'users' => [
                'fks'   => [
                    'company_id'    => ['companies', false],
                    'department_id' => ['departments', false],
                    'role_id'       => ['roles', false],
                    'created_by'    => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'master',
                'match' => ['email'],
            ],
            'insurances' => [
                'fks'   => [],
                'scope' => 'global',
                'owner' => 'master',
                'match' => ['name'],
            ],
            'currencies' => [
                'fks'   => [],
                'scope' => 'global',
                'owner' => 'master',
                'match' => ['name'],
            ],
            'payment_methods' => [
                'fks'   => [],
                'scope' => 'global',
                'owner' => 'master',
                'match' => ['name'],
            ],
            'units' => [
                'fks'   => [],
                'scope' => 'global',
                'owner' => 'master',
                'match' => ['name'],
            ],
            'product_categories' => [
                'fks'   => [
                    'company_id' => ['companies', true],
                    'parent_id'  => ['product_categories', false],
                    'created_by' => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'master',
                'match' => ['company_id', 'name'],
            ],
            'clients' => [
                'fks'   => [],
                'scope' => 'global',
                'owner' => 'master',
                'match' => ['name', 'phone'],
            ],
            'suppliers' => [
                'fks'   => [
                    'company_id' => ['companies', true],
                    'created_by' => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'master',
                'match' => ['company_id', 'name'],
            ],
            'products' => [
                'fks'   => [
                    'company_id'  => ['companies', true],
                    'unit_id'     => ['units', false],
                    'category_id' => ['product_categories', false],
                    'created_by'  => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'master',
                'match' => ['company_id', 'reference'],
            ],
            'product_changes' => [
                'fks'   => [
                    'product_id' => ['products', true],
                    'created_by' => ['users', false],
                ],
                'scope' => ['via' => 'product_id', 'table' => 'products'],
                'owner' => 'device',
            ],
            'stock' => [
                'fks'   => [
                    'company_id'    => ['companies', true],
                    'department_id' => ['departments', false],
                    'product_id'    => ['products', true],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'stockin_histories' => [
                'fks'   => [
                    'stockin_id' => ['stock_receives', true],
                    'product_id' => ['products', true],
                ],
                'scope' => ['via' => 'stockin_id', 'table' => 'stock_receives'],
                'owner' => 'device',
            ],
            'stock_receives' => [
                'fks'   => [
                    'company_id'  => ['companies', true],
                    'supplier_id' => ['suppliers', false],
                    'created_by'  => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'stock_transfers' => [
                'fks'   => [
                    'company_id'      => ['companies', true],
                    'department_id'   => ['departments', false],
                    'taken_by'        => ['users', false],
                    'created_by'      => ['users', false],
                    'requisition_id'  => ['requisitions', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'stock_transfer_items' => [
                'fks'   => [
                    'transfer_id' => ['stock_transfers', true],
                    'product_id'  => ['products', true],
                ],
                'scope' => ['via' => 'transfer_id', 'table' => 'stock_transfers'],
                'owner' => 'device',
            ],
            'requisitions' => [
                'fks'   => [
                    'company_id'    => ['companies', true],
                    'department_id' => ['departments', false],
                    'created_by'    => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'requisition_items' => [
                'fks'   => [
                    'requisition_id' => ['requisitions', true],
                    'product_id'     => ['products', true],
                ],
                'scope' => ['via' => 'requisition_id', 'table' => 'requisitions'],
                'owner' => 'device',
            ],
            'purchase_order' => [
                'fks'   => [
                    'company_id'  => ['companies', true],
                    'currency'    => ['currencies', false],
                    'supplier_id' => ['suppliers', false],
                    'created_by'  => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'purchase_order_items' => [
                'fks'   => [
                    'order_id'   => ['purchase_order', true],
                    'product_id' => ['products', true],
                ],
                'scope' => ['via' => 'order_id', 'table' => 'purchase_order'],
                'owner' => 'device',
            ],
            'proforma' => [
                'fks'   => [
                    'company_id' => ['companies', true],
                    'client_id'  => ['clients', false],
                    'created_by' => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'proforma_items' => [
                'fks'   => [
                    'proforma_id' => ['proforma', true],
                    'product_id'  => ['products', true],
                ],
                'scope' => ['via' => 'proforma_id', 'table' => 'proforma'],
                'owner' => 'device',
            ],
            'stock_adjustments' => [
                'fks'   => [
                    'company_id'    => ['companies', true],
                    'department_id' => ['departments', false],
                    'created_by'    => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'stock_adjustment_items' => [
                'fks'   => [
                    'adjustment_id' => ['stock_adjustments', true],
                    'product_id'    => ['products', true],
                ],
                'scope' => ['via' => 'adjustment_id', 'table' => 'stock_adjustments'],
                'owner' => 'device',
            ],
            'stock_out' => [
                'fks'   => [
                    'company_id'   => ['companies', true],
                    'insurance_id' => ['insurances', false],
                    'created_by'   => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'stockout_items' => [
                'fks'   => [
                    'stockout_id' => ['stock_out', true],
                    'product_id'  => ['products', true],
                ],
                'scope' => ['via' => 'stockout_id', 'table' => 'stock_out'],
                'owner' => 'device',
            ],
            'sales' => [
                'fks'   => [
                    'company_id'  => ['companies', false],
                    'create_user' => ['users', false],
                    'client_id'   => ['clients', false],
                    'branch_id'   => ['departments', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'sale_items' => [
                'fks'   => [
                    'sale_id' => ['sales', true],
                    'item_id' => ['products', true],
                ],
                'scope' => ['via' => 'sale_id', 'table' => 'sales'],
                'owner' => 'device',
            ],
            'payments' => [
                'fks'   => [
                    'transaction_id' => ['sales', false],
                    'payment_type'   => ['payment_methods', false],
                    'create_user'    => ['users', false],
                ],
                'scope' => ['via' => 'transaction_id', 'table' => 'sales'],
                'owner' => 'device',
            ],
            'expense_categories' => [
                'fks'   => [
                    'company_id' => ['companies', false],
                    'created_by' => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
            'expenses' => [
                'fks'   => [
                    'company_id'     => ['companies', true],
                    'category_id'    => ['expense_categories', false],
                    'payment_method' => ['payment_methods', false],
                    'created_by'     => ['users', false],
                ],
                'scope' => 'company',
                'owner' => 'device',
            ],
        ];
    }

    /**
     * Ordered list of table names (dependency order).
     */
    public static function order(): array
    {
        return array_keys(self::tables());
    }

    /**
     * Config for a single table, or null if the table is not syncable.
     */
    public static function config(string $table): ?array
    {
        return self::tables()[$table] ?? null;
    }

    public static function isSyncable(string $table): bool
    {
        return isset(self::tables()[$table]);
    }
}
