""" Django settings for console project. """
import os
import sys

from celery.schedules import crontab
from django.utils.translation import gettext_lazy

from console.services.product import load_product_version

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

DEBUG = int(os.environ.get('DEBUG', '0')) > 0

# Program is started under testing framework
TEST_MODE = 'test' in sys.argv or 'pytest' in sys.modules or os.environ.get("TEST_MODE")

# Program is used by developer (human), i.e. loads additional debug software
DEV_MODE = DEBUG and not TEST_MODE

# False to disable access to admin control panel via web
ADMIN_PANEL_ENABLED = DEV_MODE

##################################
###          SECURITY          ###
##################################

CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
CORS_EXPOSE_HEADERS = ['Content-Disposition']

ALLOWED_HOSTS = ['*']

######################################
###          APPLICATIONS          ###
######################################

INSTALLED_APPS = [
    'django.forms',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework.authtoken',
    'django_json_widget',
    'solo',
    'django_celery_beat',
    'sequences.apps.SequencesConfig',
    'corsheaders',
    'django_filters',
    'channels',
]

PROJECT_APPS = [
    'assets.apps.AssetsConfig',
    'license_info.apps.LicenseInfoConfig',
    'perms.apps.PermsConfig',
    'console.apps.ConsoleConfig',
    'core.apps.CoreConfig',
    'correlation.apps.CorrelationConfig',
    'dashboard.apps.DashboardConfig',
    'company.apps.CompanyConfig',
    'ncircc.apps.NcirccConfig',
    'logstash.apps.LogstashConfig',
    'networkmap.apps.NetworkmapConfig',
    'users.apps.UsersConfig',
    'incident_export.apps.IncidentExportConfig',
    'storage.apps.StorageConfig',
    'incident.apps.IncidentConfig',
    'events.apps.EventsConfig',
    'rotation.apps.RotationConfig',
    'inputs.apps.InputsConfig',
    'devices.apps.DevicesConfig',
    'notifications.apps.NotificationsConfig',
]

INSTALLED_APPS += PROJECT_APPS

MIDDLEWARE = [
    'core.middleware.LicenseMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'core.middleware.TimezoneMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

########################################
###          AUTHENTICATION          ###
########################################

AUTHENTICATION_BACKENDS = [
    'core.backends.ConsoleAuthBackend.ConsoleAuthSystem',
    'django.contrib.auth.backends.ModelBackend',
]

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {
            'min_length': 8,
        }
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

##################################
###          DATABASE          ###
##################################

if not os.environ['POSTGRES_PORT']:
    os.environ['POSTGRES_PORT'] = '5432'
DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.postgresql",  # Project depends on postgre, so no way to change it from env
        'NAME': os.environ.get('POSTGRES_DB'),
        'USER': os.environ.get('POSTGRES_USER'),
        'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
        'HOST': os.environ.get('POSTGRES_HOST'),
        'PORT': os.environ.get('POSTGRES_PORT'),
    }
}

DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

#################################
###          LOGGING          ###
#################################

LOG_PATH = os.environ.get('LOG_PATH', os.path.join(BASE_DIR, 'dockerlogs'))
USER_LOG_FILENAME = os.environ.get('USER_LOG_FILENAME', 'console.log')
MIN_LOG_LEVEL = os.environ.get('MIN_LOG_LEVEL', 'DEBUG')
LOG_MAX_BYTES = int(os.environ.get('LOG_MAX_BYTES', 1024 * 1024 * 5))
LOG_BACKUP_COUNT = int(os.environ.get('LOG_BACKUP_COUNT', 500))

os.makedirs(LOG_PATH, exist_ok=True)
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'info_message': {
            'format': '%(asctime)s %(levelname)s %(message)s',
        },
        'debug_format': {
            'format': '%(asctime)s %(levelname)s %(filename)s %(funcName)s %(message)s'
        }
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'level': MIN_LOG_LEVEL,
        },
        'file': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(LOG_PATH, USER_LOG_FILENAME),
            'formatter': 'info_message',
            'encoding': 'utf-8',
            'maxBytes': LOG_MAX_BYTES,
            'backupCount': LOG_BACKUP_COUNT,
        },
    },
    'loggers': {
        '': {
            'handlers': ['file', 'console'],
            'level': MIN_LOG_LEVEL,
        },
    },
}

##############################################
###          INTERNATIONALIZATION          ###
##############################################

LANGUAGE_CODE = 'en'
LANGUAGES = [
    ('en', gettext_lazy('English')),
    ('ru', gettext_lazy('Russian')),
]

INITIAL_DATE_FORMAT = "Y-m-d"

# @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TIME_ZONE = os.environ.get('TIME_ZONE', 'UTC')
# Timezone used for users by default
DEFAULT_CURRENT_TIMEZONE = os.environ.get('DEFAULT_CURRENT_TIMEZONE', 'Europe/Moscow')

