<?php

declare(strict_types=1);

namespace App\Modules\Interaction;

use App\Core\Database;

/**
 * InteractionModel — Database updates for guest RSVPs and wishes.
 *
 * Scopes queries and writes strictly to the workspace context.
 *
 * @package Inveetaire
 * @ref     PILOT-005
 */
class InteractionModel
{
    /**
     * Look up a workspace by slug.
     *
     * @param string $slug
     * @return array|null Workspace row or null.
     */
    public function getWorkspaceBySlug(string $slug): ?array
    {
        $db = Database::getConnection();
        $stmt = $db->prepare('
            SELECT id, slug, workspace_status 
            FROM workspaces 
            WHERE slug = :slug
            LIMIT 1
        ');
        $stmt->execute(['slug' => $slug]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
        return $row !== false ? $row : null;
    }

    /**
     * Look up a guest by token.
     *
     * @param int    $workspaceId
     * @param string $token
     * @return array|null Guest row or null.
     */
    public function getGuestByToken(int $workspaceId, string $token): ?array
    {
        $db = Database::getConnection();
        $stmt = $db->prepare('
            SELECT id, workspace_id, guest_code, full_name, invited_pax, rsvp_status 
            FROM guests 
            WHERE workspace_id = :workspace_id 
              AND guest_code = :token
            LIMIT 1
        ');
        $stmt->execute([
            'workspace_id' => $workspaceId,
            'token'        => $token
        ]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
        return $row !== false ? $row : null;
    }

    /**
     * Retrieve active invitation configuration for a workspace.
     *
     * @param int $workspaceId
     * @return array|null
     */
    public function getInvitationByWorkspace(int $workspaceId): ?array
    {
        $db = Database::getConnection();
        $stmt = $db->prepare('
            SELECT id, workspace_id, invitation_status, rsvp_enabled, rsvp_closes_at, rsvp_allow_edit
            FROM invitations 
            WHERE workspace_id = :workspace_id
            LIMIT 1
        ');
        $stmt->execute(['workspace_id' => $workspaceId]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
        return $row !== false ? $row : null;
    }

    /**
     * Retrieve existing RSVP for a guest.
     *
     * @param int $guestId
     * @return array|null
     */
    public function getGuestRsvp(int $guestId): ?array
    {
        $db = Database::getConnection();
        $stmt = $db->prepare('
            SELECT id, guest_id, workspace_id, response, confirmed_pax, message, submitted_at, updated_at
            FROM rsvps
            WHERE guest_id = :guest_id
            LIMIT 1
        ');
        $stmt->execute(['guest_id' => $guestId]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
        return $row !== false ? $row : null;
    }

    /**
     * Upsert (insert or overwrite update) a guest RSVP record.
     *
     * @param int         $workspaceId
     * @param int         $guestId
     * @param string      $response     'attending' | 'declined'
     * @param int         $confirmedPax Number of attendees.
     * @param string|null $message      Optional guest notes.
     * @return void
     */
    public function upsertRsvp(int $workspaceId, int $guestId, string $response, int $confirmedPax, ?string $message = null): void
    {
        $db = Database::getConnection();

        // Check if RSVP already exists for this guest
        $stmtCheck = $db->prepare('SELECT id FROM rsvps WHERE guest_id = :guest_id LIMIT 1');
        $stmtCheck->execute(['guest_id' => $guestId]);
        $exists = $stmtCheck->fetchColumn();

        if ($exists) {
            // Update
            $stmtUpdate = $db->prepare('
                UPDATE rsvps 
                SET response = :response, 
                    confirmed_pax = :pax, 
                    message = :message,
                    updated_at = CURRENT_TIMESTAMP 
                WHERE guest_id = :guest_id 
                  AND workspace_id = :workspace_id
            ');
            $stmtUpdate->execute([
                'response'     => $response,
                'pax'          => $confirmedPax,
                'message'      => $message,
                'guest_id'     => $guestId,
                'workspace_id' => $workspaceId
            ]);
        } else {
            // Insert
            $stmtInsert = $db->prepare('
                INSERT INTO rsvps (guest_id, workspace_id, response, confirmed_pax, message, submitted_at) 
                VALUES (:guest_id, :workspace_id, :response, :pax, :message, CURRENT_TIMESTAMP)
            ');
            $stmtInsert->execute([
                'guest_id'     => $guestId,
                'workspace_id' => $workspaceId,
                'response'     => $response,
                'pax'          => $confirmedPax,
                'message'      => $message
            ]);
        }
    }

    /**
     * Sync RSVP response state back to the guests table.
     *
     * @param int    $workspaceId
     * @param int    $guestId
     * @param string $rsvpStatus  'attending' | 'declined'
     * @return void
     */
    public function updateGuestRsvpStatus(int $workspaceId, int $guestId, string $rsvpStatus): void
    {
        $db = Database::getConnection();
        $stmt = $db->prepare('
            UPDATE guests 
            SET rsvp_status = :status, 
                updated_at = CURRENT_TIMESTAMP 
            WHERE id = :guest_id 
              AND workspace_id = :workspace_id
        ');
        $stmt->execute([
            'status'       => $rsvpStatus,
            'guest_id'     => $guestId,
            'workspace_id' => $workspaceId
        ]);
    }

    /**
     * Upsert (insert or overwrite update) a guest wish message.
     *
     * @param int    $workspaceId
     * @param int    $guestId
     * @param string $senderName
     * @param string $message
     * @param string $status     'approved' | 'pending' | 'rejected'
     * @param bool   $isVisible  1 if approved, 0 if pending/rejected
     * @return void
     */
    public function upsertWish(
        int $workspaceId,
        int $guestId,
        string $senderName,
        string $message,
        string $status = 'approved',
        bool $isVisible = true
    ): void {
        $db = Database::getConnection();

        // Check if wish already exists for this guest
        $stmtCheck = $db->prepare('SELECT id FROM wishes WHERE guest_id = :guest_id LIMIT 1');
        $stmtCheck->execute(['guest_id' => $guestId]);
        $exists = $stmtCheck->fetchColumn();

        if ($exists) {
            // Update existing wish (One Guest = One Wish)
            $stmtUpdate = $db->prepare('
                UPDATE wishes 
                SET message = :message, 
                    sender_name = :sender,
                    status = :status,
                    is_visible = :is_visible,
                    submitted_at = CURRENT_TIMESTAMP
                WHERE guest_id = :guest_id 
                  AND workspace_id = :workspace_id
            ');
            $stmtUpdate->execute([
                'message'      => $message,
                'sender'       => $senderName,
                'status'       => $status,
                'is_visible'   => $isVisible ? 1 : 0,
                'guest_id'     => $guestId,
                'workspace_id' => $workspaceId
            ]);
        } else {
            // Insert new wish
            $stmtInsert = $db->prepare('
                INSERT INTO wishes (workspace_id, guest_id, sender_name, message, status, is_visible, submitted_at) 
                VALUES (:workspace_id, :guest_id, :sender, :message, :status, :is_visible, CURRENT_TIMESTAMP)
            ');
            $stmtInsert->execute([
                'workspace_id' => $workspaceId,
                'guest_id'     => $guestId,
                'sender'       => $senderName,
                'message'      => $message,
                'status'       => $status,
                'is_visible'   => $isVisible ? 1 : 0
            ]);
        }
    }
}
