<?php
declare(strict_types=1);

require_once __DIR__ . '/master_db.php';

function golder_fallback_plan_type(): string
{
    return 'L-SOLO';
}

function golder_default_plan_type(): string
{
    return 'A-COMPLEX';
}

function golder_plan_definitions(): array
{
    static $definitions = null;
    if (is_array($definitions)) {
        return $definitions;
    }

    $definitions = [
        'L-SOLO' => [
            'plan_type' => 'L-SOLO',
            'plan_name' => 'L-Solo',
            'label' => 'L-Solo (Omur Boyu Tekli)',
            'pc_limit_mode' => 'fixed_1',
            'web_limit_mode' => 'fixed_0',
            'desktop_expiry_mode' => 'lifetime',
            'sync_expiry_mode' => 'disabled',
            'features' => [
                'WEB_ACCESS' => 0,
                'BACKUP_AUTO' => 0,
                'BACKUP_MANUAL' => 0,
                'DEVICE_MANAGEMENT' => 1,
                'PROFILE_SYNC' => 0,
                'PAYMENT_REQUEST' => 1,
                'DEMO_CREATE' => 1,
            ],
        ],
        'L-SYNC' => [
            'plan_type' => 'L-SYNC',
            'plan_name' => 'L-Sync',
            'label' => 'L-Sync (Omur Boyu + Telefon)',
            'pc_limit_mode' => 'fixed_1',
            'web_limit_mode' => 'editable',
            'desktop_expiry_mode' => 'lifetime',
            'sync_expiry_mode' => 'dated',
            'features' => [
                'WEB_ACCESS' => 1,
                'BACKUP_AUTO' => 1,
                'BACKUP_MANUAL' => 1,
                'DEVICE_MANAGEMENT' => 1,
                'PROFILE_SYNC' => 1,
                'PAYMENT_REQUEST' => 1,
                'DEMO_CREATE' => 1,
            ],
        ],
        'A-SOLO' => [
            'plan_type' => 'A-SOLO',
            'plan_name' => 'A-Solo',
            'label' => 'A-Solo (Yillik Lokal)',
            'pc_limit_mode' => 'fixed_1',
            'web_limit_mode' => 'fixed_0',
            'desktop_expiry_mode' => 'dated',
            'sync_expiry_mode' => 'disabled',
            'features' => [
                'WEB_ACCESS' => 0,
                'BACKUP_AUTO' => 0,
                'BACKUP_MANUAL' => 0,
                'DEVICE_MANAGEMENT' => 1,
                'PROFILE_SYNC' => 0,
                'PAYMENT_REQUEST' => 1,
                'DEMO_CREATE' => 1,
            ],
        ],
        'A-OFFICE' => [
            'plan_type' => 'A-OFFICE',
            'plan_name' => 'A-Office',
            'label' => 'A-Office (Yillik Coklu PC)',
            'pc_limit_mode' => 'editable',
            'web_limit_mode' => 'fixed_0',
            'desktop_expiry_mode' => 'dated',
            'sync_expiry_mode' => 'dated',
            'features' => [
                'WEB_ACCESS' => 0,
                'BACKUP_AUTO' => 0,
                'BACKUP_MANUAL' => 0,
                'DEVICE_MANAGEMENT' => 1,
                'PROFILE_SYNC' => 1,
                'PAYMENT_REQUEST' => 1,
                'DEMO_CREATE' => 1,
            ],
        ],
        'A-COMPLEX' => [
            'plan_type' => 'A-COMPLEX',
            'plan_name' => 'A-Complex',
            'label' => 'A-Complex (Yillik Tam Paket)',
            'pc_limit_mode' => 'editable',
            'web_limit_mode' => 'editable',
            'desktop_expiry_mode' => 'dated',
            'sync_expiry_mode' => 'dated',
            'features' => [
                'WEB_ACCESS' => 1,
                'BACKUP_AUTO' => 1,
                'BACKUP_MANUAL' => 1,
                'DEVICE_MANAGEMENT' => 1,
                'PROFILE_SYNC' => 1,
                'PAYMENT_REQUEST' => 1,
                'DEMO_CREATE' => 1,
            ],
        ],
    ];

    return $definitions;
}

function golder_plan_codes(): array
{
    return array_keys(golder_plan_definitions());
}

function golder_plan_feature_defaults(): array
{
    return [
        'WEB_ACCESS' => 'Web/mobile panel access',
        'BACKUP_AUTO' => 'Automatic backup',
        'BACKUP_MANUAL' => 'Manual backup',
        'DEVICE_MANAGEMENT' => 'Device management panel',
        'PROFILE_SYNC' => 'Desktop profile sync',
        'PAYMENT_REQUEST' => 'Payment request flow',
        'DEMO_CREATE' => 'Demo creation',
    ];
}

