# -*- coding: utf-8 -*-
"""DokoGen — настройки импорта из опросника (редактируемый словарь).

Идея: «что импортировать и откуда» хранится НЕ в коде, а в текстовом
JSON-файле рядом с программой (import_settings.json). При сборке .exe
файл остаётся редактируемым — можно править пути к ячейкам и ключевые
слова без пересборки.

Формат файла:
{
  "common_sheet_keyword": "общие",          // ключевое слово листа «Общие сведения»
  "employees_sheet_keyword": "сотруд",      // ключевое слово листа «Сотрудники»
  "is_sheet_exclude_keywords": ["общие сведения", "сотрудники"],  // листы, которые НЕ ИС
  "value_column": 1,                        // колонка значения (0=A, 1=B, ...)
  "fields": [
    {
      "name": "Полное наименование организации",   // человекочитаемое название
      "var": "fullName",                            // ключ в данных программы
      "cell": "'Общие сведения'!B2",                // (необязательно) конкретная ячейка
      "keywords": "полное наименование организации" // (необязательно) регэксп поиска по колонке A
    }
  ]
}

Порядок применения для каждого поля:
1) если задана cell и ячейка заполнена — берём значение оттуда;
2) иначе ищем строку, где колонка A совпадает с keywords (регэксп),
   и берём значение из колонки value_column.
"""

import os
import re
import sys
import json

# ============================================================
# ПУТЬ К ФАЙЛУ НАСТРОЕК ПО УМОЛЧАНИЮ
# ============================================================
def default_import_settings_path():
    """Путь к файлу настроек: рядом с exe (frozen) или рядом с модулем."""
    if getattr(sys, 'frozen', False):
        base = os.path.dirname(sys.executable)
    else:
        base = os.path.dirname(os.path.abspath(__file__))
    return os.path.join(base, 'import_settings.json')


# ============================================================
# ДЕФОЛТНЫЙ СЛОВАРЬ (используется, если файл не найден)
# ============================================================
def _f(name, var, cell='', keywords=''):
    return {'name': name, 'var': var, 'cell': cell, 'keywords': keywords}


DEFAULT_SETTINGS = {
    'common_sheet_keyword': 'общие',
    'employees_sheet_keyword': 'сотруд',
    'is_sheet_exclude_keywords': ['общие сведения', 'сотрудники'],
    'value_column': 1,
    'fields': [
        _f('Полное наименование организации', 'fullName', keywords=r'полное наименование организации'),
        _f('Сокращённое наименование организации', 'shortName', keywords=r'сокращенное наименование организации'),
        _f('Юридический адрес', 'addressLegal', keywords=r'адрес организации \(юридический\)'),
        _f('Фактический адрес', 'addressActual', keywords=r'адрес организации \(фактический\)'),
        _f('ИНН', 'inn', keywords=r'инн'),
        _f('Дата ОГРН', 'ogrnDate', keywords=r'дата.*огрн'),
        _f('ОГРН', 'ogrn', keywords=r'огрн'),
        _f('КПП', 'kpp', keywords=r'кпп'),
        _f('Основной ОКВЭД', 'okved', keywords=r'основной оквэд'),
        _f('Должность руководителя', 'chiefPosition', keywords=r'должность руководителя'),
        _f('ФИО руководителя', 'chiefFio', keywords=r'фио руководителя'),
        _f('Должность ответственного за ПДн', 'ispdnPosition', keywords=r'должность.*защит.*информ|должность.*администрат'),
        _f('ФИО ответственного за ПДн', 'ispdnFio', keywords=r'фио.*защит.*информ|фио.*администрат'),
        _f('Email ответственного за ПДн', 'ispdnEmail', keywords=r'электронная почта.*защит|электронная почта.*ответств|электронная почта.*специалист'),
        _f('Телефон ответственного за ПДн', 'ispdnPhone', keywords=r'телефон.*защит|телефон.*ответств|телефон.*специалист'),
        _f('Структурное подразделение по безопасности', 'ispdnDepartment', keywords=r'структур.*подраздел'),
        _f('Номер договора', 'contractNumber', keywords=r'номер.*договора|номер.*контракта'),
        _f('Дата договора', 'contractDate', keywords=r'дата.*договора|дата.*контракта'),
        _f('Перечень бумажных документов', 'paperDocuments', keywords=r'названи.*документ'),
        _f('Место хранения документов', 'paperStorage', keywords=r'место.*хранен'),
        _f('Должность ответственного за обработку ПДн', 'responsiblePosition', keywords=r'должность.*ответственн'),
        _f('ФИО ответственного за обработку ПДн', 'responsibleFio', keywords=r'фио.*ответственн'),
        _f('Должность администратора безопасности', 'administratorPosition', keywords=r'должность.*администрат.*(?:безопас|защит|пд)'),
        _f('ФИО администратора безопасности', 'administratorFio', keywords=r'фио.*администрат.*(?:безопас|защит|пд)'),
        _f('Сайт организации', 'site_name', keywords=r'сайт организации'),
        _f('Должность ответственного за сайт', 'site_responsible_position', keywords=r'должность ответственного за сайт|должность.*отв.*сайт'),
        _f('ФИО ответственного за сайт', 'site_responsible_fio', keywords=r'фио.*отв.*сайт|фио.*сайт'),
        _f('Разработчик сайта', 'site_service_provider', keywords=r'наименование организации.*разрабат.*сайт|наименование.*размещала.*сайт|разрабат.*сайт.*организац'),
        _f('ИНН разработчика сайта', 'site_service_provider_inn', keywords=r'инн.*разрабат.*сайт|инн.*размещала.*сайт'),
        _f('Размещение сайта (хостинг)', 'site_hosting', keywords=r'размещение сайта|адрес расположения серверов|адрес.*сервер.*сайт'),
        _f('Адрес хостинга', 'site_hosting_address', keywords=r'адрес.*хостинг|адрес.*располож.*сервер'),
        _f('Электронная почта', 'email', keywords=r'электронная почта'),
        _f('Телефон', 'phone', keywords=r'телефон'),
    ],
}


