<?php

namespace App\Http\Requests\Metrics;

use Illuminate\Validation\Rule;
use App\Services\DataConnectionService;
use Illuminate\Foundation\Http\FormRequest;
use App\Services\DataConnectionTablesService;

class DataStepUpdateRequest extends FormRequest
{
    private $dataConnectionService;
    private $dataConnectionTablesService;
    protected $stopOnFirstFailure = true;

    public function __construct(DataConnectionService $dataConnectionService, DataConnectionTablesService $dataConnectionTablesService)
    {
        parent::__construct();

        $this->dataConnectionService       = $dataConnectionService;
        $this->dataConnectionTablesService = $dataConnectionTablesService;
    }

    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        $connection = $this->route('metric')->getConnectionAsString();
        return [
            "performance_data_table" => ["bail", "required"],
            "calculation_column"     => ["required"],

            "function"               => ["required", function ($attribute, $value, $fail) {

                if (!is_null($this->input("calculation_column")) && !is_null($this->input('performance_data_table'))) {

                    $columnName      = $this->input("calculation_column");
                    $nonNumericCount = $this->getConnection()->table($this->input('performance_data_table'))
                        ->whereRaw("NOT {$columnName} REGEXP '^[-+]?([0-9]+\\.?[0-9]*|\\.[0-9]+)([eE][-+]?[0-9]+)?$'")
                        ->whereNotNull($columnName)
                        ->count();

                    if (!in_array($value, ["count", "distinct_count", 'conditional_count']) && $nonNumericCount > 0) {
                        $fail(trans('metrics.validations.required.The selected function can only be applied to numeric columns'));
                    }

                }

            }

            ],

            "metric_direction"       => ["required", "in:increase,decrease"],

            "filtration_column"      => ["bail", Rule::requiredIf(function () {
                $conditional_functions = [
                    "conditional_count",
                    "conditional_sum",
                    "conditional_average",
                    "conditional_max",
                    "conditional_min"
                ];

                return in_array($this->input('function'), $conditional_functions);
            })],

            "filtration_value"       => ["bail", Rule::requiredIf(function () {

                $conditional_functions = [
                    "conditional_count",
                    "conditional_sum",
                    "conditional_average",
                    "conditional_max",
                    "conditional_min"
                ];

                return in_array($this->input('function'), $conditional_functions);
            })],

            "date_filter_column"     => ["bail", Rule::requiredIf($this->input('date_range') != "all_time")],

            "date_range"             => ["bail", "required"],

            "display_format"         => ["bail", "required", function ($attribute, $value, $fail) {

                if ($this->getValueFromMetricSessionOrDB("metric_type") == "gauge_chart" && !in_array($this->input("display_format"), ["percentage", "percentage_of_total"]) && $this->input("compare_with") == "no_comparison") {
                    $fail(trans("metrics.validations.required.Given that the metric type is a 'gauge chart,'"));
                }

            }

            ],

            "custom_unit_input"      => ['nullable',
                'required_if:display_format,compact_currency,standard_currency,numeric_with_custom_unit'],

            "compare_with"           => ["bail", "required", function ($attribute, $value, $fail) {

                if (!is_null($this->input('date_range')) && $this->input("date_range") == "all_time"
                    && !is_null($this->input('compare_with')) && in_array($this->input('compare_with'), ["compare_with_preceding_period", "compare_with_same_time_last_year"])) {
                    $fail(trans("metrics.validations.required.Since you've chosen the All time date range"));
                }

            }

            ],
            "target_value_input"     => ["bail", "required_if:compare_with,compare_with_a_fixed_target_value"],

            "drill_down"             => ["nullable"],

            "drill_down_columns"     => ["required_if_accepted:drill_down"]

        ];
    }

    public function messages()
    {
        $messages = [
            "performance_data_table.required"         => trans('metrics.validations.required.performance_data_table'),
            "calculation_column.required"             => trans('metrics.validations.required.calculation_column'),
            "date_filter_column.required"             => trans('metrics.validations.required.Kindly choose a date filter column'),
            "target_value_input.required_if"          => trans('metrics.validations.required.Since youve selected compare with a fixed target'),
            "drill_down_columns.required_if_accepted" => trans('metrics.validations.required.drill_down_columns'),
            "filtration_column.required"              => trans('metrics.validations.required.filtration_column'),
            "filtration_value.required"               => trans('metrics.validations.required.filtration_value')

        ];

        if (in_array($this->input('display_format'), ['compact_currency', 'standard_currency'])) {
            $messages["custom_unit_input.required_if"] = trans("metrics.validations.required.Please enter the preferred currency to display with the KPI");
        }

        if ($this->input('display_format') == 'numeric_with_custom_unit') {
            $messages["custom_unit_input.required_if"] = trans("metrics.validations.required.Please enter the custom unit to display with the KPI");
        }

        return $messages;
    }

    public function withValidator($validator)
    {
        $validator->stopOnFirstFailure();
    }

    public function getConnection()
    {
        $connection = $this->route('metric')->getConnectionAsString();
        return $this->dataConnectionService->getConnection($connection);
    }

    public function getValueFromMetricSessionOrDB($value)
    {
        $chart = $this->route('metric');

        if (isset(session('metric_session_wizard_configuration')[$value])) {
            return session('metric_session_wizard_configuration')[$value];
        } else {
            return $metric->getResourceConfiguration($value);
        }

    }

}
