<?php

namespace Ignite\Core\Models\Data;

use Exception;
use Ignite\Core\Contracts\Entities\Participant;
use Ignite\Core\Contracts\Entities\User;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use PDOException;

class UserParticipant
{
    /**
     * @var User
     */
    protected $user;

    /**
     * @var Participant
     */
    protected $participant;

    /**
     * A data transfer object to store the combination of a User model and Participant model.
     *
     * @param User $user
     * @param Participant $participant
     */
    public function __construct(User $user, Participant $participant)
    {
        $this->user = $user;
        $this->participant = $participant;
    }

    /**
     * @return $this
     * @throws Exception
     */
    public function save()
    {
        DB::beginTransaction();

        try {
            $this->user->save();

            $this->participant->user_id = $this->user->getKey();

            $this->participant->save();

            DB::commit();

            return $this;
        } catch (Exception $e) {
            DB::rollBack();

            if ($e instanceof QueryException) {
                throw new Exception("{$e->errorInfo[2]} - SQL: {$e->getSql()}", 0, $e);
            }

            if ($e instanceof PDOException) {
                throw new Exception("{$e->errorInfo[2]}", 0, $e);
            }

            throw new Exception($e->getMessage(), 0, $e);
        }
    }

    /**
     * The user instance.
     *
     * @return User
     */
    public function user()
    {
        return $this->user;
    }

    /**
     * The participant instance.
     *
     * @return Participant
     */
    public function participant()
    {
        return $this->participant;
    }

    /**
     * Set the user model as a relation of the participant.
     *
     * @return Participant
     */
    public function participantWithUser()
    {
        return $this->participant->setRelation('user', $this->user);
    }

    /**
     * Set the participant model as a relation of the user.
     *
     * @return User
     */
    public function userWithParticipant()
    {
        return $this->user->setRelation('participant', $this->participant);
    }
}
