<?php

declare(strict_types=1);

namespace ServerManager\Controllers;

use ServerManager\Core\App;
use ServerManager\Core\Session;
use ServerManager\Core\Validator;
use ServerManager\Models\Team;
use ServerManager\Models\Server;
use ServerManager\Models\User;
use ServerManager\Services\AuditService;

class TeamController
{
    private \ServerManager\Core\View $view;
    private Team $teamModel;
    private Server $serverModel;
    private AuditService $auditService;

    public function __construct()
    {
        $this->view = App::getInstance()->getView();
        $this->teamModel = new Team();
        $this->serverModel = new Server();
        $this->auditService = new AuditService();
    }

    public function index(): void
    {
        $userId = (int) Session::get('user_id');
        $search = $_GET['search'] ?? '';

        if ($search !== '') {
            $teams = $this->teamModel->findByCreator($userId);
            $teams = array_filter($teams, function ($team) use ($search) {
                $s = mb_strtolower($search);
                return mb_strpos(mb_strtolower($team['name'] ?? ''), $s) !== false
                    || mb_strpos(mb_strtolower($team['description'] ?? ''), $s) !== false;
            });
        } else {
            $teams = $this->teamModel->findByCreator($userId);
        }

        $this->view->display('teams.index', [
            'title' => 'Teams - ServerManager',
            'teams' => $teams,
            'search' => $search,
        ]);
    }

    public function searchUsers(): void
    {
        $q = $_GET['q'] ?? '';
        if (mb_strlen($q) < 2) {
            $this->view->json(['users' => []]);
            return;
        }

        $userModel = new User();
        $allUsers = $userModel->getAll(1, 999);
        $filtered = array_filter($allUsers['data'], function ($u) use ($q) {
            $s = mb_strtolower($q);
            return mb_strpos(mb_strtolower($u['username'] ?? ''), $s) !== false
                || mb_strpos(mb_strtolower($u['email'] ?? ''), $s) !== false;
        });

        $results = array_map(function ($u) {
            return [
                'id' => (int) $u['id'],
                'username' => $u['username'],
                'email' => $u['email'],
            ];
        }, array_slice(array_values($filtered), 0, 20));

        $this->view->json(['users' => $results]);
    }

    public function create(): void
    {
        $this->view->display('teams.create', [
            'title' => 'Create Team - ServerManager',
        ]);
    }

    public function store(): void
    {
        $validator = new Validator();
        $rules = [
            'name' => 'required|min:2|max:100',
            'description' => 'max:500',
        ];

        if (!$validator->validate($_POST, $rules)) {
            Session::setFlash('error', $validator->getFirstError());
            $this->view->redirect('/teams/create');
        }

        $id = $this->teamModel->create([
            'name' => $_POST['name'],
            'description' => $_POST['description'] ?? '',
        ]);

        $this->auditService->log('team_created', 'team', $id, [
            'name' => $_POST['name'],
        ]);

        Session::setFlash('success', 'Team created successfully.');
        $this->view->redirect('/teams');
    }

    public function show(int $id): void
    {
        $userId = (int) Session::get('user_id');
        $team = $this->teamModel->findById($id);

        if (!$team || (int) $team['created_by'] !== $userId) {
            $this->view->error(404);
        }

        $members = $this->teamModel->getMembers($id);
        $servers = $this->teamModel->getServers($id);

        $userModel = new User();
        $allUsers = $userModel->getAll(1, 999);
        $memberIds = array_map(fn($m) => $m['user_id'], $members);
        $availableUsers = array_filter($allUsers['data'], fn($u) => !in_array((int) $u['id'], $memberIds, true));

        $userId = (int) Session::get('user_id');
        $ownedServers = $this->serverModel->getOwnedServers($userId);
        $serverIds = array_map(fn($s) => (int) $s['id'], $servers);
        $availableServers = array_filter($ownedServers, fn($s) => !in_array((int) $s['id'], $serverIds, true));

        $this->view->display('teams.show', [
            'title' => $team['name'] . ' - Teams - ServerManager',
            'team' => $team,
            'members' => $members,
            'servers' => $servers,
            'availableUsers' => $availableUsers,
            'availableServers' => $availableServers,
        ]);
    }

    public function update(int $id): void
    {
        $userId = (int) Session::get('user_id');
        $team = $this->teamModel->findById($id);

        if (!$team || (int) $team['created_by'] !== $userId) {
            $this->view->json(['success' => false, 'message' => 'Team not found'], 404);
        }

        $validator = new Validator();
        $rules = [
            'name' => 'required|min:2|max:100',
            'description' => 'max:500',
        ];

        if (!$validator->validate($_POST, $rules)) {
            $this->view->json(['success' => false, 'message' => $validator->getFirstError()]);
        }

        $this->teamModel->update($id, [
            'name' => $_POST['name'],
            'description' => $_POST['description'] ?? '',
        ]);

        $this->auditService->log('team_updated', 'team', $id, [
            'name' => $_POST['name'],
        ]);

        $this->view->json(['success' => true, 'message' => 'Team updated.']);
    }

