<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;
use App\Core\Response;
use App\Models\TenantModel;
use App\Models\UserModel;
use App\Models\RoleModel;

/**
 * Business Settings Controller
 */
class SettingsController extends Controller
{
    private TenantModel $tenantModel;
    private UserModel $userModel;
    private RoleModel $roleModel;

    public function __construct()
    {
        $this->tenantModel = new TenantModel();
        $this->userModel = new UserModel();
        $this->roleModel = new RoleModel();
    }

    /**
     * GET /api/v1/settings/business
     */
    public function getBusiness(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $profile = $this->tenantModel->find($tenantId);
        Response::success($profile);
    }

    /**
     * PUT /api/v1/settings/business
     */
    public function updateBusiness(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];
        $data = $this->getJsonBody();

        if ($this->tenantModel->updateProfile($tenantId, $userId, $data)) {
            Response::success([], 'Business profile updated');
        }
        Response::error('Update failed');
    }

    /**
     * POST /api/v1/settings/logo
     */
    public function uploadLogo(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];

        if (empty($_FILES['logo']))
            Response::error('No logo provided');

        $file = $_FILES['logo'];
        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $filename = "logo_" . $tenantId . "_" . time() . "." . $ext;
        $relativePath = "uploads/logos/" . $filename;
        $absolutePath = UPLOAD_DIR . "logos/" . $filename;

        if (!is_dir(dirname($absolutePath))) {
            mkdir(dirname($absolutePath), 0777, true);
        }

        if (move_uploaded_file($file['tmp_name'], $absolutePath)) {
            // Get old logo to delete it
            $profile = $this->tenantModel->find($tenantId);
            $oldLogo = $profile['logo'] ?? null;

            if ($this->tenantModel->updateLogo($tenantId, $userId, $relativePath)) {
                if ($oldLogo && file_exists(UPLOAD_DIR . str_replace('uploads/', '', $oldLogo))) {
                    unlink(UPLOAD_DIR . str_replace('uploads/', '', $oldLogo));
                }
                Response::success(['url' => $relativePath], 'Logo uploaded successfully');
            }
        }

        Response::error('File upload failed');
    }

    /**
     * GET /api/v1/settings/invoice
     */
    public function getInvoiceSettings(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $settings = $this->tenantModel->getSettings($tenantId);
        Response::success($settings);
    }

    /**
     * PUT /api/v1/settings/invoice
     */
    public function updateInvoiceSettings(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];
        $data = $this->getJsonBody();

        if ($this->tenantModel->updateSettings($tenantId, $userId, $data)) {
            Response::success([], 'Invoice settings updated');
        }
        Response::error('Update failed');
    }

    /**
     * GET /api/v1/settings/email
     */
    public function getEmailSettings(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $settings = $this->tenantModel->getSettings($tenantId);
        Response::success($settings);
    }

    /**
     * PUT /api/v1/settings/email
     */
    public function updateEmailSettings(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $userId = (int) $_REQUEST['user']['sub'];
        $data = $this->getJsonBody();

        if ($this->tenantModel->updateSettings($tenantId, $userId, $data)) {
            Response::success([], 'Email settings updated');
        }
        Response::error('Update failed');
    }

    /**
     * POST /api/v1/settings/test-email
     */
    public function testEmail(): void
    {
        // Implementation for PHPMailer would go here
        Response::success([], 'Test email triggered (simulated)');
    }
    /**
     * GET /api/v1/settings/users
     */
    public function getUsers(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $users = $this->userModel->getTenantUsers($tenantId);
        Response::success($users);
    }

    /**
     * PUT /api/v1/settings/users/{id}
     */
    public function updateUser(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $data = $this->getJsonBody();
        $this->validate($data, [
            'name' => 'required',
            'email' => 'required|email',
            'role_id' => 'required'
        ]);

        $user = $this->userModel->find((int) $id);
        if (!$user || $user['tenant_id'] != $tenantId) {
            Response::error('User not found', [], 404);
        }

        // Check email uniqueness if changed
        if ($data['email'] !== $user['email']) {
            if ($this->userModel->findByEmail($data['email'], $tenantId)) {
                Response::error('Email already in use');
            }
        }

        $this->userModel->update((int) $id, [
            'name' => $data['name'],
            'email' => $data['email'],
            'role_id' => (int) $data['role_id'],
            'is_active' => isset($data['is_active']) ? (int)$data['is_active'] : $user['is_active']
        ]);

        Response::success([], 'User updated successfully');
    }

    /**
     * GET /api/v1/settings/roles
     */
    public function getRoles(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $roles = $this->roleModel->getTenantRoles($tenantId);
        Response::success($roles);
    }

    /**
     * POST /api/v1/settings/roles
     */
    public function storeRole(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $data = $this->getJsonBody();
        $this->validate($data, ['name' => 'required']);

        $roleId = $this->roleModel->create([
            'tenant_id' => $tenantId,
            'name' => $data['name'],
            'permissions_json' => json_encode($data['permissions'] ?? []),
            'is_default' => 0
        ]);

        Response::success(['id' => $roleId], 'Role created successfully');
    }

    /**
     * PUT /api/v1/settings/roles/{id}
     */
    public function updateRole(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $data = $this->getJsonBody();
        $this->validate($data, ['name' => 'required']);

        $role = $this->roleModel->find((int) $id);
        if (!$role || $role['tenant_id'] != $tenantId) {
            Response::error('Role not found', [], 404);
        }

        if ($role['name'] === 'Admin') {
            Response::error('Cannot modify the system Admin role');
        }

        $this->roleModel->update((int) $id, [
            'name' => $data['name'],
            'permissions_json' => json_encode($data['permissions'] ?? [])
        ]);

        Response::success([], 'Role updated successfully');
    }

    /**
     * DELETE /api/v1/settings/roles/{id}
     */
    public function deleteRole(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $role = $this->roleModel->find((int) $id);
        if (!$role || $role['tenant_id'] != $tenantId) {
            Response::error('Role not found', [], 404);
        }

        if ($role['name'] === 'Admin' || $role['is_default']) {
            Response::error('Cannot delete system roles');
        }

        // Check if users are using this role
        $stmt = $this->userModel->getDb()->prepare("SELECT COUNT(*) FROM users WHERE role_id = ? AND is_active = 1");
        $stmt->execute([$id]);
        if ($stmt->fetchColumn() > 0) {
            Response::error('Cannot delete role while active users are assigned to it');
        }

        $this->roleModel->delete((int) $id);
        Response::success([], 'Role deleted');
    }

    /**
     * POST /api/v1/settings/users
     */
    public function storeUser(): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        $data = $this->getJsonBody();
        $this->validate($data, [
            'name' => 'required',
            'email' => 'required|email',
            'role_id' => 'required'
        ]);

        $existing = $this->userModel->findByEmail($data['email'], $tenantId);
        if ($existing) {
            if (!$existing['is_active']) {
                // Re-activate and update
                $this->userModel->update((int)$existing['id'], [
                    'name' => $data['name'],
                    'role_id' => (int)$data['role_id'],
                    'is_active' => 1
                ]);
                Response::success(['id' => $existing['id']], 'User re-activated and updated');
            }
            Response::error('User with this email already exists in your organization');
        }

        $userId = $this->userModel->create([
            'tenant_id' => $tenantId,
            'name' => $data['name'],
            'email' => $data['email'],
            'password_hash' => password_hash('password123', PASSWORD_BCRYPT), // Default password
            'role_id' => (int) $data['role_id'],
            'is_active' => 1
        ]);

        Response::success(['id' => $userId], 'User created successfully');
    }

    /**
     * DELETE /api/v1/settings/users/{id}
     */
    public function deleteUser(string $id): void
    {
        $tenantId = (int) $_REQUEST['tenant_id'];
        // Don't allow deleting self?
        $this->userModel->update((int) $id, ['is_active' => 0]);
        Response::success([], 'User deactivated');
    }
}