USE_I18N = True
USE_L10N = True
USE_TZ = True

LOCALE_PATHS = [
    os.path.join(BASE_DIR, 'locale')
]

###############################
###          FILES          ###
###############################

# Build paths for generated files like static inside the project like this: os.path.join(PUBLIC_DIR, ...)
PUBLIC_DIR = os.environ.get('PUBLIC_DIR', os.path.join(BASE_DIR, 'public'))

PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(PUBLIC_DIR, 'static')
MEDIA_ROOT = os.path.join(PUBLIC_DIR, 'media')

REDIS_HOST = os.environ.get('REDIS_HOST', 'redis')
REDIS_PORT = int(os.environ.get('REDIS_PORT', 6379))
REDIS_CACHE_TIMEOUT = 86400

###############################
###          CACHE          ###
###############################

SOLO_CACHE = 'local'
SOLO_CACHE_TIMEOUT = 60 * 5  # 5 mins
SOLO_CACHE_PREFIX = 'solo'

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    },
    'local': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    },
    'redis': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': f'redis://{REDIS_HOST}:{REDIS_PORT}/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient'
        }
    }
}

#############################
###          DRF          ###
#############################

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.OrderingFilter',
        'core.backends.filters.SearchAllFieldsBackend',
    ),
    'DEFAULT_PAGINATION_CLASS': 'core.services.pagination.BasicPagination',
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ],
}

################################
###          CELERY          ###
################################

CELERY_BROKER_URL = f'redis://{REDIS_HOST}:{REDIS_PORT}'
CELERY_RESULT_BACKEND = f'redis://{REDIS_HOST}:{REDIS_PORT}'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = TIME_ZONE
CELERY_IMPORTS = ['devices.tasks.firewall', 'devices.tasks.sensor']

""" Single place to setup at which time daily tasks should execute, crontab schedule object"""
DAILY_CRONTAB = crontab(minute='0', hour='1')
""" Single place to setup at which time weekly tasks should execute, crontab schedule object"""
WEEKLY_CRONTAB = crontab(minute='0', hour='1', day_of_week='1')
""" Single place to setup at which time monthly tasks should execute, crontab schedule object"""
MONTHLY_CRONTAB = crontab(minute='0', hour='1', day_of_month='1')
""" Execute every 2 minutes."""
EVERY_2_MINUTE = crontab(minute='*/2')

ROTATE_SIZE_CHECK_CRONTAB = crontab(minute='*/5')
CELERY_BEAT_SCHEDULE = {
    'update_statistics': {
        'task': 'dashboard.tasks.update_statistics_task',
        'schedule': crontab()
    },
    'expire_users': {
        'task': 'console.tasks.expire_users_task',
        'schedule': DAILY_CRONTAB
    },
    'update_auto_network_map_data': {
        'task': 'networkmap.tasks.update_auto_network_map_data',
        'schedule': crontab()
    },
    'update_firewall_info_task': {
        'task': 'devices.tasks.firewall.update_firewall_info_task',
        'schedule': crontab()
    },
    'update_amount_of_elk_events': {
        'task': 'console.tasks.update_amount_of_aggregated_events',
        'schedule': crontab()
    },
    'check_blocked_users': {
        'task': 'core.tasks.check_blocked_users',
        'schedule': crontab()
    },
    'update_status_notification': {
        'task': 'ncircc.tasks.update_status_notification',
        'schedule': crontab(),  # todo Уточнить точное время
    },
    'update_comments': {
        'task': 'ncircc.tasks.update_comments',
        'schedule': crontab(),  # todo Уточнить точное время
    },
    'ping_sensors': {
        'task': 'devices.tasks.sensor.ping_sensors',
        'schedule': crontab()
    },
    'get_disk_usage_task': {
        'task': 'core.tasks.get_disk_usage_task',
        'schedule': crontab()
    },
    'reboot_correlator_task': {
        'task': 'correlation.tasks.reboot_correlator_task',
        'schedule': EVERY_2_MINUTE,
    },

}

######################################
###          AMC SERVICES          ###
######################################

# LICENSE
LICENSE_CLIENT_URL = os.environ.get('LICENSE_CLIENT_URL', 'http://license-client:8050')
LICENSE_CACHE_TIMEOUT = 60 * 60  # 60 minutes
LICENSE_FEATURE_EVENT_PROCESSING = "event_processing"
LICENSE_OPTION_EVENT_SOURCE_COUNT = "event_sources"

# NGINX
NGINX_ENABLED_CONFIG_FILENAME = "armaconsole.nginx"
NGINX_HTTP_CONFIG_FILENAME = "armaconsole_http.nginx"
NGINX_HTTPS_CONFIG_FILENAME = "armaconsole_https.nginx"
NGINX_SITES_AVAILABLE = "/usr/local/armaconsole/nginx"

