<?php
declare(strict_types=1);

namespace App\Modules\Settings;

use App\Core\Support\StringHelper;
use PDO;
use Throwable;

final class CompanySettingsRepository
{
    public function __construct(
        private readonly PDO $pdo
    ) {
    }

    /**
     * @return array<string, mixed>
     */
    public function getSettings(): array
    {
        try {
            $statement = $this->pdo->prepare('SELECT * FROM company_settings WHERE id = 1 LIMIT 1');
            $statement->execute();
            $row = $statement->fetch(PDO::FETCH_ASSOC);
        } catch (Throwable) {
            return $this->defaults();
        }

        if (!is_array($row)) {
            return $this->defaults();
        }

        return [
            'company_name' => trim((string) ($row['company_name'] ?? '')),
            'person_name' => trim((string) ($row['person_name'] ?? '')),
            'sender_contact_person' => trim((string) ($row['sender_contact_person'] ?? '')),
            'street' => trim((string) ($row['street'] ?? '')),
            'city' => trim((string) ($row['city'] ?? '')),
            'postal_code' => trim((string) ($row['postal_code'] ?? '')),
            'country_code' => trim((string) ($row['country_code'] ?? 'PL')),
            'phone' => trim((string) ($row['phone'] ?? '')),
            'email' => trim((string) ($row['email'] ?? '')),
            'tax_number' => trim((string) ($row['tax_number'] ?? '')),
            'bank_account' => trim((string) ($row['bank_account'] ?? '')),
            'bank_owner_name' => trim((string) ($row['bank_owner_name'] ?? '')),
            'bdo_number' => trim((string) ($row['bdo_number'] ?? '')),
            'regon' => trim((string) ($row['regon'] ?? '')),
            'court_register' => trim((string) ($row['court_register'] ?? '')),
            'logo_path' => trim((string) ($row['logo_path'] ?? '')),
            'default_package_length_cm' => (float) ($row['default_package_length_cm'] ?? 25.0),
            'default_package_width_cm' => (float) ($row['default_package_width_cm'] ?? 20.0),
            'default_package_height_cm' => (float) ($row['default_package_height_cm'] ?? 8.0),
            'default_package_weight_kg' => (float) ($row['default_package_weight_kg'] ?? 1.0),
            'default_label_format' => trim((string) ($row['default_label_format'] ?? 'PDF')),
        ];
    }

    /**
     * @param array<string, mixed> $data
     */
    public function saveSettings(array $data): void
    {
        $this->ensureRow();

        $statement = $this->pdo->prepare(
            'UPDATE company_settings SET
                company_name = :company_name,
                person_name = :person_name,
                sender_contact_person = :sender_contact_person,
                street = :street,
                city = :city,
                postal_code = :postal_code,
                country_code = :country_code,
                phone = :phone,
                email = :email,
                tax_number = :tax_number,
                bank_account = :bank_account,
                bank_owner_name = :bank_owner_name,
                bdo_number = :bdo_number,
                regon = :regon,
                court_register = :court_register,
                logo_path = :logo_path,
                default_package_length_cm = :length,
                default_package_width_cm = :width,
                default_package_height_cm = :height,
                default_package_weight_kg = :weight,
                default_label_format = :label_format,
                updated_at = NOW()
            WHERE id = 1'
        );

        $statement->execute([
            'company_name' => StringHelper::nullableString((string) ($data['company_name'] ?? '')),
            'person_name' => StringHelper::nullableString((string) ($data['person_name'] ?? '')),
            'sender_contact_person' => StringHelper::nullableString((string) ($data['sender_contact_person'] ?? '')),
            'street' => StringHelper::nullableString((string) ($data['street'] ?? '')),
            'city' => StringHelper::nullableString((string) ($data['city'] ?? '')),
            'postal_code' => StringHelper::nullableString((string) ($data['postal_code'] ?? '')),
            'country_code' => strtoupper(trim((string) ($data['country_code'] ?? 'PL'))) ?: 'PL',
            'phone' => StringHelper::nullableString((string) ($data['phone'] ?? '')),
            'email' => StringHelper::nullableString((string) ($data['email'] ?? '')),
            'tax_number' => StringHelper::nullableString((string) ($data['tax_number'] ?? '')),
            'bank_account' => StringHelper::nullableString((string) ($data['bank_account'] ?? '')),
            'bank_owner_name' => StringHelper::nullableString((string) ($data['bank_owner_name'] ?? '')),
            'bdo_number' => StringHelper::nullableString((string) ($data['bdo_number'] ?? '')),
            'regon' => StringHelper::nullableString((string) ($data['regon'] ?? '')),
            'court_register' => StringHelper::nullableString((string) ($data['court_register'] ?? '')),
            'logo_path' => StringHelper::nullableString((string) ($data['logo_path'] ?? '')),
            'length' => max(0.1, (float) ($data['default_package_length_cm'] ?? 25.0)),
            'width' => max(0.1, (float) ($data['default_package_width_cm'] ?? 20.0)),
            'height' => max(0.1, (float) ($data['default_package_height_cm'] ?? 8.0)),
            'weight' => max(0.001, (float) ($data['default_package_weight_kg'] ?? 1.0)),
            'label_format' => in_array(strtoupper(trim((string) ($data['default_label_format'] ?? ''))), ['PDF', 'ZPL'], true)
                ? strtoupper(trim((string) $data['default_label_format']))
                : 'PDF',
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    public function getSenderAddress(): array
    {
        $settings = $this->getSettings();
        return [
            'name' => $settings['person_name'] !== '' ? $settings['person_name'] : ($settings['company_name'] !== '' ? $settings['company_name'] : null),
            'contactPerson' => $settings['sender_contact_person'] !== ''
                ? $settings['sender_contact_person']
                : ($settings['person_name'] !== '' ? $settings['person_name'] : null),
            'company' => $settings['company_name'] !== '' ? $settings['company_name'] : null,
            'street' => $settings['street'] !== '' ? $settings['street'] : null,
            'city' => $settings['city'] !== '' ? $settings['city'] : null,
            'postalCode' => $settings['postal_code'] !== '' ? $settings['postal_code'] : null,
            'countryCode' => $settings['country_code'] !== '' ? $settings['country_code'] : 'PL',
            'phone' => $settings['phone'] !== '' ? $settings['phone'] : null,
            'email' => $settings['email'] !== '' ? $settings['email'] : null,
        ];
    }

    private function ensureRow(): void
    {
        $this->pdo->exec(
            'INSERT INTO company_settings (id) VALUES (1) ON DUPLICATE KEY UPDATE updated_at = updated_at'
        );
    }

    /**
     * @return array<string, mixed>
     */
    private function defaults(): array
    {
        return [
            'company_name' => '',
            'person_name' => '',
            'sender_contact_person' => '',
            'street' => '',
            'city' => '',
            'postal_code' => '',
            'country_code' => 'PL',
            'phone' => '',
            'email' => '',
            'tax_number' => '',
            'bank_account' => '',
            'bank_owner_name' => '',
            'bdo_number' => '',
            'regon' => '',
            'court_register' => '',
            'logo_path' => '',
            'default_package_length_cm' => 25.0,
            'default_package_width_cm' => 20.0,
            'default_package_height_cm' => 8.0,
            'default_package_weight_kg' => 1.0,
            'default_label_format' => 'PDF',
        ];
    }
}
