<?php
/**
 * Auth Controller
 */

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Support\Database;
use App\Support\Response;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

class AuthController
{
    private array $config;
    
    public function __construct(array $config)
    {
        $this->config = $config;
    }
    
    /**
     * POST /api/auth/login
     */
    public function login(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $body = $request->getParsedBody();
        
        $email = trim($body['email'] ?? '');
        $password = $body['password'] ?? '';
        
        if (empty($email) || empty($password)) {
            return Response::validationError($response, [
                'email' => 'Email is required',
                'password' => 'Password is required',
            ]);
        }
        
        // Check if it's a platform admin login
        $admin = Database::fetch(
            'SELECT * FROM platform_admins WHERE email = $1',
            [$email]
        );
        
        if ($admin && password_verify($password, $admin['password_hash'])) {
            return $this->createTokenResponse($response, $admin, 'platform_admin');
        }
        
        // Check if it's a tenant user login
        $user = Database::fetch(
            'SELECT u.*, t.status as tenant_status 
             FROM users u 
             JOIN tenants t ON t.id = u.tenant_id 
             WHERE u.email = $1',
            [$email]
        );
        
        if ($user && password_verify($password, $user['password_hash'])) {
            if ($user['tenant_status'] !== 'active') {
                return Response::error($response, 'Account is not active', 403);
            }
            if ($user['status'] !== 'active') {
                return Response::error($response, 'User is inactive', 403);
            }
            
            // Update last login
            Database::update('users', ['last_login_at' => 'NOW()'], 'id = $1', [$user['id']]);
            
            return $this->createTokenResponse($response, $user, 'user');
        }
        
        return Response::error($response, 'Invalid credentials', 401);
    }
    
    /**
     * POST /api/auth/register
     */
    public function register(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $body = $request->getParsedBody();
        
        $name = trim($body['name'] ?? '');
        $email = trim($body['email'] ?? '');
        $password = $body['password'] ?? '';
        $phone = trim($body['phone'] ?? '');
        $address = trim($body['address'] ?? '');
        
        // Validation
        $errors = [];
        if (empty($name)) $errors['name'] = 'Name is required';
        if (empty($email)) $errors['email'] = 'Email is required';
        elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors['email'] = 'Invalid email format';
        if (empty($password)) $errors['password'] = 'Password is required';
        elseif (strlen($password) < 8) $errors['password'] = 'Password must be at least 8 characters';
        
        if (!empty($errors)) {
            return Response::validationError($response, $errors);
        }
        
        // Check if email already exists
        $exists = Database::fetch(
            'SELECT id FROM tenants WHERE email = $1',
            [$email]
        );
        
        if ($exists) {
            return Response::error($response, 'Email already registered', 409);
        }
        
        // Generate slug from name
        $slug = strtolower(preg_replace('/[^a-z0-9]+/', '-', $name));
        $originalSlug = $slug;
        $counter = 1;
        while (Database::fetch('SELECT id FROM tenants WHERE slug = $1', [$slug])) {
            $slug = $originalSlug . '-' . $counter++;
        }
        
        // Create tenant
        $tenantId = Database::insert('tenants', [
            'name' => $name,
            'slug' => $slug,
            'email' => $email,
            'phone' => $phone,
            'address' => $address,
            'status' => 'pending_approval',
        ]);
        
        // Create first user (admin of the tenant)
        $userId = Database::insert('users', [
            'tenant_id' => $tenantId,
            'email' => $email,
            'password_hash' => password_hash($password, PASSWORD_DEFAULT),
            'first_name' => $name,
            'last_name' => '',
            'user_type' => 'admin',
            'status' => 'pending', // Needs email verification first
        ]);
        
        // Enable default modules (office, calendar, messenger)
        $defaultModules = Database::fetchAll('SELECT id FROM modules WHERE key IN (\'office\', \'calendar\', \'messenger\')');
        foreach ($defaultModules as $module) {
            Database::insert('tenant_modules', [
                'tenant_id' => $tenantId,
                'module_id' => $module['id'],
                'status' => 'enabled',
            ]);
        }
        
        return Response::success($response, [
            'tenant_id' => $tenantId,
            'user_id' => $userId,
            'message' => 'Registration successful. Pending admin approval.',
        ], 'Registration successful', 201);
    }
    
