<?php

declare(strict_types=1);

namespace App\Modules\Workspace;

use App\Core\BaseController;
use App\Core\Request;
use App\Core\Session;
use App\Core\Database;

/**
 * AdminCrewController — Manages Couple Users, Crew Users, and many-to-many Workspace Assignments (RC-016B)
 */
class AdminCrewController extends BaseController
{
    protected string $layout = 'admin';

    /**
     * List all Couple Owner accounts.
     */
    public function couplesList(Request $request): void
    {
        $db = Database::getConnection();
        $stmt = $db->query('
            SELECT u.id, u.username, u.email, u.display_name, u.is_active, w.groom_name, w.bride_name, w.slug 
            FROM users u
            JOIN workspaces w ON u.workspace_id = w.id
            WHERE u.role_id = 2
            ORDER BY u.id DESC
        ');
        $couples = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $this->render('admin/couples_list', [
            'title' => 'Couple Owner Accounts',
            'couples' => $couples
        ]);
    }

    /**
     * Toggle status (active/inactive) of a Couple user.
     */
    public function toggleCoupleStatus(Request $request): void
    {
        $id = (int) $request->param('id');
        $db = Database::getConnection();
        
        $stmt = $db->prepare('SELECT is_active FROM users WHERE id = ? AND role_id = 2');
        $stmt->execute([$id]);
        $user = $stmt->fetch();

        if ($user) {
            $newStatus = $user['is_active'] ? 0 : 1;
            $stmtUpdate = $db->prepare('UPDATE users SET is_active = ? WHERE id = ?');
            $stmtUpdate->execute([$newStatus, $id]);
            $this->flash('success', 'Couple account status updated successfully.');
        } else {
            $this->flash('error', 'Couple user account not found.');
        }

        $this->redirect('/app/admin/couples');
    }

    /**
     * List all Crew Accounts and allow creating new ones.
     */
    public function crewsList(Request $request): void
    {
        $db = Database::getConnection();
        $stmt = $db->query('
            SELECT u.id, u.username, u.email, u.display_name, u.is_active, COUNT(ca.workspace_id) as workspace_count
            FROM users u
            LEFT JOIN crew_accounts ca ON ca.user_id = u.id AND ca.is_active = 1
            WHERE u.role_id = 3
            GROUP BY u.id
            ORDER BY u.id DESC
        ');
        $crews = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $this->render('admin/crew_list', [
            'title' => 'Crew Accounts Management',
            'crews' => $crews,
            'errors' => Session::get('errors') ?? [],
            'old' => Session::get('old_input') ?? []
        ]);
        Session::set('errors', null);
        Session::set('old_input', null);
    }

    /**
     * Create a new Crew Account.
     */
    public function createCrew(Request $request): void
    {
        $username = trim((string) ($request->post('username') ?? ''));
        $displayName = trim((string) ($request->post('display_name') ?? ''));
        $email = trim((string) ($request->post('email') ?? ''));
        $password = (string) $request->post('password');

        $errors = [];
        if ($username === '') {
            $errors['username'] = 'Username is required.';
        }
        if ($displayName === '') {
            $errors['display_name'] = 'Display Name is required.';
        }
        if ($email === '') {
            $errors['email'] = 'Email is required.';
        }
        if ($password === '') {
            $errors['password'] = 'Password is required.';
        }

        $db = Database::getConnection();

        // Unique checks
        if ($username !== '') {
            $stmt = $db->prepare('SELECT id FROM users WHERE username = ? LIMIT 1');
            $stmt->execute([$username]);
            if ($stmt->fetch()) {
                $errors['username'] = 'Username is already taken.';
            }
        }
        if ($email !== '') {
            $stmt = $db->prepare('SELECT id FROM users WHERE email = ? LIMIT 1');
            $stmt->execute([$email]);
            if ($stmt->fetch()) {
                $errors['email'] = 'Email address is already registered.';
            }
        }

        if (!empty($errors)) {
            Session::set('errors', $errors);
            Session::set('old_input', $request->allPost());
            $this->redirect('/app/admin/crews');
            return;
        }

        $passwordHash = password_hash($password, PASSWORD_DEFAULT);

        $stmtInsert = $db->prepare('
            INSERT INTO users (role_id, email, username, display_name, password_hash, is_active, workspace_id)
            VALUES (3, ?, ?, ?, ?, 1, NULL)
        ');
        $stmtInsert->execute([$email, $username, $displayName, $passwordHash]);

        $this->flash('success', "Crew account for '{$displayName}' has been created successfully.");
        $this->redirect('/app/admin/crews');
    }

    /**
     * Show Workspace assignments page.
     */
    public function assignmentsList(Request $request): void
    {
        $db = Database::getConnection();

        // 1. Fetch all Crew users
        $stmt = $db->query('SELECT id, username, display_name FROM users WHERE role_id = 3 AND is_active = 1');
        $crews = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        // 2. Fetch all Workspaces
        $stmt = $db->query('SELECT id, groom_name, bride_name, slug FROM workspaces ORDER BY id DESC');
        $workspaces = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        // 3. Fetch all current crew workspace assignments
        $stmt = $db->query('
            SELECT ca.user_id, ca.workspace_id, w.groom_name, w.bride_name
            FROM crew_accounts ca
            JOIN workspaces w ON ca.workspace_id = w.id
            WHERE ca.is_active = 1
        ');
        $assignments = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        // Group assignments by crew ID for view convenience
        $assignmentsByCrew = [];
        foreach ($assignments as $asg) {
            $assignmentsByCrew[(int) $asg['user_id']][] = $asg;
        }

        $this->render('admin/crew_assignments', [
            'title' => 'Crew Workspace Assignments',
            'crews' => $crews,
            'workspaces' => $workspaces,
            'assignmentsByCrew' => $assignmentsByCrew
        ]);
    }

    /**
     * Save Crew workspace assignments.
     */
    public function saveAssignments(Request $request): void
    {
        $crewId = (int) $request->post('crew_id');
        $workspaceIds = $request->post('workspace_ids') ?? [];

        if ($crewId <= 0) {
            $this->flash('error', 'Invalid crew operator selected.');
            $this->redirect('/app/admin/crews/assignments');
            return;
        }

        $db = Database::getConnection();
        $db->beginTransaction();

        try {
            // Delete existing assignments for this crew member
            $stmtDel = $db->prepare('DELETE FROM crew_accounts WHERE user_id = ?');
            $stmtDel->execute([$crewId]);

            // Insert new assignments
            if (!empty($workspaceIds)) {
                $stmtUser = $db->prepare('SELECT display_name, username FROM users WHERE id = ?');
                $stmtUser->execute([$crewId]);
                $crewUser = $stmtUser->fetch(\PDO::FETCH_ASSOC);
                $crewName = $crewUser ? ($crewUser['display_name'] ?: $crewUser['username']) : 'Crew';

                foreach ($workspaceIds as $wsId) {
                    $wsId = (int) $wsId;
                    if ($wsId > 0) {
                        $stmtIns = $db->prepare('
                            INSERT INTO crew_accounts (workspace_id, user_id, display_name, desk_label, is_active)
                            VALUES (?, ?, ?, ?, 1)
                        ');
                        $stmtIns->execute([$wsId, $crewId, $crewName, 'Desk']);
                    }
                }
            }

            $db->commit();
            $this->flash('success', 'Crew workspace assignments updated successfully.');
        } catch (\Throwable $e) {
            if ($db->inTransaction()) {
                $db->rollBack();
            }
            $this->flash('error', 'Failed to save assignments: ' . $e->getMessage());
        }

        $this->redirect('/app/admin/crews/assignments');
    }
}