function golder_legacy_plan_type_alias(string $planType): string
{
    $planType = strtoupper(trim($planType));
    if ($planType === '') {
        return golder_fallback_plan_type();
    }

    if (isset(golder_plan_definitions()[$planType])) {
        return $planType;
    }

    if (in_array($planType, ['1', '2', '3'], true)) {
        return 'L-SYNC';
    }

    return golder_fallback_plan_type();
}

function golder_normalize_plan_type(string $planType): string
{
    return golder_legacy_plan_type_alias($planType);
}

function golder_plan_definition(string $planType): array
{
    $normalized = golder_normalize_plan_type($planType);
    $definitions = golder_plan_definitions();
    return $definitions[$normalized] ?? $definitions[golder_fallback_plan_type()];
}

function golder_plan_label(string $planType): string
{
    return (string)(golder_plan_definition($planType)['label'] ?? golder_normalize_plan_type($planType));
}

function golder_plan_requires_desktop_expiry(string $planType): bool
{
    return (string)(golder_plan_definition($planType)['desktop_expiry_mode'] ?? '') === 'dated';
}

function golder_plan_requires_sync_expiry(string $planType): bool
{
    return (string)(golder_plan_definition($planType)['sync_expiry_mode'] ?? '') === 'dated';
}

function golder_plan_supports_profile_sync(string $planType): bool
{
    return !empty(golder_plan_definition($planType)['features']['PROFILE_SYNC']);
}

function golder_plan_supports_web_mobile(string $planType): bool
{
    return !empty(golder_plan_definition($planType)['features']['WEB_ACCESS']);
}

function golder_normalize_datetime_string(?string $value): string
{
    $value = trim((string)$value);
    if ($value === '') {
        return '';
    }

    $timestamp = strtotime($value);
    if ($timestamp === false) {
        return '';
    }

    return gmdate('Y-m-d H:i:s', $timestamp);
}

function golder_is_expired_datetime(?string $value): bool
{
    $normalized = golder_normalize_datetime_string($value);
    if ($normalized === '') {
        return false;
    }

    $timestamp = strtotime($normalized);
    if ($timestamp === false) {
        return false;
    }

    return $timestamp < time();
}

function golder_normalize_plan_expiry_dates(string $planType, ?string $desktopExpiry, ?string $syncExpiry): array
{
    $planType = golder_normalize_plan_type($planType);
    $desktop = golder_normalize_datetime_string($desktopExpiry);
    $sync = golder_normalize_datetime_string($syncExpiry);

    if (!golder_plan_requires_desktop_expiry($planType)) {
        $desktop = '';
    }
    if (!golder_plan_requires_sync_expiry($planType)) {
        $sync = '';
    }

    return [
        'desktop_expiry_date' => $desktop,
        'sync_expiry_date' => $sync,
        'expiry_date' => $desktop,
    ];
}

function golder_validate_plan_expiry_dates(string $planType, ?string $desktopExpiry, ?string $syncExpiry): array
{
    $planType = golder_normalize_plan_type($planType);
    $desktopRaw = trim((string)$desktopExpiry);
    $syncRaw = trim((string)$syncExpiry);
    $normalized = golder_normalize_plan_expiry_dates($planType, $desktopExpiry, $syncExpiry);
    $errors = [];

    if (golder_plan_requires_desktop_expiry($planType) && $normalized['desktop_expiry_date'] === '') {
        $errors['desktop_expiry_date'] = ($desktopRaw === '')
            ? 'desktop_expiry_date zorunludur.'
            : 'desktop_expiry_date gecersiz.';
    }

    if (golder_plan_requires_sync_expiry($planType) && $normalized['sync_expiry_date'] === '') {
        $errors['sync_expiry_date'] = ($syncRaw === '')
            ? 'sync_expiry_date zorunludur.'
            : 'sync_expiry_date gecersiz.';
    }

    return [
        'ok' => !$errors,
        'errors' => $errors,
        'desktop_expiry_date' => $normalized['desktop_expiry_date'],
        'sync_expiry_date' => $normalized['sync_expiry_date'],
        'expiry_date' => $normalized['expiry_date'],
    ];
}