    /**
     * POST /api/auth/verify-email
     */
    public function verifyEmail(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $body = $request->getParsedBody();
        $token = $body['token'] ?? '';
        
        if (empty($token)) {
            return Response::validationError($response, ['token' => 'Token is required']);
        }
        
        // TODO: Verify token and activate user
        
        return Response::success($response, null, 'Email verified successfully');
    }
    
    /**
     * GET /api/auth/me
     */
    public function me(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $auth = $request->getAttribute('auth');
        
        if ($auth['type'] === 'platform_admin') {
            $data = Database::fetch(
                'SELECT id, email, name, role, created_at, last_login_at FROM platform_admins WHERE id = $1',
                [$auth['id']]
            );
            $data['type'] = 'platform_admin';
        } else {
            $data = Database::fetch(
                'SELECT u.id, u.email, u.first_name, u.last_name, u.user_type, u.status, u.avatar_url, u.last_login_at,
                        t.id as tenant_id, t.name as tenant_name, t.slug as tenant_slug, t.status as tenant_status
                 FROM users u
                 JOIN tenants t ON t.id = u.tenant_id
                 WHERE u.id = $1',
                [$auth['id']]
            );
            $data['type'] = 'user';
        }
        
        return Response::success($response, $data);
    }
    
    /**
     * POST /api/auth/refresh
     */
    public function refresh(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $body = $request->getParsedBody();
        $refreshToken = $body['refresh_token'] ?? '';
        
        if (empty($refreshToken)) {
            return Response::validationError($response, ['refresh_token' => 'Refresh token is required']);
        }
        
        try {
            $decoded = JWT::decode($refreshToken, new Key($this->config['jwt']['secret'], 'HS256'));
            
            if ($decoded->type !== 'refresh') {
                return Response::error($response, 'Invalid token type', 401);
            }
            
            // Get user/admin
            if ($decoded->user_type === 'platform_admin') {
                $user = Database::fetch('SELECT * FROM platform_admins WHERE id = $1', [$decoded->sub]);
            } else {
                $user = Database::fetch('SELECT * FROM users WHERE id = $1', [$decoded->sub]);
            }
            
            if (!$user) {
                return Response::error($response, 'User not found', 401);
            }
            
            return $this->createTokenResponse($response, $user, $decoded->user_type);
        } catch (\Exception $e) {
            return Response::error($response, 'Invalid refresh token', 401);
        }
    }
    
    /**
     * POST /api/auth/logout
     */
    public function logout(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        // JWT is stateless, so logout is handled client-side
        // Here we could blacklist the token if needed
        return Response::success($response, null, 'Logged out successfully');
    }
    
    /**
     * POST /api/auth/forgot-password
     */
    public function forgotPassword(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $body = $request->getParsedBody();
        $email = trim($body['email'] ?? '');
        
        if (empty($email)) {
            return Response::validationError($response, ['email' => 'Email is required']);
        }
        
        // Check if email exists
        $admin = Database::fetch('SELECT id FROM platform_admins WHERE email = $1', [$email]);
        $user = Database::fetch('SELECT id FROM users WHERE email = $1', [$email]);
        
        // Always return success to prevent email enumeration
        if (!$admin && !$user) {
            return Response::success($response, null, 'If the email exists, a reset link has been sent');
        }
        
        // TODO: Generate reset token, send email
        
        return Response::success($response, null, 'If the email exists, a reset link has been sent');
    }
    
    /**
     * Create JWT token response
     */
    private function createTokenResponse(ResponseInterface $response, array $user, string $type): ResponseInterface
    {
        $now = time();
        $expiry = $this->config['jwt']['expiry'];
        $refreshExpiry = $this->config['jwt']['refresh_expiry'];
        
        $payload = [
            'iss' => 'fahrschuldesk',
            'sub' => $user['id'],
            'iat' => $now,
            'exp' => $now + $expiry,
            'type' => 'access',
            'user_type' => $type,
        ];
        
        $refreshPayload = [
            'iss' => 'fahrschuldesk',
            'sub' => $user['id'],
            'iat' => $now,
            'exp' => $now + $refreshExpiry,
            'type' => 'refresh',
            'user_type' => $type,
        ];
        
        $accessToken = JWT::encode($payload, $this->config['jwt']['secret'], 'HS256');
        $refreshToken = JWT::encode($refreshPayload, $this->config['jwt']['secret'], 'HS256');
        
        return Response::json($response, [
            'success' => true,
            'data' => [
                'access_token' => $accessToken,
                'refresh_token' => $refreshToken,
                'token_type' => 'Bearer',
                'expires_in' => $expiry,
            ],
        ]);
    }
}