import attr
from typing import List, Iterable, Union

from django.utils.translation import get_language

from staff.lib import xlsx

'dmirain: тут протекла абстракция и этого импорта тут не должно быть, но так глубоко рефакторить я не готов.'
from staff.headcounts.headcounts_summary import DepartmentCounters


@attr.s(auto_attribs=True)
class Field:
    name_en: str
    name_ru: str
    help_text: str
    data_field_name: str
    column: xlsx.Column

    @property
    def name(self) -> str:
        return self.name_en if get_language() == 'en' else self.name_ru


_without_outline_options = {'level': 0}
_within_outline_options = {'level': 1, 'hidden': True}
_collapsed_options = {'level': 0, 'collapsed': True}


COLUMNS = (
    Field(
        'Name', 'Подразделение', '',
        '',
        xlsx.Column(width=55, options=_collapsed_options),
    ),
    Field(
        'ID', 'ID', '',
        '',
        xlsx.Column(width=8.43, options=_within_outline_options),
    ),
    Field(
        'Hierarchy', 'Иерархия', '',
        '',
        xlsx.Column(width=11, options=_without_outline_options),
    ),
    Field(
        'Limit', 'Потолок', '[1]',
        'total_hc',
        xlsx.Column(width=11, options=_without_outline_options),
    ),
    Field(
        'Actual HC', 'Численность работающих сотрудников', '[2]',
        'current_count',
        xlsx.Column(width=11, options=_without_outline_options),
    ),
    Field(
        'Offer', 'Офферы', '[3]',
        'offers',
        xlsx.Column(width=11, options=_without_outline_options),
    ),
    Field(
        'Balance', 'Баланс', '[1]-[2]-[3]=[4]=\n[5]+[6]+[7]-[8]',
        'current_balance',
        xlsx.Column(width=11, options=_without_outline_options),
    ),
    Field(
        'Opened vacancy', 'Открытые вакансии', '[5]',
        'vacancy_open',
        xlsx.Column(width=11, options=_without_outline_options),
    ),
    Field(
        'Unassigned headcount', 'Незанятый хедкаунт', '[6]',
        'vacancy_plan',
        xlsx.Column(width=11, options=_collapsed_options),
    ),
    Field(
        'Unassigned new headcount', 'Незанятый хедкаунт новый', '[6.1]',
        'vacancy_plan_new',
        xlsx.Column(width=11, options=_within_outline_options),
    ),
    Field(
        'Unassigned replacement headcount', 'Незанятый хедкаунт на замену уволенным', '[6.2]',
        'vacancy_plan_replacement',
        xlsx.Column(width=11, options=_within_outline_options),
    ),
    Field(
        'Credit', 'Кредит', '[7]',
        'reserve_new',
        xlsx.Column(width=11, options=_without_outline_options),
    ),
    Field(
        'Crossheadcount', 'Пересечения', '[8]',
        'crossheadcount',
        xlsx.Column(width=11, options=_collapsed_options),
    ),
    Field(
        'Сrossing with the working', 'Пересечения с работающими', '[8.1]',
        'replacement_to_working',
        xlsx.Column(width=11, options=_within_outline_options),
    ),
    Field(
        'Сrossing with the offers', 'Пересечения с офферами', '[8.2]',
        'offers_for_working_replacement',
        xlsx.Column(width=11, options=_within_outline_options),
    ),
    Field(
        'Сrossing with the vacancies', 'Пересечения с вакансиями', '[8.3]',
        'vacancy_open_for_working_replacement',
        xlsx.Column(width=11, options=_within_outline_options),
    ),
    Field(
        'Сrossing with the unassigned headcount', 'Пересечения с незанятым хедкаутом', '[8.4]',
        'vacancy_plan_for_working_replacement',
        xlsx.Column(width=11, options=_within_outline_options),
    ),
)


class SummaryModel(object):
    def __init__(self, departments, summary_data):
        self.departments = departments
        self.summary_data = summary_data

    def __iter__(self):
        for department in self.departments:
            yield department, attr.asdict(self.summary_data.get(department['id'], DepartmentCounters()))


class DepartmentsSummarySheetPresenter(xlsx.SheetPresenter):
    outline_settings = {'symbols_below': 0, 'symbols_right': 0}
    freeze_panes = {'row': 2, 'col': 1}

    _heading_format = {
        'align': 'center',
        'valign': 'vcenter',
        'text_wrap': True,
        'bold': True,
        'bg_color': '#FFCC00',
    }

    _help_heading_format = {
        'align': 'center',
        'valign': 'vcenter',
        'text_wrap': True,
        'bold': True,
        'font_color': '#808080',
    }

    _gray_row_format = {
        'font_color': '#D3D3D3',
    }

    def columns(self) -> Iterable[xlsx.Column]:
        return (f.column for f in COLUMNS)

    def help_row(self) -> xlsx.ViewRow:
        return xlsx.ViewRow(
            xlsx.ViewCell(field.help_text, self._help_heading_format)
            for field in COLUMNS
        )

    def column_caption_row(self) -> xlsx.ViewRow:
        return xlsx.ViewRow(
            xlsx.ViewCell(field.name, self._heading_format)
            for field in COLUMNS
        )

    def _row_options_for_department(self, first_department_level: int, department_data: dict) -> dict:
        row_level = department_data['level'] - first_department_level
        row_level = min(row_level, 7)
        row_options = {'level': row_level, 'hidden': row_level > 1, 'collapsed': row_level > 1}
        return row_options

    def _row_data(self, department_data: dict, fields_data: dict) -> List[Union[str, int]]:
        row_data = [
            department_data['name'],
            department_data['id'],
            ' → '.join(dep['name'] for dep in department_data['chain']),
        ]
        for field in COLUMNS:
            if field.data_field_name:
                row_data.append(fields_data.get(field.data_field_name, 0))
        return row_data

    def rows(self) -> Iterable[xlsx.ViewRow]:
        yield self.help_row()
        yield self.column_caption_row()

        first_department_level = None

        for department_data, fields_data in self._model:
            if not first_department_level:
                first_department_level = department_data['level']

            row_data = self._row_data(department_data, fields_data)
            row_options = self._row_options_for_department(first_department_level, department_data)
            row_format = None if department_data['intranet_status'] else self._gray_row_format

            yield xlsx.ViewRow(
                cells=xlsx.SheetPresenter.default_view_cells_from_row_data(row_data),
                options=row_options,
                row_format=row_format,
            )
