<?php
declare(strict_types=1);
namespace PpPhp\Core\Build\SocialAuth;

final class SocialAuthBuilder
{
    /** Providers with a runtime implementation. Order drives the UI. */
    public const PROVIDERS = ['google', 'microsoft', 'apple', 'facebook', 'github', 'linkedin'];

    /** Credentials without which a provider cannot work and is skipped. */
    public const REQUIRED = [
        'google'    => ['client_id', 'client_secret'],
        'microsoft' => ['client_id', 'client_secret'],
        'apple'     => ['services_id', 'team_id', 'key_id', 'private_key'],
        'facebook'  => ['app_id', 'app_secret'],
        'github'    => ['client_id', 'client_secret'],
        'linkedin'  => ['client_id', 'client_secret'],
    ];

    /** @return array{files:array,login:array,register:array,warnings:array} */
    public function build(string $outputDir, array $security): array
    {
        $social=(array)($security['social_auth']??[]); $warnings=[]; $enabled=[];
        if (!empty($social['enabled']) && !empty($security['db_auth_enabled'])) {
            foreach (self::PROVIDERS as $id) {
                $cfg=(array)($social['providers'][$id]??[]); if (empty($cfg['enabled'])) continue;
                $required=self::REQUIRED[$id];
                $missing=array_filter($required,static fn($key)=>trim((string)($cfg[$key]??''))==='');
                if ($missing) { $warnings[] = ucfirst($id).' social login skipped: missing '.implode(', ',$missing).'.'; continue; }
                $enabled[]=$id;
            }
        }
        $dir=$outputDir.'/generated/auth/social'; if (!is_dir($dir)) mkdir($dir,0755,true); $files=[];
        $source=__DIR__.'/Runtime';
        foreach (glob($source.'/*.php')?:[] as $file) { $name=basename($file); $dest=$dir.'/'.$name; copy($file,$dest); $files[]=$dest; }
        // Ship ONLY what the social runtime reads. This used to be the entire
        // security blob — registration policy, lockout settings and the account
        // email templates all landed in a file inside the web root, next to the
        // provider secrets, for no reason.
        $config = [
            'enabled'                 => (bool) ($social['enabled'] ?? false),
            'allow_login'             => (bool) ($social['allow_login'] ?? true),
            'allow_registration'      => (bool) ($social['allow_registration'] ?? true),
            'auto_create_users'       => (bool) ($social['auto_create_users'] ?? true),
            'link_by_verified_email'  => (bool) ($social['link_by_verified_email'] ?? true),
            'default_role'            => (string) ($social['default_role'] ?? 'registered'),
            // identity column mapping the account service needs
            'users_table'    => (string) ($security['users_table'] ?? 'users'),
            'username_field' => (string) ($security['username_field'] ?? 'username'),
            'email_field'    => (string) ($security['email_field'] ?? 'email'),
            'fullname_field' => (string) ($security['fullname_field'] ?? 'fullname'),
            'role_field'     => (string) ($security['role_field'] ?? 'role'),
            'status_field'   => (string) ($security['status_field'] ?? 'status'),
            'providers'      => array_intersect_key((array) ($social['providers'] ?? []), array_flip($enabled)),
        ];
        $configFile=$dir.'/config.php';
        // The guard matters: this file holds live OAuth secrets. If the server
        // ever stops executing PHP (a misconfigured host, a copied backup), a
        // direct request must not return anything useful.
        file_put_contents($configFile,
            "<?php\ndeclare(strict_types=1);\n"
            . "if (!defined('BASE_PATH')) { http_response_code(404); exit; }\n"
            . "return " . var_export($config, true) . ";\n");
        $files[]=$configFile;
        // Belt and braces for Apache; harmless elsewhere.
        $htaccess = $dir . '/.htaccess';
        file_put_contents($htaccess, "<Files \"config.php\">\n  Require all denied\n</Files>\n");
        $files[] = $htaccess;
        foreach (self::PROVIDERS as $id) {
            $providerDir=$dir.'/'.$id; if (!is_dir($providerDir)) mkdir($providerDir,0755,true);
            $callback=$providerDir.'/callback.php'; file_put_contents($callback,"<?php\ndeclare(strict_types=1);\n\$socialProvider = ".var_export($id,true).";\nrequire dirname(__DIR__).'/callback-handler.php';\n"); $files[]=$callback;
        }
        return ['files'=>$files,'login'=>!empty($social['allow_login'])?$enabled:[],'register'=>!empty($social['allow_registration'])?$enabled:[],'warnings'=>$warnings];
    }
}
