<?php
/********************************************************************************
 * (c)1337 aheadware.com - All rights reserved
 ********************************************************************************/

/**
 * Class TB_Shared_Ent_TeamData_Attendee
 *
 * @property integer $id
 * @property integer $appointment_id
 * @property integer $profile_id
 * @property string $status
 * @property string $has_attended
 * @property integer $set_by_profile_id
 * @property integer|NULL $contract_id
 * @property DateTime $last_update_dt
 * @property DateTime $created_dt
 *
 */
class TB_Shared_Ent_TeamData_Attendee extends Francis_Db_Row {

    // Invitation status
    const STATUS_ACCEPTED = 'accepted';
    const STATUS_DECLINED = 'declined';
    const STATUS_WAITING = 'waiting';

    const HAS_ATTENDED = 'attended';
    const HAS_NOT_ATTENDED = 'not_attended';

    /**
     * @return array
     */
    public static function getValidStatus() {
        return array(
            self::STATUS_ACCEPTED,
            self::STATUS_DECLINED,
            self::STATUS_WAITING
        );
    }

    /**
     * Get attendee status of given appointment
     *
     * @param integer $appointmentId
     * @return array TB_Shared_Ent_TeamData_Attendee[]
     */
    public static function getByAppointmentId( $appointmentId )
    {
        $sql = 'SELECT * FROM ' . self::getTable() . ' WHERE appointment_id = :appointment_id ';
        return self::findMany( $sql, array( ':appointment_id' => $appointmentId ) );
    }

    /**
     * @param $appointmentId
     * @param $profileId
     * @return bool
     */
    public static function deleteByAppointmentIdAndProfileId( $appointmentId, $profileId )
    {
        $sql = 'DELETE FROM ' . self::getTable() . ' WHERE profile_id = :profile_id AND appointment_id = :appointment_id LIMIT 1';
        return self::execute( $sql, array( ':profile_id' => $profileId, ':appointment_id' => $appointmentId ) );
    }

