<?php


/**
 * @uri /health-diagnostic/status
 */
class HealthStatus extends CfProtectedResource
{
    public function get($request)
    {
        $model = new HealthDiagnosticModel($this->username);

        $response = new Response($request);
        $response->body = json_encode($model->getHealthStatus());
        $response->code = Response::OK;

        return $response;
    }
}

/**
 * @uri /health-diagnostic/report_ids
 */
class HealthReports extends CfProtectedResource
{
    public function get($request)
    {
        $response = new Response($request);
        $response->body = json_encode(HealthDiagnosticReportModel::$reportTypes);
        $response->code = Response::OK;

        return $response;
    }
}

/**
 * @uri /health-diagnostic/report/:reportName
 */
class HealthReport extends CfProtectedResource
{
    public function post($request, $reportName)
    {
        $response = new Response($request);
        $model = new HealthDiagnosticReportModel($this->username, $reportName);
        $query = $model->getSql();

        try {
            $data = self::getRequestData($request);
        } catch (Exception $exception) {
            $response->code = Response::BADREQUEST;
            $response->body = $exception->getMessage();
            return $response;
        }

        $response->body = cfapi_query_post(
            $this->username,
            $query,
            $data->sortColumn ?? '',
            $data->sortDescending ?? false,
            $data->skip ?? -1,
            $data->limit ?? -1,
            $data->hostContextInclude ?? [],
            $data->hostContextExclude ?? []
        );
        $response->code = Response::OK;

        return $response;
    }

    public static function getRequestData($request)
    {
        $data = Utils::getValidJsonData($request->data);

        if (!isset($data->sortDescending)) {
            $data->sortDescending = false;
        }

        if (isset($data->skip)) {
            if (!is_int($data->skip)) {
                throw new Exception("'skip' field must be an integer");
            }
        } else {
            $data->skip = -1;
        }

        if (isset($data->limit)) {
            if (!is_int($data->limit)) {
                throw new Exception("'limit' field must be an integer");
            }
        } else {
            $data->limit = -1;
        }

        if (isset($data->hostContextInclude)) {
            if (!is_array($data->hostContextInclude)) {
                throw new Exception("'hostContextInclude' field must be an array");
            }
        } else {
            $data->hostContextInclude = [];
        }

        if (isset($data->hostContextExclude)) {
            if (!is_array($data->hostContextExclude)) {
                throw new Exception("'hostContextExclude' field must be an array");
            }
        } else {
            $data->hostContextExclude = [];
        }

        return $data;
    }
}

class RbacProtectedReports extends CfProtectedResource
{
    protected function process($request, HealthDiagnosticReportModel $model)
    {
        $response = new Response($request);
        $query = $model->getSql();

        try {
            $data = HealthReport::getRequestData($request);
        } catch (Exception $exception) {
            $response->code = Response::BADREQUEST;
            $response->body = $exception->getMessage();
            return $response;
        }

        $response->body = cfapi_query_post(
            $this->username,
            $query,
            $data->sortColumn ?? '',
            $data->sortDescending ?? false,
            $data->skip ?? -1,
            $data->limit ?? -1,
            $data->hostContextInclude ?? [],
            $data->hostContextExclude ?? [],
            false
        );
        $response->code = Response::OK;

        return $response;
    }
}

/**
 * @uri /health-diagnostic/report/hostsNeverCollected
 */
class HostsNeverCollectedReport extends RbacProtectedReports
{
    /**
     * @param $request
     * @return Response
     * @throws ResponseException
     *
     * @rbacName Access to `hosts never collected from` report
     * @rbacGroup Health Diagnostic
     * @rbacAlias HostsNeverCollectedReport.post
     */
    public function post($request)
    {
        $model = new HealthDiagnosticReportModel($this->username, BaseHealthDiagnostic::HOSTS_NEVER_COLLECTED_TYPE);
        return $this->process($request, $model);
    }
}

/**
 * @uri /health-diagnostic/report/deletedHostsReport
 */
class DeletedHostsReportHD extends RbacProtectedReports
{
    /**
     * @param $request
     * @return Response
     * @throws ResponseException
     *
     * @rbacName Access to `removed hosts still reporting` report
     * @rbacGroup Health Diagnostic
     * @rbacAlias deletedHostsReportHD.post
     */
    public function post($request)
    {
        $model = new HealthDiagnosticReportModel($this->username, BaseHealthDiagnostic::DELETED_HOSTS_REPORT_TYPE);
        return $this->process($request, $model);
    }
}

/**
 * @uri /health-diagnostic/dismiss/:reportName
 */
class HealthDismissed extends CfProtectedResource
{
    private $model;

    public function __construct($parameters)
    {
        parent::__construct($parameters);
        $this->model = new DismissHealthDiagnosticModel(CfdbPdo::getInstance()->getConnection(), $this->username);
    }

    public function get($request, $reportName)
    {
        $limit = Utils::queryParam('limit', $default = 0);
        $offset = Utils::queryParam('offset', $default = -1);
        $response = new Response($request);
        $response->body = $this->model->dismissedList($reportName, $limit, $offset);
        $response->code = Response::OK;
        return $response;
    }

    public function post($request, $reportName)
    {
        $data = Utils::getValidJsonData($request->data);
        $response = new Response($request);

        if (isset($data->hosts) && !is_array($data->hosts)) {
            $response->code = Response::BADREQUEST;
            $response->body = "'hosts' field must be an array";
            return $response;
        }

        $this->model->add($data->hosts, $reportName);
        $response->code = Response::CREATED;
        return $response;

    }

    public function delete($request, $reportName)
    {
        $data = Utils::getValidJsonData($request->data);
        $response = new Response($request);

        if (isset($data->hosts) && !is_array($data->hosts)) {
            $response->code = Response::BADREQUEST;
            $response->body = "'hosts' field must be an array";
            return $response;
        }

        $this->model->delete($data->hosts, $reportName);
        $response->code = Response::ACCEPTED;
        return $response;
    }
}