    public function delete(int $id): void
    {
        $userId = (int) Session::get('user_id');
        $team = $this->teamModel->findById($id);

        if (!$team || (int) $team['created_by'] !== $userId) {
            $this->view->json(['success' => false, 'message' => 'Team not found'], 404);
        }

        $this->teamModel->delete($id);

        $this->auditService->log('team_deleted', 'team', $id, [
            'name' => $team['name'],
        ]);

        Session::setFlash('success', 'Team deleted.');
        $this->view->redirect('/teams');
    }

    public function addUser(int $id): void
    {
        $userId = (int) Session::get('user_id');
        $team = $this->teamModel->findById($id);

        if (!$team || (int) $team['created_by'] !== $userId) {
            $this->view->json(['success' => false, 'message' => 'Team not found'], 404);
        }

        $userId = (int) ($_POST['user_id'] ?? 0);
        if ($userId <= 0) {
            $this->view->json(['success' => false, 'message' => 'Invalid user']);
        }

        if ($this->teamModel->addMember($id, $userId)) {
            $this->auditService->log('team_user_added', 'team', $id, [
                'user_id' => $userId,
            ]);
            $this->view->json(['success' => true, 'message' => 'User added to team.']);
        }

        $this->view->json(['success' => false, 'message' => 'User is already in this team.']);
    }

    public function removeUser(int $id): void
    {
        $userId = (int) Session::get('user_id');
        $team = $this->teamModel->findById($id);

        if (!$team || (int) $team['created_by'] !== $userId) {
            $this->view->json(['success' => false, 'message' => 'Team not found'], 404);
        }

        $userId = (int) ($_POST['user_id'] ?? 0);
        if ($userId <= 0) {
            $this->view->json(['success' => false, 'message' => 'Invalid user']);
        }

        $this->teamModel->removeMember($id, $userId);

        $this->auditService->log('team_user_removed', 'team', $id, [
            'user_id' => $userId,
        ]);

        $this->view->json(['success' => true, 'message' => 'User removed from team.']);
    }

    public function addServer(int $id): void
    {
        $userId = (int) Session::get('user_id');
        $team = $this->teamModel->findById($id);

        if (!$team || (int) $team['created_by'] !== $userId) {
            $this->view->json(['success' => false, 'message' => 'Team not found'], 404);
        }

        $serverId = (int) ($_POST['server_id'] ?? 0);
        $role = $_POST['role'] ?? 'viewer';

        if ($serverId <= 0) {
            $this->view->json(['success' => false, 'message' => 'Invalid server']);
        }

        if (!in_array($role, ['viewer', 'manager'], true)) {
            $this->view->json(['success' => false, 'message' => 'Invalid role']);
        }

        $userId = (int) Session::get('user_id');
        $server = $this->serverModel->findById($serverId);
        if (!$server || (int) $server['created_by'] !== $userId) {
            $this->view->json(['success' => false, 'message' => 'Server not found or not owned by you'], 404);
        }

        if ($this->teamModel->addServer($id, $serverId, $role)) {
            $this->auditService->log('team_server_added', 'team', $id, [
                'server_id' => $serverId,
                'role' => $role,
            ]);
            $this->view->json(['success' => true, 'message' => 'Server assigned to team.']);
        }

        $this->view->json(['success' => false, 'message' => 'Server is already assigned to this team.']);
    }

    public function removeServer(int $id): void
    {
        $userId = (int) Session::get('user_id');
        $team = $this->teamModel->findById($id);

        if (!$team || (int) $team['created_by'] !== $userId) {
            $this->view->json(['success' => false, 'message' => 'Team not found'], 404);
        }

        $serverId = (int) ($_POST['server_id'] ?? 0);
        if ($serverId <= 0) {
            $this->view->json(['success' => false, 'message' => 'Invalid server']);
        }

        $this->teamModel->removeServer($id, $serverId);

        $this->auditService->log('team_server_removed', 'team', $id, [
            'server_id' => $serverId,
        ]);

        $this->view->json(['success' => true, 'message' => 'Server removed from team.']);
    }

    public function updateServerRole(int $id): void
    {
        $userId = (int) Session::get('user_id');
        $team = $this->teamModel->findById($id);

        if (!$team || (int) $team['created_by'] !== $userId) {
            $this->view->json(['success' => false, 'message' => 'Team not found'], 404);
        }

        $serverId = (int) ($_POST['server_id'] ?? 0);
        $role = $_POST['role'] ?? 'viewer';

        if ($serverId <= 0) {
            $this->view->json(['success' => false, 'message' => 'Invalid server']);
        }

        if (!in_array($role, ['viewer', 'manager'], true)) {
            $this->view->json(['success' => false, 'message' => 'Invalid role']);
        }

        $this->teamModel->updateServerRole($id, $serverId, $role);

        $this->auditService->log('team_server_role_updated', 'team', $id, [
            'server_id' => $serverId,
            'role' => $role,
        ]);

        $this->view->json(['success' => true, 'message' => 'Server role updated.']);
    }
}