    public static function getWithProfileDataByAppointmentId( $appointmentId )
    {
        $dbh = self::getDbh();
        $sql  = 'SELECT a.status AS status, a.has_attended AS has_attended, ';
        $sql .= 'a.last_update_dt as status_last_update_de, a.profile_id, a.set_by_profile_id ';
        $sql .= 'p.* FROM ' . self::getTable() . ' AS a ';
        $sql .= 'LEFT JOIN ' . TB_Shared_Ent_TeamData_Profile::getTable() . ' AS p ';
        $sql .= 'ON p.id = a.profile_id ';
        $sql .= 'WHERE a.appointment_id = :appointment_id ';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array(
            ':appointment_id' => $appointmentId
        ));
        $res = $stmt->fetchAll( PDO::FETCH_ASSOC );
        return $res;
    }

    public static function getAttendeesWithStatusForAppointmentId( $appointmentId, $status )
    {
        $sql = 'SELECT * FROM ' . self::getTable() . ' WHERE appointment_id = :appointment_id ';
        $sql .= 'AND status = :status ';
        $sql .= 'ORDER BY last_update_dt ASC';
        return self::findMany( $sql, array( ':appointment_id' => $appointmentId, ':status' => $status ) );
    }

    /**
     * @param $appointmentId
     * @return NULL|TB_Shared_Ent_TeamData_Attendee
     */
    public static function getNextOnWaitingList( $appointmentId )
    {
        $sql = 'SELECT * FROM ' . self::getTable() . ' WHERE appointment_id = :appointment_id ';
        $sql .= 'AND status = :status ORDER BY last_update_dt ASC LIMIT 1 ';
        return self::findOne( $sql, array( ':appointment_id' => $appointmentId, ':status' => self::STATUS_WAITING) );
    }

    /**
     * Find attendee entry for appointement+profile ids
     *
     * @param integer $appointmentId
     * @param integer $profileId
     */
    public static function getByAppointmentIdAndProfileId( $appointmentId, $profileId ) {
        $sql  = 'SELECT * FROM ' . self::getTable() . ' WHERE appointment_id = :appointment_id ';
        $sql .= 'AND profile_id = :profile_id LIMIT 1';
        return self::findOne( $sql, array( ':appointment_id' => $appointmentId, ':profile_id' => $profileId ) );
    }

    /**
     * Deletes all attendees for given appointment id
     *
     * @param int $appointmentId
     */
    public static function deleteAllForAppointmentId( $appointmentId ) {
        $sql = 'DELETE FROM ' . self::getTable() . ' WHERE appointment_id = :appointment_id';
        return self::execute( $sql, array( ':appointment_id' => $appointmentId ) );
    }

    /**
     * Deletes all statuses of given profile id
     *
     * @param $profileId
     * @return bool
     */
    public static function deleteAllForProfileId( $profileId ) {
        $sql = 'DELETE FROM ' . self::getTable() . ' WHERE profile_id = :profile_id';
        return self::execute( $sql, array( ':profile_id' => $profileId ) );
    }


    public static function getAttendancesForContractId( $contractId )
    {
        $sql = 'SELECT * FROM ' . self::getTable() . ' WHERE contract_id = :contract_id ';
        return self::findMany( $sql, array( ':contract_id' => $contractId ) );
    }

    public static function getAppointmentIdsForContractId( $contractId )
    {
        $dbh = self::getDbh();
        $sql = 'SELECT appointment_id FROM ' . self::getTable() . ' WHERE contract_id = :contract_id';
        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array(
            ':contract_id' => $contractId
        ));
        $res = $stmt->fetchAll( PDO::FETCH_COLUMN );
        return $res;
    }

    public static function getStatsOfAcceptedAttendancesForTeamId( $teamId )
    {
        $dbh = self::getDbh();

        $sql  = 'SELECT DATE( app.start_dt ) AS accept_date, COUNT( a.id ) as cnt ';
        $sql .= 'FROM attendee AS a INNER JOIN appointment AS app ON (a.`appointment_id` = app.`id`) ';
        $sql .= 'WHERE app.`team_id` = :team_id AND ';
        $sql .= 'a.has_attended = "attended" AND ';
        $sql .= 'app.state = "open" AND ';
        $sql .= 'app.`start_dt` BETWEEN CURDATE() - INTERVAL 30 DAY AND CURDATE() ';
        $sql .= 'GROUP BY accept_date ';

        $stmt = $dbh->prepare( $sql );
        $stmt->execute( array(
            ':team_id' => $teamId
        ));
        $res = $stmt->fetchAll( PDO::FETCH_ASSOC );
        return $res;

    }

    /**
     * Called on contract deletion
     * @param $contractId
     */
    public static function removeContractId( $contractId, $profileId = NULL, $teamId = NULL )
    {
        $contractId = +$contractId;

        $params = array(
            ':contract_id' => $contractId
        );

        if ( $contractId <= 0 && $profileId === NULL && $teamId === NULL )
        {
            throw new \Exception( 'Contract removals of fake contracts require a profile and teamId' );
        }

        $sql = '';

        // Note
        // If we deal with a valid contractId we can simplify the SQL statement
        // plus:
        if ( $contractId > 0)
        {
            $sql .= 'UPDATE ' . self::getTable() . ' SET contract_id = NULL ';
            $sql .= 'WHERE contract_id = :contract_id ';
            self::execute( $sql, $params );
        }
        else
        {
            $dbh = self::getDbh();
            $sql  = 'SELECT app.id FROM appointment app, attendee att WHERE ';
            $sql .= 'att.appointment_id = app.id AND ';
            $sql .= 'att.profile_id = :profile_id AND ';
            $sql .= 'app.team_id = :team_id';
            $stmt = $dbh->prepare( $sql );
            $stmt->execute( array( ':profile_id' => $profileId, ':team_id' => $teamId )  );
            $appIds = $stmt->fetchAll( PDO::FETCH_COLUMN, 0 );


            $params[ ':profile_id' ] = $profileId;

            $in = "";
            $i = 0;
            foreach ( $appIds as $item )
            {
                $key = ":id".$i++;
                $in .= "$key,";
                $in_params[$key] = $item;
            }

            $in = rtrim($in,",");

            $sql  = 'UPDATE ' . self::getTable() . ' SET contract_id = NULL ';
            $sql .= 'WHERE contract_id = :contract_id ';
            $sql .= 'AND profile_id = :profile_id ';
            $sql .= "AND appointment_id IN ($in)";

            $stmt = $dbh->prepare( $sql );
            $stmt->execute( array_merge( $params, $in_params ) );
        }
    }

    /**
     * Return table name
     *
     * @return null|string
     */
    public static function getTable() {
        return 'attendee';
    }

    /**
     * Return db handler
     *
     * @return Francis_Db_MySql|null
     */
    public static function getDbh() {
        return TB_Shared_Db_TeamData::get();
    }
}