function golder_ensure_plan_tables(PDO $master): void
{
    $master->exec(
        "CREATE TABLE IF NOT EXISTS plan_catalog (
            plan_type VARCHAR(20) PRIMARY KEY,
            plan_name VARCHAR(80) NOT NULL,
            pc_limit_mode VARCHAR(20) NOT NULL,
            web_limit_mode VARCHAR(20) NOT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
    );

    $master->exec(
        "CREATE TABLE IF NOT EXISTS plan_feature_map (
            id BIGINT AUTO_INCREMENT PRIMARY KEY,
            plan_type VARCHAR(20) NOT NULL,
            feature_key VARCHAR(100) NOT NULL,
            is_enabled TINYINT(1) NOT NULL DEFAULT 0,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            UNIQUE KEY uniq_plan_feature (plan_type, feature_key)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
    );

    $master->exec(
        "CREATE TABLE IF NOT EXISTS plan_feature_defaults (
            feature_key VARCHAR(100) PRIMARY KEY,
            description_text VARCHAR(255) DEFAULT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
    );

    golder_seed_plan_defaults($master);
}

function golder_seed_plan_defaults(PDO $master): void
{
    $upPlan = $master->prepare(
        "INSERT INTO plan_catalog (plan_type, plan_name, pc_limit_mode, web_limit_mode)
         VALUES (:p, :n, :pc, :web)
         ON DUPLICATE KEY UPDATE
             plan_name = VALUES(plan_name),
             pc_limit_mode = VALUES(pc_limit_mode),
             web_limit_mode = VALUES(web_limit_mode)"
    );

    foreach (golder_plan_definitions() as $planType => $definition) {
        $upPlan->execute([
            ':p' => $planType,
            ':n' => (string)($definition['label'] ?? $definition['plan_name'] ?? $planType),
            ':pc' => (string)($definition['pc_limit_mode'] ?? 'fixed_1'),
            ':web' => (string)($definition['web_limit_mode'] ?? 'fixed_0'),
        ]);
    }

    $upFeature = $master->prepare(
        "INSERT INTO plan_feature_defaults (feature_key, description_text)
         VALUES (:k, :d)
         ON DUPLICATE KEY UPDATE description_text = VALUES(description_text)"
    );

    foreach (golder_plan_feature_defaults() as $featureKey => $description) {
        $upFeature->execute([':k' => $featureKey, ':d' => $description]);
    }

    $upMap = $master->prepare(
        "INSERT INTO plan_feature_map (plan_type, feature_key, is_enabled)
         VALUES (:p, :k, :v)
         ON DUPLICATE KEY UPDATE is_enabled = VALUES(is_enabled)"
    );

    foreach (golder_plan_definitions() as $planType => $definition) {
        foreach ((array)($definition['features'] ?? []) as $featureKey => $enabled) {
            $upMap->execute([
                ':p' => $planType,
                ':k' => (string)$featureKey,
                ':v' => (int)$enabled,
            ]);
        }
    }
}

function golder_plan_feature_enabled(PDO $master, string $planType, string $featureKey): bool
{
    golder_ensure_plan_tables($master);
    $st = $master->prepare(
        'SELECT is_enabled
         FROM plan_feature_map
         WHERE plan_type = :p
           AND feature_key = :k
         LIMIT 1'
    );
    $st->execute([
        ':p' => golder_normalize_plan_type($planType),
        ':k' => trim($featureKey),
    ]);
    $row = $st->fetch();
    if (!is_array($row)) {
        return false;
    }
    return ((int)($row['is_enabled'] ?? 0)) === 1;
}

function golder_customer_plan_feature_enabled(array $customer, string $featureKey): bool
{
    $plan = golder_customer_effective_plan($customer);
    return ((int)($plan['features'][$featureKey] ?? 0)) === 1;
}

function golder_normalize_plan_limits(string $planType, int $pcDevices, int $webSessions): array
{
    $definition = golder_plan_definition($planType);
    $normalizedPlanType = (string)($definition['plan_type'] ?? golder_fallback_plan_type());

    $pcDevices = max(1, $pcDevices);
    $webSessions = max(0, $webSessions);

    if ((string)($definition['pc_limit_mode'] ?? '') === 'fixed_1') {
        $pcDevices = 1;
    }
    if ((string)($definition['web_limit_mode'] ?? '') === 'fixed_0') {
        $webSessions = 0;
    }

    return [
        'plan_type' => $normalizedPlanType,
        'max_pc_devices' => $pcDevices,
        'max_web_sessions' => $webSessions,
    ];
}