# ============================================================
# ЗАГРУЗКА НАСТРОЕК
# ============================================================
def load_settings(path=None):
    """Загрузка словаря импорта из JSON-файла.

    path=None  -> файл по умолчанию рядом с программой.
    Если файла нет или он битый — возвращается встроенный дефолт.
    """
    if path is None:
        path = default_import_settings_path()

    if not path or not os.path.exists(path):
        return DEFAULT_SETTINGS

    try:
        with open(path, encoding='utf-8-sig') as f:
            loaded = json.load(f)
        # Дополняем недостающие ключи из дефолта
        merged = dict(DEFAULT_SETTINGS)
        for k, v in loaded.items():
            if k == 'fields' and isinstance(v, list):
                merged['fields'] = v
            else:
                merged[k] = v
        return merged
    except Exception:
        return DEFAULT_SETTINGS


def ensure_default_file(path=None):
    """Создаёт файл настроек import_settings.json, если его ещё нет.

    Возвращает путь к файлу. Нужно, чтобы пользователь видел словарь
    импорта и мог править его в блокноте без пересборки программы.
    """
    if path is None:
        path = default_import_settings_path()
    if os.path.exists(path):
        return path
    try:
        os.makedirs(os.path.dirname(path), exist_ok=True)
        with open(path, 'w', encoding='utf-8') as f:
            json.dump(DEFAULT_SETTINGS, f, ensure_ascii=False, indent=2)
    except Exception:
        pass
    return path


def parse_cell_ref(cell_ref):
    """Разбор ссылки на ячейку: 'Общие сведения'!B2 / Общие сведения!B2 / B2.

    Возвращает (sheet_name или None, координаты 'B2').
    """
    if not cell_ref:
        return None, ''
    ref = cell_ref.strip()
    if ref.startswith('='):
        ref = ref[1:].strip()
    if '!' in ref:
        sheet_part, coord = ref.split('!', 1)
        sheet_part = sheet_part.strip()
        if sheet_part.startswith("'") and sheet_part.endswith("'"):
            sheet_part = sheet_part[1:-1]
        return sheet_part or None, coord.strip().upper()
    return None, ref.upper()


def cell_value(ws, coord):
    """Значение ячейки по координате 'B2' (с нормализацией)."""
    if not coord:
        return ''
    try:
        val = ws[coord]
        return val.value if val is not None else ''
    except Exception:
        return ''