# CORRELATOR
CORRELATOR_SEVERITY_LEVEL = int(os.environ.get('CORRELATOR_SEVERITY_LEVEL', 6))
CORRELATOR_AUTO_CATEGORY_NAME = os.environ.get('CORRELATOR_AUTO_CATEGORY_NAME', gettext_lazy('Auto'))
CORRELATOR_URL = os.environ.get('CORRELATOR_URL', 'http://correlator:5566')

# VECTOR
LOGSTASH_CONFIG_DIR = os.environ.get('LOGSTASH_CONFIG_DIR', os.path.join(PUBLIC_DIR, 'vector'))

# ELASTICSEARCH
ELASTIC_URL = os.environ.get('ELASTIC_URL', 'http://elasticsearch:9200')
elk_split = ELASTIC_URL.replace('http://', '').split(':')
ELK_HOST = elk_split[0] if len(elk_split) >= 0 else 'elasticsearch'
ELK_PORT = elk_split[1] if len(elk_split) > 0 else 9200
ELK_LOGIN = os.environ.get('ELASTIC_USER', 'elastic')
ELK_PASS = os.environ.get('ELASTIC_PASSWORD', 'changeme')
ELK_MAX_ENTRIES = 100000
ELK_AGGREGATED_INDEX = 'aggregated-*'
ELK_FIREWALL_PRODUCT_NAME = 'Industrial Firerwall'  # Yes this is mistake, but it is how now Vector parses IF logs
ELK_ENDPOINT_PRODUCT_NAME = 'Industrial Endpoint'

# RABBITMQ
RABBIT_URL = os.environ.get('RABBIT_URL', 'http://rabbitmq-management:5672')
rabbit_split = RABBIT_URL.replace('http://', '').split(':')
RABBIT_HOST = rabbit_split[0] if len(rabbit_split) >= 0 else 'rabbitmq-management'
RABBIT_PORT = rabbit_split[1] if len(rabbit_split) > 0 else 5672

###############################
###          OTHER          ###
###############################

# ROUTING
ROOT_URLCONF = 'console.urls'
WSGI_APPLICATION = 'console.wsgi.application'
ASGI_APPLICATION = 'console.asgi.application'
LOGIN_REDIRECT_URL = 'index'
LOGOUT_REDIRECT_URL = 'login'
LOGIN_URL = 'login'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [(REDIS_HOST, REDIS_PORT)],
        },
    },
}

# TEMPLATES
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

# Site info must not contain dynamic data, only static values
SITE_INFO = {
    'domain': 'infowatch.ru',
    'name': 'InfoWatch ARMA',
    'package': 'armaconsole',  # Must be a valid deb package name
    'version': '1.4.0',  # Must be a valid deb package version
    'architecture': 'amd64',  # Must be a valid deb package architecture
    # These values are used in CEF format
    'vendor': 'InfoWatch ARMA',
    'product': 'ARMAMC'
}

# How many (in percent) keep in table while rotation occurs
# So 0.3 - means 30% of table will stay while rotation
SAVE_DURING_ROTATION = float(os.environ.get('SAVE_DURING_ROTATION', 0.3))

EMAIL_HOST_USER = 'console@arma.com'
EMAIL_HOST = 'localhost'

# GENERATE SELFSIGNED CERTIFICATE
TLS_CERT_DAYS = 365
TLS_CERT_KEY_SIZE = 2048
TLS_CERT_COUNTRY = "RU"
TLS_CERT_STATE = "Moscow"
TLS_CERT_LOCALITY = "Moscow"
TLS_CERT_ORIG_NAME = "ARMA"
TLS_CERT_UNIT_NAME = "Console"
TLS_CERT_COMMON_NAME = "iwarma.ru"
TLS_CERT_FILENAME = "/etc/nginx/ssl/armaconsole/nginx-selfsigned.crt"
TLS_CERT_KEY_FILENAME = "/etc/nginx/ssl/armaconsole/nginx-selfsigned.key"
# TODO: need use
TLS_CERT_DHPARAM_FILENAME = "/etc/nginx/ssl/armaconsole/dhparam.pem"

WEB_UI_PORT = int(os.environ.get('WEB_UI_PORT', 9090))
MAX_UPLOADSIZE = 80 * 1024 * 1024

# NCIRCC
NCIRCC_DOMAIN_NAME = os.environ.get('NCIRCC_DOMAIN_NAME', 'https://test-lk.cert.gov.ru')
NCIRCC_CERT_VERIFY = '/etc/ssl/certs/' if os.path.exists('/etc/ssl/certs/') else False

# Compatible ARMAIF versions
MINIMAL_COMPATIBLE_AIF_VERSION = "3.6"

MINIMAL_VERSION_CORRELATION_RULES = '1.3.4'

# Product version
PRODUCT_VERSION = load_product_version()