function golder_customer_effective_plan(array $customer): array
{
    $rawPlanType = (string)($customer['plan_type'] ?? '');
    $planType = golder_normalize_plan_type($rawPlanType);
    $definition = golder_plan_definition($planType);
    $normalizedLimits = golder_normalize_plan_limits(
        $planType,
        (int)($customer['max_pc_devices'] ?? $customer['max_devices'] ?? 1),
        (int)($customer['max_web_sessions'] ?? 0)
    );

    $legacyExpiry = golder_normalize_datetime_string((string)($customer['expiry_date'] ?? ''));
    $desktopExpiry = golder_normalize_datetime_string((string)($customer['desktop_expiry_date'] ?? ''));
    $syncExpiry = golder_normalize_datetime_string((string)($customer['sync_expiry_date'] ?? ''));

    if ($desktopExpiry === '' && golder_plan_requires_desktop_expiry($planType)) {
        $desktopExpiry = $legacyExpiry;
    }
    if ($syncExpiry === '' && golder_plan_requires_sync_expiry($planType)) {
        $syncExpiry = $legacyExpiry;
    }

    $normalizedDates = golder_normalize_plan_expiry_dates($planType, $desktopExpiry, $syncExpiry);
    $syncStatus = golder_customer_sync_status(array_merge($customer, [
        'plan_type' => $planType,
        'desktop_expiry_date' => $normalizedDates['desktop_expiry_date'],
        'sync_expiry_date' => $normalizedDates['sync_expiry_date'],
        'expiry_date' => $normalizedDates['expiry_date'],
    ]));

    return array_merge($definition, $normalizedLimits, $normalizedDates, [
        'legacy_expiry_date' => $legacyExpiry,
        'web_mobile_enabled' => (
            golder_plan_supports_web_mobile($planType)
            && (int)$normalizedLimits['max_web_sessions'] > 0
            && $syncStatus === 'active'
        ) ? 1 : 0,
        'sync_status' => $syncStatus,
    ]);
}

function golder_customer_desktop_expiry(array $customer): string
{
    return (string)(golder_customer_effective_plan($customer)['desktop_expiry_date'] ?? '');
}

function golder_customer_sync_expiry(array $customer): string
{
    return (string)(golder_customer_effective_plan($customer)['sync_expiry_date'] ?? '');
}

function golder_customer_desktop_access_expired(array $customer): bool
{
    $plan = golder_customer_effective_plan($customer);
    if (!golder_plan_requires_desktop_expiry((string)($plan['plan_type'] ?? ''))) {
        return false;
    }

    $desktopExpiry = trim((string)($plan['desktop_expiry_date'] ?? ''));
    if ($desktopExpiry === '') {
        return true;
    }

    return golder_is_expired_datetime($desktopExpiry);
}

function golder_customer_sync_status(array $customer): string
{
    $planType = golder_normalize_plan_type((string)($customer['plan_type'] ?? ''));
    if (!golder_plan_supports_profile_sync($planType)) {
        return 'disabled';
    }

    $effective = golder_normalize_plan_expiry_dates(
        $planType,
        (string)($customer['desktop_expiry_date'] ?? ''),
        (string)($customer['sync_expiry_date'] ?? ($customer['expiry_date'] ?? ''))
    );
    $syncExpiry = trim((string)($effective['sync_expiry_date'] ?? ''));
    if ($syncExpiry === '') {
        return 'expired';
    }

    return golder_is_expired_datetime($syncExpiry) ? 'expired' : 'active';
}

function golder_customer_sync_enabled(array $customer): bool
{
    return golder_customer_sync_status($customer) === 'active';
}

function golder_customer_web_mobile_enabled(array $customer): bool
{
    $effective = golder_customer_effective_plan($customer);
    return !empty($effective['web_mobile_enabled']);
}

function golder_enforce_customer_plan(PDO $master, int $customerId): ?array
{
    golder_ensure_customers_columns($master);
    golder_ensure_plan_tables($master);

    $customer = golder_customer_by_id($master, $customerId);
    if (!$customer) {
        return null;
    }

    $normalized = golder_customer_effective_plan($customer);

    $master->prepare(
        'UPDATE customers
         SET plan_type = :p,
             max_pc_devices = :pc,
             max_web_sessions = :web,
             max_devices = :pc_legacy,
             desktop_expiry_date = :desktop_expiry,
             sync_expiry_date = :sync_expiry,
             expiry_date = :legacy_expiry
         WHERE id = :id'
    )->execute([
        ':p' => $normalized['plan_type'],
        ':pc' => $normalized['max_pc_devices'],
        ':pc_legacy' => $normalized['max_pc_devices'],
        ':web' => $normalized['max_web_sessions'],
        ':desktop_expiry' => ($normalized['desktop_expiry_date'] !== '' ? $normalized['desktop_expiry_date'] : null),
        ':sync_expiry' => ($normalized['sync_expiry_date'] !== '' ? $normalized['sync_expiry_date'] : null),
        ':legacy_expiry' => ($normalized['expiry_date'] !== '' ? $normalized['expiry_date'] : null),
        ':id' => $customerId,
    ]);

    return golder_customer_by_id($master, $customerId);
}
